代理模式之动态代理

动态代理模式

什么是动态代理模式?

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

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方法中的逻辑有时还是需要修改。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值