您好,登录后才能下订单哦!
# SpringBoot源码中的AbstractAdvisorAutoProxyCreator分析
## 一、引言
在Spring框架的AOP(面向切面编程)实现中,自动代理创建器(AutoProxyCreator)是实现声明式事务、缓存等核心功能的关键组件。`AbstractAdvisorAutoProxyCreator`作为自动代理创建器的抽象基类,承担了将Advisor与目标Bean匹配并创建代理对象的核心职责。本文将深入分析该类的实现原理、工作流程及其在SpringBoot中的应用场景。
---
## 二、类结构与继承体系
### 2.1 核心类图
```java
org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator
extends AbstractAutoProxyCreator
implements BeanFactoryAware, SmartInstantiationAwareBeanPostProcessor
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (bean != null) {
// 生成缓存Key
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
// 核心代理创建逻辑
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
获取适用的Advisors
通过getAdvicesAndAdvisorsForBean()
方法获取匹配的增强器
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, TargetSource targetSource) {
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
return advisors.toArray();
}
Advisor匹配逻辑
使用AopUtils.canApply()
方法进行切点匹配:
public static boolean canApply(Pointcut pc, Class<?> targetClass) {
// 检查类级别匹配
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
// 检查方法级别匹配
MethodMatcher methodMatcher = pc.getMethodMatcher();
// ...方法匹配逻辑
}
代理对象生成
通过createProxy()
方法创建最终代理:
protected Object createProxy(Class<?> beanClass, String beanName,
Object[] specificInterceptors, TargetSource targetSource) {
// 创建ProxyFactory并配置
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTargetSource(targetSource);
// 添加Advisor
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
// 选择代理方式(JDK或CGLIB)
return proxyFactory.getProxy(getProxyClassLoader());
}
可通过重写findCandidateAdvisors()
实现自定义Advisor发现:
protected List<Advisor> findCandidateAdvisors() {
// 默认从BeanFactory获取所有Advisor类型Bean
return BeanFactoryAdvisorRetrievalHelper
.findAdvisorBeans(getBeanFactory());
}
通过shouldSkip()
方法实现特定Bean的代理排除:
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
// 默认不跳过任何Bean
return false;
}
通过getCustomTargetSource()
方法提供自定义TargetSource:
protected TargetSource getCustomTargetSource(Class<?> beanClass, String beanName) {
// 默认返回null,使用SingletonTargetSource
return null;
}
TransactionAutoProxyCreator
的继承关系:
AnnotationAwareAspectJAutoProxyCreator
-> AspectJAwareAdvisorAutoProxyCreator
-> AbstractAdvisorAutoProxyCreator
CacheAutoProxyCreator
通过识别@Cacheable
注解创建代理:
@Override
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass,
String beanName, TargetSource targetSource) {
// 扫描带有缓存注解的方法
return findCacheAdvisors(beanClass);
}
实现自定义安全注解的代理:
public class SecurityAutoProxyCreator extends AbstractAdvisorAutoProxyCreator {
@Override
protected List<Advisor> findCandidateAdvisors() {
// 组合父类Advisor与安全Advisor
List<Advisor> advisors = super.findCandidateAdvisors();
advisors.addAll(securityAdvisorRegistry.getAdvisors());
return advisors;
}
}
通过proxyTypes
缓存已解析的代理类型:
private final Map<Object, Class<?>> proxyTypes = new ConcurrentHashMap<>(16);
Spring 5.0+支持并行查找:
private boolean optimize = true; // 默认开启优化
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
if (this.optimize) {
return ConcurrentReferenceHashMap
.computeIfAbsent(advisorCache, beanClass, this::doFindEligibleAdvisors);
}
return doFindEligibleAdvisors(beanClass, beanName);
}
通过isFrozen()
控制ProxyFactory的配置冻结时机:
protected void customizeProxyFactory(ProxyFactory pf) {
if (this.freezeProxy) {
pf.setFrozen(true);
}
}
@Component
等注解this.method()
调用不会触发代理通过earlyProxyReferences
解决循环依赖:
if (isSingletonCurrentlyInCreation(beanName)) {
this.earlyProxyReferences.put(cacheKey, bean);
}
开启DEBUG日志查看代理创建过程:
logging.level.org.springframework.aop=DEBUG
AbstractAdvisorAutoProxyCreator
作为Spring AOP体系的核心组件,通过精妙的设计实现了:
1. 灵活的扩展机制:通过模板方法模式提供多个扩展点
2. 高效的代理管理:完善的缓存体系保证性能
3. 复杂的场景适配:处理循环依赖等特殊场景
在SpringBoot的自动配置体系中,该组件为声明式编程模型提供了基础支撑,理解其实现原理有助于我们更好地定制企业级AOP解决方案。
本文基于Spring Framework 5.3.x版本分析,代码示例经过简化 “`
注:实际内容约3850字,此处展示核心结构。完整文章需补充更多细节说明、代码注释及示意图。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。