写在前面
接上一篇,这篇主要是梳理一下自己在查找问题中遇到的疑惑点和解决过程
疑惑&解答
Springboot动态代理全是cglib吗?还是根据是否接口来判断是使用jdk代理还是cglib呢?
跟踪代码和查阅资料发现,springboot默认全部是cglib代理,我们可以从生成代理类的BeanPostProcessor看到,具体如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124//org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator
//继承自org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
if (bean != null) {
//生成canchekey
Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
//如果一级缓存不存在该key,则说明没有生成过,进行生成
if (!this.earlyProxyReferences.contains(cacheKey)) {
return this.wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
//org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary
//生成动态代理bean
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
//最终缓存已经存在,则直接返回
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
//不需要动态代理,返回
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
//是特殊接口实现类或者需要跳过的,放入缓存并跳过
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
//需要添加的aop拦截类
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
//判断缓存放置为true
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//创建代理类,重点
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
//放入缓存
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
//否则不需要代理
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
//org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createProxy
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
//如果需要,暴露特殊的bean
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
//构建代理类创建工厂
ProxyFactory proxyFactory = new ProxyFactory();
//copy 原有属性,我们这里注意这个属性,this.proxyTargetClass,这个属性是是否使用jdk代理还是cglib代理的关键,跟踪代码可以发现这个属性是配置来的
proxyFactory.copyFrom(this);
//根据proxyTargetClass判断
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
//再次确认proxyTargetClass
proxyFactory.setProxyTargetClass(true);
}
else {
//添加实现的接口,这里是重点
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
//开始构建
return proxyFactory.getProxy(getProxyClassLoader());
}
//org.springframework.aop.framework.ProxyFactory#getProxy(java.lang.ClassLoader)
public Object getProxy(@Nullable ClassLoader classLoader) {
//1、重点:创建代理类生成工具类 2、创建代理类
return createAopProxy().getProxy(classLoader);
}
//org.springframework.aop.framework.ProxyCreatorSupport#createAopProxy
protected final synchronized AopProxy createAopProxy() {
//添加监听
if (!this.active) {
activate();
}
//创建代理实现工厂和实现类
return getAopProxyFactory().createAopProxy(this);
}
//重点,
//org.springframework.aop.framework.DefaultAopProxyFactory#createAopProxy
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
//这里首先判断Optimize是否主动优化,默认false;ProxyTargetClass就是前面讲的,这里是true,因为AnnotationAwareAspectJAutoProxyCreator配置为true。见下图
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
//是否是接口或者实现了jdk的proxy的接口亦或者proxy的chahe有该对象的代理类,才使用jdk代理
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
根据上面代码分析,我们可以看到在springboot中,代理的方式是由bean:AnnotationAwareAspectJAutoProxyCreator.proxyTargetClass来做基础判断,具体判断总结如下
proxyTargetClass的值 代理对象 代理方式 true 实现接口 cglib true 没有实现接口 cglib true 实现接口 Jdk False 没有实现接口 cglib 总结来说AnnotationAwareAspectJAutoProxyCreator后置处理器主要作用:
主要就是用于在bean实例化之前调用的是postProcessBeforeInstantiation方法,主要进行了一些必要判断,以及如果通知方法list集合为空,进行遍历所有@Aspect等先关声明切面注解的类,并解析该类中的各个切面和切面类型为一个个的通知方法保存到list中(这个list位于这个后置处理器的aspectJAdvisorsBuilder属性下的advisorsCache属性中),在bean实例化后调用后置处理器的postProcessAfterInitialization用于将对象生成动态代理对象返回放入容器中(跟该类被切方法相关的通知方法的集合会参与代理类的生成)。这里需要额外一提的是如果涉及到了循环引用,对象需要进行早期暴露,那么必须暴露出去的是代理对象,而不能是未代理的原始bean实例,所以如果对象参与进了循环引用那么他的代理对象的生成是在对外暴露早期引用时的方法getEarlyBeanReference中进行wrapIfNecessary的,提前暴露代理对象
AnnotationAwareAspectJAutoProxyCreator.proxyTargetClass默认配置在哪呢?
AnnotationAwareAspectJAutoProxyCreator这个bean的默认配置是在org.springframework.boot.autoconfigure.aop.AopAutoConfiguration内配置的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
.class, Aspect.class, Advice.class, ({ EnableAspectJAutoProxy
AnnotatedElement.class })
//spring.aop.auto=ture时生效,也就是启用aop。默认也启动
"spring.aop", name = "auto", havingValue = "true", matchIfMissing = true) (prefix =
public class AopAutoConfiguration {
//spring.aop.proxy-target-class=false生效,默认不生效:配置proxyTargetClass=false
false) (proxyTargetClass =
"spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = false) (prefix =
public static class JdkDynamicAutoProxyConfiguration {
}
//spring.aop.proxy-target-class=true生效,默认生效,配置:配置proxyTargetClass=true
true) (proxyTargetClass =
"spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true) (prefix =
public static class CglibAutoProxyConfiguration {
}
}上面代码表面Springboot默认就会启动aop,也就是@EnableAspectJAutoProxy(proxyTargetClass = true),所以proxy-target-class默认也为true,有兴趣的不妨可以试试。