【设计模式】【结构型7-1】【代理模式】【动态代理】【静态代理】

文章目录

代理模式

代理 是结构型 通过继承,或者实现相同的接口来进行增强和监控

经典的使用 spring aop,mybatis dao层

静态代理

作用:可以增加功能 而不破坏现有代码结构,一定程度的解耦

第一步 创建接口

java 复制代码
/***
 * 卖房子
 */
public interface Sell {
    void sellHouse();
}

第二步 创建需要代理的对象

java 复制代码
public class PersonSell implements Sell{
    @Override
    public void sellHouse() {
        System.out.println("我卖房子---");
    }
}

第三步 创建代理对象 使用

java 复制代码
public class ProxySell implements Sell{
    private Sell sell;
    public ProxySell(Sell sell) {
        this.sell = sell;
    }
    @Override
    public void sellHouse() {
        System.out.println("中介联系人");
        sell.sellHouse();
        System.out.println("中介促成交易");
    }
}

    public static void main(String[] args) {
        PersonSell personSell = new PersonSell();
        ProxySell proxySell = new ProxySell(personSell);
        proxySell.sellHouse();
    }

可以看到 调用代理人方法 最终代理人服务被代理的对象 进行了前后包夹 无死角环绕

动态代理

jdk动态代理

  1. Interface:对于 JDK 动态代理,目标类需要实现一个 Interface。
  2. InvocationHandler:InvocationHandler 是一个接口,可以通过实现这个接口,定义横切逻辑,再通过反射机制(invoke)调用目标类的代码,在次过程,可能包装逻辑,对目标方法进行前置后置处理。
  3. Proxy:Proxy 利用 InvocationHandler 动态创建一个符合目标类实现的接口的实例,生成目标类的代理对象。
java 复制代码
return Proxy.newProxyInstance(sourceObject.getClass().getClassLoader(), sourceObject.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("-----------我开始代理啦------------");
                method.invoke(sourceObject, args);
                return proxy;
            }
        });
其实整个核心就是这样的 使用Proxy.newProxyInstance 传入类加载器 传入接口 新创建一个处理器 执行 method.invoke 方法 并返回代理对象

展开一下

java 复制代码
public interface Sell2 {
    void sellHouse();
}

public class PersonSell implements Sell2 {
    @Override
    public void sellHouse() {
        System.out.println("我卖房子---");
    }
}

public class DynamicSellProxy {
	//这里就两步 1:用Proxy newProxyInstance 创建一个代理类 用 InvocationHandler 来执行 target的方法
    public Object proxy(Object target){
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("----动态代理前置----");
                method.invoke(target,args);
                System.out.println("----动态代理后置----");
                return proxy;
            }
        });
    }
}
//测试
 public static void main(String[] args) {
        ((Sell2) new DynamicSellProxy().proxy(new PersonSell())).sellHouse();
    }

cjlib动态代理

  1. 使用 JDK 创建代理有一大限制,它只能为接口创建代理实例,而 CgLib 动态代理就没有这个限制。
  2. CgLib 动态代理是使用字节码处理框架 ASM,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。
  3. CgLib 创建的动态代理对象性能比 JDK 创建的动态代理对象的性能高不少,但是 CGLib 在创建代理对象时所花费的时间却比 JDK 多得多,所以对于单例的对象,因为无需频繁创建对象,用 CGLib 合适,反之,使用 JDK 方式要更为合适一些。同时,由于 CGLib 由于是采用动态创建子类的方法,对于 final 方法,无法进行代理
java 复制代码
public class CGLIBSellProxy {

    public Object getProxy(Object target){
        Enhancer enhancer = new Enhancer();
        //设置被代理的class
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                System.out.println("--------cjlib 动态代理前置-------");
                methodProxy.invokeSuper(o, objects);
                System.out.println("------cjlib 动态代理后置---------");
                return o;
            }
        });
        return enhancer.create();
    }
}

((PersonSell) (new CGLIBSellProxy().getProxy(new PersonSell()))).sellHouse();
相关推荐
杨充8 小时前
10.可测试性实战设计
设计模式·开源·代码规范
杨充8 小时前
9.重构十二式的实战
设计模式·开源·代码规范
杨充9 小时前
6.设计原则的全景图
设计模式·开源·全栈
杨充9 小时前
2.面向对象的特性
设计模式
杨充9 小时前
7.SOLID原则案例汇
设计模式·开源·全栈
杨充9 小时前
8.反模式与坏味道
设计模式·开源·代码规范
杨充9 小时前
3.接口vs抽象类比较
设计模式
咖啡八杯12 小时前
文法、BNF与AST
java·设计模式·解释器模式·ast·文法
咖啡八杯20 小时前
GoF设计模式——解释器模式
java·后端·spring·设计模式