依赖spring-boot-starter-web内部嵌套依赖spring-aop默认提供核心类之后置处理器InfrastructureAdvisorAutoProxyCreator
,意味着不管 AOP 异或 事务Transaction 都存在发挥效用的可能性【InfrastructureAdvisorAutoProxyCreator -> AbstractAdvisorAutoProxyCreator -> AbstractAutoProxyCreator】,如果需要 AOP 异或 事务必须生效则需要显示添加依赖spring-boot-starter-aop、spring-tx。
后置处理器InfrastructureAdvisorAutoProxyCreator【AbstractAutoProxyCreator】的必要性:尝试为每个bean创建Cglib代理。
public abstract class AbstractAutoProxyCreator{
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
...
//通过当前bean获取Advisor and Advice
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
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;
}
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName,TargetSource targetSource) {
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 从IOC容器中候选Advisor
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 从众多候选Advisor 选择适合当前bean的Advisor
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
}
bean可以被代理的前提是:当前IOC容器存在切面类Advisor,并且该Advisor的切点Pointcut
作用范围包含当前bean。如果是事务则当前bean的类名或者内部方法存在@Transactional。
1.切面类Advisor的提前初始化
SpringBoot自动装配引入AOP 或者 事务Transaction 相关的切面类Advisor,例如:
- 事务引入的切面类Advisor:BeanFactoryTransactionAttributeSourceAdvisor;通知Advice:TransactionInterceptor;切点Pointcut:TransactionAttributeSourcePointcut。
- Aop引入的切面类Advisor:InstantiationModelAwarePointcutAdvisorImpl;切点Pointcut:AspectJExpressionPointcut;通知Advice:前置通知、环绕通知、后置通知…。
1.1.事务Transaction之切面类Advisor
通常SpringBoot操作数据库需要依赖:
// 数据库厂商提供操作数据库的api
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
//SpringBoot提供操作数据库的api,例如jdbcTemplate。是对操作数据库的api再次封装
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
<scope>compile</scope>
</dependency>
//mybatis 对 spring-boot-starter-jdbc 再次封装
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.1</version>
</dependency>
spring-boot-starter-jdbc
内部封装了spring-jdbc
,spring-jdbc 内部封装了spring-tx
,spring-tx 提供事务操作的拦截器TransactionInterceptor
。该拦截器拦截@Transactional
注解,完成所在类的代理。
项目中只要存在依赖spring-tx,则必定触发TransactionAutoConfiguration、TransactionInterceptor类加载。
自动装配类TransactionAutoConfiguration存在于spring-boot-autoconfigure包中,并且该候选类生效的前提是存在依赖spring-tx。
public class ProxyTransactionManagementConfiguration {
//TRANSACTION_ADVISOR_BEAN_NAME:org.springframework.transaction.config.internalTransactionAdvisor
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
advisor.setTransactionAttributeSource(transactionAttributeSource());
advisor.setAdvice(transactionInterceptor());
...
return advisor;
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionInterceptor transactionInterceptor(
TransactionAttributeSource transactionAttributeSource) {
TransactionInterceptor interceptor = new TransactionInterceptor();
interceptor.setTransactionAttributeSource(transactionAttributeSource);
if (this.txManager != null) {
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
}
- 事务中切面类Advisor默认为
BeanFactoryTransactionAttributeSourceAdvisor
,通知Advice默认为TransactionInterceptor
。 - 核心类ProxyTransactionManagementConfiguration是通过类
TransactionAutoConfiguration
内部注解@EnableTransactionManagement引入的。 - 注解@Role是BeanFactoryTransactionAttributeSourceAdvisor满足 InfrastructureAdvisorAutoProxyCreator#isEligibleBean 逻辑的关键。
1.2、Aop之切面类Advisor的初始化
advisorNames:注解@Aspect对应的类。
Advisor:InstantiationModelAwarePointcutAdvisorImpl。
public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator {
@Override
protected List<Advisor> findCandidateAdvisors() {
// 调用抽象类对应的方法,事务获取切面类Advisor方式
List<Advisor> advisors = super.findCandidateAdvisors();
if (this.aspectJAdvisorsBuilder != null) {
//Aop获取切面类Advisor的方式
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
}
public class BeanFactoryAspectJAdvisorsBuilder {
public List<Advisor> buildAspectJAdvisors() {
List<String> aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List<Advisor> advisors = new ArrayList<>();
aspectNames = new ArrayList<>();
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
for (String beanName : beanNames) {
if (!isEligibleBean(beanName)) {
continue;
}
...
if (this.advisorFactory.isAspect(beanType)) {
aspectNames.add(beanName);
...
advisors.addAll(classAdvisors);
}
}
this.aspectBeanNames = aspectNames;
return advisors;
}
}
}
...
return advisors;
}
}
类似于Transaction,AnnotationAwareAspectJAutoProxyCreator同样重写了isEligibleBean
方法。
针对Aop其候选切面类Advisor必选满足两个条件:
- isEligibleBean ~ 是否有资格进行自动代理。
- 当前bean必须存在@Aspect注解。
2、AbstractAutoProxyCreator获取切面类Advisor
该类型的后置处理器其核心功能总结:判断当前bean是否需要代理处理并且返回对应的切面类Advisor。
public abstract class AbstractAutoProxyCreator implements SmartInstantiationAwareBeanPostProcessor{
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
...
return wrapIfNecessary(bean, beanName, cacheKey);
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
...
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
...
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);//#1
if (specificInterceptors != DO_NOT_PROXY) {
...//具体代理类生成过程
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
}
Map集合类型的属性advisedBeans,其元素为不需要的代理的bean。
isInfrastructureClass:表示是否为aop相关的基础设施类。infrastructureClass包含Advice、Pointcut、Advisor、AopInfrastructureBean以及AnnotationAwareAspectJAutoProxyCreator提供的@Aspect等类。这些infrastructureClass均不需要代理处理。
步骤1:当前bean如果需要代理则返回其对应的切面类Advisor。注意此时的Advisor中已经包含其通知advice、切点pointcut等核心类。
2.1、AbstractAdvisorAutoProxyCreator
public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator {
private BeanFactoryAdvisorRetrievalHelper advisorRetrievalHelper;
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName,TargetSource targetSource) {
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
List<Advisor> candidateAdvisors = findCandidateAdvisors();//#1
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);//#2
...
return eligibleAdvisors;
}
protected List<Advisor> findCandidateAdvisors() {
return this.advisorRetrievalHelper.findAdvisorBeans();//#2
}
private class BeanFactoryAdvisorRetrievalHelperAdapter extends BeanFactoryAdvisorRetrievalHelper {
public BeanFactoryAdvisorRetrievalHelperAdapter(ConfigurableListableBeanFactory beanFactory) {
super(beanFactory);
}
@Override
protected boolean isEligibleBean(String beanName) {
return AbstractAdvisorAutoProxyCreator.this.isEligibleAdvisorBean(beanName);
}
}
}
步骤1分别是Aop、Transaction获取切面类Advisor的核心方法:
- Aop:
AnnotationAwareAspectJAutoProxyCreator
重写了抽象类AbstractAdvisorAutoProxyCreator中方法findCandidateAdvisors获取提前初始化的切面类Advisor。 - Transaction :区别于Aop的后置处理器,事务后置处理器之
InfrastructureAdvisorAutoProxyCreator
通过步骤#2调用AbstractAdvisorAutoProxyCreator类中方法获取提前初始化的切面类Advisor。
3、执行代理逻辑
4、AspectJAwareAdvisorAutoProxyCreator
AspectJAwareAdvisorAutoProxyCreator重写了抽象父类AbstractAutoProxyCreator
的shouldSkip
方法。
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
List<Advisor> candidateAdvisors = findCandidateAdvisors();
for (Advisor advisor : candidateAdvisors) {
if (advisor instanceof AspectJPointcutAdvisor &&
((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
return true;
}
}
return super.shouldSkip(beanClass, beanName);
}