1.代理模式是什么?
定义:为对象A提供一个代理对象,由代理对象控制对象A的引用。
在某些情况下,一个对象B不适合或不能直接引用对象A,那么代理对象就可以在A和B之间起到中介作用。
组成:
抽象角色:通过接口或抽象类声明真实角色实现的业务方法。
代理角色:实现抽象角色,是真正的代理对象,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。
真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。
种类:静态代理、动态代理(jdk,cglib,spring和aspectj)
静态代理:由我们自己定义代理类
动态代理:由程序自动生成代理类(用的更多)
生活中的例子:房屋中介,黄牛,媒人,经济人等。
周杰伦需要开演唱会,他只需要负责唱歌,而其他的面谈,签合同,订票,收钱都由代理角色来处理。
特点:1.执行者、被代理人
对于被代理人,这件事情一定要做,但是自己不想做或者没时间做,找代理做
对于执行者,需要获取到代理人的个人资料
2.为什么要使用代理模式
中介隔离:客户类不想或者不能直接引用委托对象,那么代理类就可以起到中介作用。
开闭原则:在增加额外的功能时,只需要给代理类增加额外功能,而不去修改委托类。例如:加缓存、日志等功能。
3.怎么使用代理模式
3.1 静态代理(需要自己定义代理类)
使用周杰伦唱歌的案例
抽象角色:抽象出真实角色的业务
真实角色,周杰伦开演唱会需要做的所有事情
代理角色,实现抽象角色的方法,可以代替真实角色去做事情
测试:
控制台输出:
可以看出,我们只需要拿到真实对象的资料,即真实资料的引用,就可以使用代理对象来操作实现方法。
3.2 动态代理(程序动态生成代理类)
3.2.1 JDK自带的动态代理 java.lang.reflect.Proxy;
结构
抽象接口
真实对象
处理器接口: java.lang.reflect.InvocationHandler 处理器接口
通过invoke实现对真实角色的代理访问
测试
控制台输出
可以看出,jdk自带的动态代理需要实现InvocationHandler,重写invoke方法,来对方法进行修改或增强,创建代理对象用Proxy.newProxyInstance.
3.2.2 cglib实现的动态代理(代理对象没有实现抽象角色接口)
引入依赖
<dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.1</version> </dependency>
真实角色
创建代理对象的工厂
测试
所以cglib和jdk自带的动态代理的区别为:
如果目标对象有接口,优先使用jdk动态代理
如果目标对象无接口,使用cglib动态代理
spring就是这样实现的。
归根结底:字节码重组,可以在一个方法调用前和调用后加一些代码。