参考三、springboot2.x默认使用的代理是cglib代理
一 、什么是代理模式?
代理模式就是为其他对象提供一个代理对象,并由代理对象来控制这个对象的访问。通俗来说就是我们生活中所说的中介。
二、代理模式中最主要的角色都有哪些?
真实角色:业务逻辑的具体执行者,代理角色代理的对象。
代理角色:代理角色内部含有真实角色的引用,负责对真实角色的调用,在并在真实角色执行业务逻辑前后进行预处理和善后处理。
三、代理模式有什么优点?
1、职责清晰:真实的角色只需要关注业务逻辑的实现,非业务逻辑的部分,后期通过代理角色即可实现。
2、增强功能。开闭原则中规定 软件的对象对于扩展是开放的,但是对于修改是封闭的。可以通过代理角色来扩展真实角色的功能,这样只需要修改代理角色,不需要修改真实角色,符合代码设计的开闭原则。代理角色主要负责为真实角色处理消息,过滤消息,然后把消息转发给被真实角色,真实角色处理完业务逻辑之后,代理角色对返回的结果进行处理。代理角色本身并不处理业务逻辑,真正的业务逻辑处理是真实角色实现的。
3、中介隔离作用
在某些情况下,真实角色没有办法被直接引用或者不想直接引用真实角色,代理角色就可以在真实角色和调用者之间起到中介的作用,但是代理角色和和真实角色应该实现相同的接口。
四、代理模式的种类有哪些?
代理模式可分为 静态代理+动态代理,其中动态代理又可分为 JDK的动态代理和CGLIB的动态代理。
五、动态代理比较静态代理,有哪些优点?也就是说,静态代理有哪些缺点?
1、静态代理增加了 维护代码的复杂度,动态代理减少了大量的重复代码,便于代码的维护。因为静态代理中,真实角色和代理角色实现了相同的接口,如果接口中新增一个方法,那么真实角色和代理角色都要实现这个新增的方法,这样会出现大量重复的代码,代码的维护复杂度会增加!
2、静态代理的代理角色只能代理一种类型的真实角色,如果要对多种类型的真实角色进行代理,就需要多个代理角色,如果程序的规模比较大,那么代理角色就会非常多,静态代理这种情况是没有办法胜任的。
六、JDK的动态代理和CGLIB的动态代理有什么区别?各自的实现的原理是什么?
JDK动态代理:
JDK动态代理实现 InvocationHandler,利用拦截器和反射机制生成 代理接口 的匿名类,在调用具体方法前调用invokeHander来处理;
JDK动态代理中,所有被代理的类必须实现接口,也就是说代理的方法只能是接口中定义的方法,对于真实对象中,如果不是实现接口的方法,是真实对象自己内部方法,则无法被代理,有一定的局限性。
CGLIB动态代理
CGLIB 是针对类实现代理,cglib底层是用ASM框架(字节码操作框架),使用字节码技术生成代理类,主要是对于一个指定的类 生成其子类,覆盖其中的方法,并对覆盖的方法进行增强。CGLIB动态代理生成子类时采用方法拦截技术拦截所有父类方法的调用,顺势织入横切逻辑。 因为代理的时候生成子类,所以被代理的类或者方法最好不要用final修饰,对于final修饰的类或方法,是没有办法继承的。
七、Spring中aop是如何使用代理模式的?
当Bean实现接口时,默认用JDK动态代理,强制情况下可以使用CGLIB动态代理;
当Bean没有 实现接口,只能使用CGLIB动态代理
八、Spring中怎么强制使用CGLIB动态代理?
spring.aop.proxy-target-class=true
springboot2.x 之后默认就是使用的CGLIB动态代理。
springboot团队之所以默认的代理模式设置成cglib代理,看看spring的官方团队是怎么解释的
This was changed in 1.4 (see 5423). We’ve generally found cglib proxies less likely to cause unexpected cast exceptions.
他们认为使用cglib更不容易出现转换错误。springboot 默认的配置文件的位置在
/org/springframework/boot/spring-boot-autoconfigure/2.1.7.RELEASE/spring-boot-autoconfigure-2.1.7.RELEASE.jar!/META-INF/spring-configuration-metadata.json
{
"name": "spring.aop.proxy-target-class",
"type": "java.lang.Boolean",
"description": "Whether subclass-based (CGLIB) proxies are to be created (true), as opposed to standard Java interface-based proxies (false).",
"defaultValue": true
},