读书笔记之代理技术

    代理(Proxy),通俗的讲就是找个人帮你去处理事务。它又分为静态代理和动态代理。下面将举例进行说明,存在一个Hello接口

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

和其实现类

public class HelloImpl implements Hello {
    @Override
    public void say(String name) {
    System.out.println("Hello," + name + "!");
    }
}

现在我们需要在say方法的前后分别处理一些逻辑,这时我们考虑用到代理模式。如果不使用代理模式,则会将前后逻辑写死在代码中,不利于日后代码的维护和修改,就会如下所示

public class HelloImpl implements Hello {
    @Override
    public void say(String name) {
        before();
        System.out.pringln("Hello," + name + "!");
        after();
    }

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

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


    静态代理的做法:

    写一个代理类,并通过它去调用HelloImpl的say方法,同时在其前后完成逻辑处理,具体代码如下

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 static void main() {
    Hello helloProxy = new HelloProxy();
    helloProxy.say("Tom");
}

这样做也会存在问题,问题在于随着日后代码的增多,类似XxxProxy的代理类就会越来越多...


基于JDK动态代理的做法:

public class DynamicProxy implements InvocationHandler {

    private Object target;

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

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

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

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

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

在这是定义了一个target变量,通过它来实现被代理的目标对象,下面是对应的main方法

public static void main(String[] args) {
    DynamicProxy dynamicProxy = new DynamicProxy(new HelloImpl());
    Hello helloProxy = dynamicProxy.getProxy();

    helloProxy.say("Jerry");
}

从上可以看到main方法通过DynamicProxy类去包装HelloImpl实例,并利用自身的getProxy方法动态的创建一个Hello接口,最后调用这个代理类的say方法。单基于JDK动态代理的做法也是存在问题的,即它只能代理接口,而不能代理没有接口的类。


基于CGlib动态代理的做法:

public class CGLibProxy implements MethodInterceptor {
    private static CGLibProxy instance = new CGLibProxy();

    private CGLibProxy() {

    }

    public static CGLibProxy getInstance() {
        return instance;
    }

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

    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        before();
        Object result = proxy.invokeSuper(obj, args);
        after();
        return result;
    } 

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

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

对应的main方法可以描述为

public static void main(String[] args) {
    Hello helloProxy = cgLibProxy.getInstance().getProxy(HelloImpl.class);
    helloProxy.say("Jack");
}

从而我们可以看到基于CGLib动态代理既可以有接口的代理,又可以实现没有接口的代理,这样也就弥补了JDK的不足。



    

猜你喜欢

转载自blog.csdn.net/sinat_33010325/article/details/80216621