参考:https://segmentfault.com/a/1190000011291179
代理主要的作用是是在一个方法使用前后,能进行别的处理,比如:日志相关
静态代理
代理方式:代理对象和目标对象都需要实现相同的接口类
1.定义接口UserService(接口类)
2.定义接口的实现类UserServiceImpl(目标对象)
3.定义代理类UserProxy(代理对象):与目标对象实现同一接口,UserProxy代替UserServiceImpl实现功能
4.编写测试类运行
优点:可以在不修改目标对象的情况下拓展目标对象的新功能
缺点:1.如果有很多类需要代理类,那就需要写很多代理类。2.接口类新增功能,那么代理对象和目标对象都要进行修改
动态代理:JDK代理
代理方式:利用java.lang.reflect.Proxy为目标对象生成动态代理
特点:动态代理对象不需要实现接口,但是目标对象必须要实现接口,否则无法使用动态代理
1.定义接口UserService(接口类)
2. 定义接口的实现类UserServiceImpl(目标对象)
3.定义动态代理类
4.编写测试类运行
结论:动态代理类:class com.sun.proxy.$Proxy0代理目标对象:cn.com.swanclouds.service.UserServiceImpl@548c4f57执行了save()方法
为什么jdk动态代理必须基于接口
1.生成的代理类继承了Proxy,由于java是单继承,所以只能实现接口,通过接口实现
2.从代理模式的设计来说,充分利用了java的多态特性,也符合基于接口编码的规范
动态代理:cglib代理
cglib(code generation library)第三方代码生成类库,针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的所有方法,所以该类或方法不能声明称final的。CGLIB底层使用字节码处理框架ASM,来转换字节码并生成新的类。
代理方式:运行时为目标对象生成一个子类从而实现目标对象的功能
特点:无论目标对象是否实现接口,都可以代理
1.定义目标对象Class
2.定义动态代理类
3. 编写测试类运行
结论:运行时动态代理类UserProxy利用Enhancer替UserService生成了一个子类,在intercept方法中通过子类去真正调用save()方法。
也就是说,如果有人问到使用CGLIB代理,真正调用方法的是谁,那么答案就是Enhancer生成的目标对象的子类,名称格式为:
JDK动态代理与CGLIB动态代理区别:
- JDK代理必须要求目标对象实现接口
- CGLIB代理不管目标对象是否实现接口,都可以代理,达到代理类无入侵
动态代理与静态代理的区别:
1.静态代理在编译时就已经实现,编译后是代理类是一个实际的class文件
2.动态代理是在运行时生成的,编译后没有实际的class文件,而是在运行时生成类字节码,加载到JVM中