代理
代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理
预处理例子:spring aop的before,after,arround,exception处理。
代理的静态实现逻辑
-
基于接口的代理
public class MgtInstance implements MgtInterface{ public void dosth(){...} } public class MgtProxy implements MgtInterface { private MgtInterface mgt; //。。。注入mgtInstance @Override public void dosth(){ try{ //...before mgt.dosth... //...after }catch(){ //exception }final{ } } }
-
基于继承的代理
public class MgtInstance implements MgtInterface{ public void dosth(){...} } public class MgtProxy extends MgtInstance implements MgtInterface { @Override public void dosth(){ try{ //...before super.dosth(); //...after }catch(){ //exception }final{ } } }
代理实现的两大常用组件
上述是静态实现,动态代理使用反射,可以解耦实际操作(userDao.dosth)与 其他委托处理信息(before,after,arround, exception),
- jdk动态代理底层源码及原理
https://blog.csdn.net/weixin_37961431/article/details/108182253
主要涉及类
invocationhandle接口;Proxy,proxyGenerator;接口;实现类
proxyGenerator生成代理类字节流,生成class;此class是继承proxy,实现接口;依赖handle实现类作为成员变量,
// 查看jdk动态代理的源代码
byte[] bytes= ProxyGenerator.generateProxyClass("$Proxy0",new Class[] {UserDao.class});
try {
FileOutputStream fs = new FileOutputStream(new File("D:\\$Proxy0.class"));
fs.write(bytes);
} catch (Exception e) {
e.printStackTrace();
}
符合设计六大原则的开闭原则:对拓展开放,对修改关闭
-
cglib动态代理底层源码及原理
https://jpeony.blog.csdn.net/article/details/80633194
https://zhuanlan.zhihu.com/p/92019070主要涉及类:MethodInterceptor接口;enchance,methodProxy,fastClass
public static void main(String[] args) { // 代理类class文件存入本地磁盘方便我们反编译查看源码 System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\code"); // 通过CGLIB动态代理获取代理对象的过程 Enhancer enhancer = new Enhancer(); // 设置enhancer对象的父类 enhancer.setSuperclass(HelloService.class); // 设置enhancer的回调对象 enhancer.setCallback(new MyMethodInterceptor()); // 创建代理对象 HelloService proxy= (HelloService)enhancer.create(); // 通过代理对象调用目标方法 proxy.sayHello(); }
符合设计六大原则的里氏替换原则:对子类可以扩展父类的功能,但不能改变父类原有的功能
-
两者区别
- JDK动态代理是实现了被代理对象的接口,Cglib是继承了被代理对象。
- JDK和Cglib都是在运行期生成字节码,JDK是直接写Class字节码,Cglib使用ASM框架写Class字节码,Cglib代理实现更复杂,生成代理类比JDK效率低。
- JDK调用代理方法,是通过反射机制调用,Cglib是通过FastClass机制直接调用方法,Cglib执行效率更高。