设计模式-代理模式

一、代理模式 - 静态代理

代理模式本质是为了对原有逻辑的增强。
静态代理如下:

  1. 代理类和被代理类实现相同接口
  2. 在代理类中注入被代理类作为属性,在代理类中的方法调用被代理类的方法,就可在不修改被代理类的前提下对代码功能增强。

案例:

interface UserManager {
    void add(String name,int age);
    void find(String name);
}
//被代理类
public class UserManagerImpl implements UserManager{
    @Override
    public void add(String name, int age) {
        System.out.println("UserManagerImpl.add()");
    }
    @Override
    public void find(String name) {
        System.out.println("UserManagerImpl.find()");
    }
}
//代理类
public class UserManagerImplProxy implements UserManager {
    //将被代理类设置为属性
    private UserManagerImpl userManagerImpl;
    //初始化被代理类
    public UserManagerImplProxy(UserManagerImpl userManagerImpl){
        this.userManagerImpl = userManagerImpl;
    }
    @Override //对代码增强
    public void add(String name, int age) {
        System.out.println("日志记录开始....");
        userManagerImpl.add(name,age);
        System.out.println("日志记录结束....");
    }
    @Override //对代码增强
    public void find(String name) {
        System.out.println("日志记录开始....");
        userManagerImpl.find(name);
        System.out.println("日志记录结束....");
    }
}
//测试代码:
UserManager usermanager = new UserManagerImplProxy(new UserManagerImpl());
usermanager.add("张三",20);

二、代理模式 - 动态代理 - JDK代理 - 基于接口实现

通过java提供的java.lang.reflect.Proxy来动态生成代理类,从而简化代码。

public class TestProxy{
    UserManagerImpl ui = new UserManagerImpl();
    @Test
    public void test01(){
        // object:生成的代理实例
        Object object = Proxy.newProxyInstance(
                UserManagerImpl.class.getClassLoader(), //被代理着的类加载器
                UserManagerImpl.class.getInterfaces(),  //被代理者的接口有哪些
                new InvocationHandler() {  //调用处理程序接口,由代理实例来回调
                    /**
                     * 代理实例在调用目标方法时,最终执行该方法
                     * @param proxy    代理实例本身
                     * @param method   被代理者的目标方法对象
                     * @param args     被代理者的目标方法参数
                     */
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("日志记录开始....");
                        Object result  = method.invoke(ui,args);
                        System.out.println("日志记录结束....");
                        return result; //result:目标方法的返回值
                    }
                }
        );
        UserManager um = (UserManager) object;
        um.add("测试1",11);
        um.find("测试2");
    }
}

这种方式我们称之为JDK代理,缺点是如果被代理者有自我拓展的方法(不是来自于接口的),那么代理后是无法调用这些方法的。必须保证,代理者和被代理者实现统一的接口,代理后只能调用接口中已有的方法。

三、代理模式 - 动态代理 - CGLIB代理 - 基于继承实现(代理者是被代理者的子类 )

由于cglib动态代理不是jdk提供,但是spring-core中已经集成了,所以不需要额外导包。

public class TestCGLIBProxy {
    UserManagerImpl umi = new UserManagerImpl();
    @Test
    public void test01(){
        //1.创建增强器对象
        Enhancer enhancer = new Enhancer();
        //2.设置接口(不是必须)
        enhancer.setInterfaces(umi.getClass().getInterfaces());
        //3.设置代理者的父类
        enhancer.setSuperclass(umi.getClass());
        //4.设置回调
        enhancer.setCallback(new MethodInterceptor() {
            /**
             * @param o        代理者
             * @param method   正在调用的方法
             * @param objects  正在调用的方法参数
             * @param methodProxy  方法代理对象
             */
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                System.out.println("记录日志前...");
                Object result = method.invoke(umi, objects);
                System.out.println("记录日志后...");
                return result;
            }
        });
        //5.创建代理对象
        Object obj = enhancer.create();
        //6.调用
        UserManagerImpl proxy = (UserManagerImpl)obj;
        proxy.find("x");
    }
}

好处是:因为是继承关系(父类:被代理者,子类:代理者),所以被代理者自我拓展的方法也可以被代理者调用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值