前言
在上一篇文章中讲到了Spring是如何获取对应的Bean的增强,然后本次主要讲解一下Spring如何在获取到增强后创建Spring代理的。
在步入正题之前先给大家看一下Spring创建代理的大致流程图
接下来我们就回到AbstractAutoProxyCreator.class
类中的wrapIfNecessary
方法。
- 看源码(
AbstractAutoProxyCreator.class
)
1 | kotlin复制代码protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { |
在上一篇Spring源码之创建AOP代理之增强器的获取文章中,主要是围绕着getAdvicesAndAdvisorsForBean
方法展开的,主要是获取到了所有对应Bean的增强器,并获取到了此目标Bean所匹配的Advisor,
接下来我们着手对接下来的方法createProxy
进行分析,
- 看源码(
AbstractAutoProxyCreator.class
)
1 | scss复制代码protected Object createProxy(Class<?> beanClass, @Nullable String beanName, |
- 源码分析
上述代码中的ProxyFactory proxyFactory = new ProxyFactory();
新建了一个工厂类,并且往后看,明显的看出对于代理类的创建Spring是委托给了ProxyFactory
处理的。
接下来继续跟踪源码proxyFactory.getProxy(classLoader);
该方法创建了代理对象。
- 看源码(
Proxyfactory.java
)
1 | less复制代码public Object getProxy(@Nullable ClassLoader classLoader) { |
- 源码分析
通过上述注释可以感觉到终于要来到了主题,到底是如何决定使用哪种代理方式的。首先我们看到getProxy
方法中的createAopProxy
方法,它的默认实现其实是在DefaultAopProxyFactory
类中。这中间它经过了ProxyCreatorSupport
类的createAopProxy
方法。
- 看源码(
ProxyCreatorSupport.java
)
1 | kotlin复制代码protected final synchronized AopProxy createAopProxy() { |
紧接着我们直接来到具体实现createAopProxy方法
的实现类DefaultAopProxyFactory
类中。
- 看源码(
DefaultAopProxyFactory.java
)
1 | arduino复制代码@Override |
- 源码分析
在这个DefaultAopProxyFactory
类中可以明显的看到,这里根据Optimize
、ProxyTargetClass
、hasNoUserSuppliedProxyInterfaces
三个属性进行的决断,看究竟使用哪种动态代理。
- optimize 需要优化,默认为
false
详细来说就是:用来控制通过CGLIB创建的代理是否使用激进的优化策略;除非完全了解AOP代理如何处理优化,否则不推荐用户使用这个设置,目前这个属性仅用于CGLIB 代理,对于JDK动态代理(缺省代理)无效- ProxyTargetClass使用类代理,也就是使用 CGLIB 动态代理 默认为
false
设置方式:<aop:aspectj-autoproxy proxy-target-class=”true”/>
- hasNoUserSuppliedProxyInterfaces(config) // 是否存在代理接口
JDK与Cglib的说明
- 如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
- 如果目标对象实现了接口,可以强制使用CGLIB实现AOP。
- 如果目标对象没有实现了接口,必须采用CGLIB库,Spring会自动在JDK动态代理 和CGLIB之间转换
如何强制使用CGLIB实现AOP?
- 添加 CGLIB 库,Spring_HOME/cglib/*.jar
- Spring 配置文件中加人<aop:aspectj-autoproxy proxy-target-class=”true”/>。
JDK动态代理和CGLIB字节码生成的区别?
- JDK动态代理只能对实现了接口的类生成代理,而不能针对类。
- GLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,因为是继承,所以该类或方法最好不要声明成final。
好了到这里就讲完了Spring是如何决定使用哪种动态代理的方式的。
想要获取更多精彩内容请微信搜索【码上遇见你】
本文转载自: 掘金