什么是代理与不同代理的区别。

 

 

简单来说就是你不用去做,别人代替你去处理。

 

废话不多说直接代码演示。

举个简单的例子:

 

public interface Hello {
    void say(String name);
}

 

实现类:

public class HelloImpl implements Hello {
    public void say(String name) {
        System.out.println("hello" + name);
    }
}
 
 
 
代理模式:
 
public class HelloProxy implements Hello {

    private Hello hello;

    public HelloProxy(){
        hello = new HelloImpl();
    }


    @Override
    public void say(String name) {
        before();
        hello.say(name);
        after();
    }


    private void before(){
        System.out.println("Before");
    }

    private void after(){
        System.out.println("After");
    }
}
 
在main方法中测试:
 
public class Main {

    public  static void main(String[] args){

        Hello helloProxy = new HelloProxy();

        helloProxy.say("Mc");
    }
}

 

可以得到:
 

Before

helloMc

After

 

这就是所谓的代理模式。

 
 
 

上述代理代码中在main中测试时可以发现,这样的代理,是静态的,需要每次都去写一个XXXProxy类去使用。

为了解决这个问题就衍生出了:
JDK动态代理
 
public class DynamicProxy implements InvocationHandler {


    private Object target;

    public DynamicProxy(Object target){
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        target = method.invoke(target,args);
        after();
        return null;
    }

    private void before(){
        System.out.println("Before");
    }

    private void after(){
        System.out.println("After");
    }
}

这是JDK提供的动态代理方案,写一个类继承InvocationHandler.

使用的时候:
 
public  static void main(String[] args){

    Hello hello  = new HelloImpl();

    DynamicProxy dynamicProxy = new DynamicProxy(hello );

    Hello helloProxy = (Hello) Proxy.newProxyInstance(
            hello.getClass().getClassLoader(),
            hello.getClass().getInterfaces(),
            dynamicProxy);

    helloProxy.say("Mc");


}

意思就是使用DynamicProxy类去包装HelloImpl示例,然后再调用JDK给我们提供的Proxy类的工厂方法去动态创建一个Hello接口的代理类。

避免倒是都是
Proxy.newProxyInstance

可以重构一下:

写出:
 
public class DynamicProxy implements InvocationHandler {


    private Object target;

    public DynamicProxy(Object target) {
        this.target = target;

    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        target = method.invoke(target, args);
        after();
        return null;
    }

    private void before() {
        System.out.println("Before");
    }

    private void after() {
        System.out.println("After");
    }



    public <T> T getProxy() {
        return (T) Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                this);
    }

}

添加一个getProxy方法。

这样使用的时候就简便多了:
 
public  static void main(String[] args){

    Hello hello  = new HelloImpl();

    DynamicProxy dynamicProxy = new DynamicProxy(hello );

    Hello helloProxy = dynamicProxy.getProxy();

    helloProxy.say("Mc");

}

这样使用的时候直接填写实现类即可使用代理。

 
CGlib动态代理
DynamicProxy非常不错,接口变了,动态代理类无需改变。而静态代理类则不同,接口变了,实现了要变,动态代理类也需要变。
但是DynamicProxy 也有不好的时候,比如要代理一个没有任何接口的类,他就不可以。
因此我们又发现了CGlib这个类库。
 
public class CGLibProxy implements MethodInterceptor {



    public <T> T getProxy(Class<T> cls){
        return (T) Enhancer.create(cls,this);
    }

    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {

        before();
        o = methodProxy.invokeSuper(o,objects);
        after();
        return o;
    }


    private void before() {
        System.out.println("Before");
    }

    private void after() {
        System.out.println("After");
    }
}
CGLib给我们提供的是方法级别的代理,也可以理解为对方法的拦截(就是方法拦截器吧)。

使用的时候:

 
public  static void main(String[] args){

   CGLibProxy cgLibProxy = new CGLibProxy();
   Hello helloProxy = cgLibProxy.getProxy(HelloImpl.class);
   helloProxy.say("Mc");


}

还可以再优化,将CGLibProxy写成单例模式,不用每次都new一个。

 
private static CGLibProxy cgLibProxy;

public static synchronized CGLibProxy getCgLibProxy() {
    if (cgLibProxy == null) {
        synchronized (CGLibProxy.class) {
            cgLibProxy = new CGLibProxy();
        }
    }
    return cgLibProxy;
}

这样只需要一行代码就完成测试。

 
Hello helloProxy = CGLibProxy.getCgLibProxy().getProxy(HelloImpl.class);
helloProxy.say("MC");

 

 
 
 
 
 
 
 

 

 
 
 
 
 
 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值