代理模式之动态代理

来源:互联网 发布:传奇变速源码 编辑:程序博客网 时间:2024/06/04 00:22

动态代理模式

什么是动态代理模式?

动态代理模式就是对不同的目标类,能通过一个代理类来完成指定的切入操作。而不需要针对新增的目标类重新设计代理类。

Java如何实现动态代理?

还是拿静态代理所用的例子

JDK动态代理

这里只给出代理类和测试类的代码,其他代码与静态代理中的相同。
代理类:DocumentManagerProxy_JDK.java

package com.proxypattern;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;/** * @author zdxie * @Date 上午 9:16 2017/9/6  * @Description 实现InvocationHandler接口,编写invoke方法。所有工作都在invoke方法中完成。 */public class DocumentManagerProxy_JDK implements InvocationHandler{    private Logger logger;    private Privilege privilege;    private Object target;    public DocumentManagerProxy_JDK(Logger logger, Privilege privilege, Object target) {        this.logger = logger;        this.privilege = privilege;        this.target = target;    }    //所有工作都在invoke方法中完成    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        if (this.privilege.getKey().equals("root")){            this.logger.writeLog("权限验证通过!");            //调用目标方法            method.invoke(this.target,args);            this.logger.writeLog("操作成功!");        }else{            System.out.println("Error:没有权限,操作失败!");            this.logger.writeLog("没有权限,操作失败");        }        return null;    }}

测试方法:

public void testDocument_JDK(){        DocumentManager manager = new DocumentManagerImpl();        Logger logger = new Logger();        Privilege privilege = new Privilege();        privilege.setKey("root");        DocumentManagerProxy_JDK proxy_jdk = new DocumentManagerProxy_JDK(logger,privilege,manager);        //获取代理对象实例        DocumentManager manager_1 = (DocumentManager) Proxy.newProxyInstance(manager.getClass().getClassLoader(),                manager.getClass().getInterfaces(),proxy_jdk);        //在代理对象调用方法的时候,进入了拦截器(代理对象)中的invoke方法        //执行的内容就是拦截器中的invoke方法体的内容        manager_1.readDocument();        manager_1.writeDocument();    }

cglib实现动态代理

代理类:

package com.proxypattern;import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;/** * @author zdxie * @Date 下午 2:45 2017/9/6 0006 * @Description 实现cglib提供的MethodInterceptor接口,重写intercept方法, *              并提供创建代理类的方法createProxy */public class DocumentManagerProxy_cglib implements MethodInterceptor{    private Object target;    private Privilege privilege;    private Logger logger;    public DocumentManagerProxy_cglib(Object target, Privilege privilege, Logger logger) {        this.target = target;        this.privilege = privilege;        this.logger = logger;    }    public Object createProxy(){        Enhancer enhancer = new Enhancer();        //拦截器对象        enhancer.setCallback(this);        //设置代理类的父类为目标类        enhancer.setSuperclass(target.getClass());        return enhancer.create();    }    @Override    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {        if (this.privilege.getKey().equals("root")){            this.logger.writeLog("权限验证通过!");            method.invoke(this.target,objects);            this.logger.writeLog("读取成功!");        }else{            System.out.println("Error:没有权限,读取失败!");            this.logger.writeLog("没有权限,读取失败");        }        return null;    }}

测试方法:

    @Test    public void testDocument_JDK(){        DocumentManager manager = new DocumentManagerImpl();        Logger logger = new Logger();        Privilege privilege = new Privilege();        privilege.setKey("root");        DocumentManagerProxy_JDK proxy_jdk = new DocumentManagerProxy_JDK(logger,privilege,manager);        //获取代理对象实例        DocumentManager manager_1 = (DocumentManager) Proxy.newProxyInstance(manager.getClass().getClassLoader(),                manager.getClass().getInterfaces(),proxy_jdk);        manager_1.readDocument();        manager_1.writeDocument();    }

动态代理的优缺点

优点:
1. 能完成对目标类的各种切入操作。
2. 实现了代替目标类完成工作。
3. 分离了目标类和切入类,将工作完全松耦合。
4. 用反射调用目标方法,目标方法变动无需修改代理方法。
5. 没有针对性,新增目标类只需在创建代理对象时传入目标类即可,不用新增代理类。

缺点:
1. 还是需要手动编写拦截器(代理),invoke方法中的逻辑有时还是需要修改。