Spring内部的AOP机制[待完善,各个类在AOP中处理的作用,以便深入理解AOP的内部机制]
- 一、建立Spring的AOP【@Aspect或者@Transactional】机制的内部环境
- AbstractAdvisorAutoProxyCreator
- 二、@Transactional的AOP内部机制
- 三、@Async的AOP内部机制
- @Aspect的执行机制,及执行过程中,更好理解之前创建的各个类的角色及作用
- Spring AOP 中的基础数据结构
- Advisor在Spring AOP中扮演的角色及作用
- PointcutAdvisor在Spring AOP中扮演的角色及作用
- AbstractPointcutAdvisor在Spring AOP中扮演的角色及作用
- Spring AOP中的编码规范
- 以用户操作日志为例,来说明Spring AOP如何起作用
- 总结:
【这种排版方式,是为了解决多个命名相同又调用,即便是代码debug,跟着跟,也会跟丢,所以,通过这种排版,理顺一下调用链,加深理解】
一、建立Spring的AOP【@Aspect或者@Transactional】机制的内部环境
1、前言
Spring提供了两种开启AOP的方式,一种是通过Xml的方式:aop:aspectj-autoproxy/,另一种是通过**@EnableAspectJAutoProxy方式。
不管是何种启用方式,AnnotationAwareAspectJAutoProxyCreator对象的创建都需要先被IOC容器解析成为BeanDefinition,然后Spring再从该BeanDefinition中创建该对象。两种方式被解析成BeanDefinition的方式不同,一种是通过AopNamespaceHandler**,另一种是通过基于Spring环境下的注解驱动AspectJAutoProxyRegistrar,该类是Spring Aop中的核心对象要在IOC容器中解析成BeanDefinition并注册的。【再次回顾一下基于Spring环境下的注解开发的实现,另一种注解驱动的可参考Dubbo的**@EnableDubbo**,以此巩固Spring环境下的注解驱动开发过程。】
在创建AnnotationAwareAspectJAutoProxyCreator的对象时,通过BeanFactoryAware来为AOP提供BeanFactory的环境。【从Spring提供的各种Aware接口可以看出,这是为了方便扩展Spring而提供的接口】。该接口被执行的时机是在对象创建的initializeBean阶段中。依赖如下:
2、AnnotationAwareAspectJAutoProxyCreator的环境创建流程
2.1、 @Aspect入口
Spring AOP的内部环境的建立是在AnnotationAwareAspectJAutoProxyCreator对象创建的initializeBean阶段中【这里的AOP指的是用**@Aspect注解的,不是@Async**的AOP环境建立】。
AbstractAutowireCapableBeanFactory::invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanFactoryAware) {
// 1.spring aop环境的建立入口【注释中的阿拉伯数字代表了创建SpringAOP环境时的执行顺序】
// 这个bean对象指的是
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
在AnnotationAwareAspectJAutoProxyCreator的bean后置处理器创建完成之后,第一次被执行的时机在registerBeanPostProcessors中的第三个阶段nonOrderedPostProcessorNames。此时,来看看之前各个类在AOP机制中的作用。
AbstractAutoProxyCreator:postProcessBeforeInstantiation() 对创建的bean是否要进行拦截并AOP处理。这个类是链接点,创建AOP代理对象。在这里createProxy。接着触发ProxyFactory的创建。从这里引申出面试点。
- Q:Spring AOP的入口是哪里?
- A:AnnotationAwareAspectJAutoProxyCreator,这其实是一个BeanPostProcessor。在populateBean中或者initializeBean中都会起作用。实际是createProxy方法。(这有个问题,这里所说的在populateBean中起作用,并不是真正创建代理。只是populateBean中,该processor的相关方法被不作处理的执行了一次。实际创建代理对象是在initializeBean的postProcessAfterInitialization的方法。)
- Q:Spring创建代理的方式有几种?默认是哪种?
- A:cglib代理和jdk动态代理。默认是基于一个或更多接口的JDK动态代理。若指定proxyTargetClass,则使用CGLIB代理。
ProxyFactory是Spring AOP 提供了基于编码的方式创建AOP proxies Factory,而不是在beanFactory通过声明式的设置。
ProxyCreatorSupport是proxy factories的基类,提供对一个可配置的AopProxyFactory的方便的访问(持有该引用对象)【在创建ProxyCreatorSupport的时候,接着创建了DefaultAopProxyFactory。】。
DefaultAopProxyFactory创建CGLIB或者JDK动态代理的AopProxyFactory的默认实现。
2.2、AnnotationAwareAspectJAutoProxyCreator具体的环境创建
2.2.1、AbstractAdvisorAutoProxyCreator设置beanFactory
// Helper for retrieving standard Spring Advisors from a BeanFactory, for use with auto-proxying.
// 对于使用自动代理,可以从BeanFactory中获取标准的Spring Advisors 帮助类,赋值的时机在子类初始化beanFactory的时候
private BeanFactoryAdvisorRetrievalHelper advisorRetrievalHelper;
// 2.在创建完AnnotationAwareAspectJAutoProxyCreator该对象并初始化的过程中invokeAwareMethods这一阶段中
// 完成对Spring AOP环境所需要的对beanFactory的持有。以便Spring AOP能够访问beanFactory中的方法跟数据
@Override
public void setBeanFactory(BeanFactory beanFactory) {
// 将Spring的IOC容器保存到AbstractAutoProxyCreator中
super.setBeanFactory(beanFactory);
if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
throw new IllegalStateException("Cannot use AdvisorAutoProxyCreator without a ConfigurableListableBeanFactory");
}
// 初始化Spring AOP的环境,先执行的是AnnotationAwareAspectJAutoProxyCreator中的initBeanFactory方法
initBeanFactory((ConfigurableListableBeanFactory) beanFactory);
}
2.2.2、AbstractAutoProxyCreator中beanFactory的赋值
这个类实现了BeanFactoryAware,beanFactory会因此被赋值,在创建相关对象的时候,就是为了提供对外访问Spring内部相关对象的入口,这也是Spring中Aware接口的作用。
@Override
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
2.2.3、AnnotationAwareAspectJAutoProxyCreator的initBeanFactory
初始化Spring AOP中的工厂,对IOC容器中的beanFactory进行包装加工,使之能用于Spring AOP的,所以才说是initBeanFactory。注意,别理解成改变了它的行为。【这是我阅读代码时遇到的命名困惑,再次回看时,想通的,稍微注解一下。】
// 3.创建Spring AOP【@Aspect和@Transational】的环境【findAdvisor和buildAdvisor】
@Override
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 触发父类AbstractAdvisorAutoProxyCreator,创建可以从BeanFactory中获取Spring Advisors的帮助类。
super.initBeanFactory(beanFactory);
// 【这个对象的含义需要再次认清】
if (this.aspectJAdvisorFactory == null) {
this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
}
// 创建AspectJ Advisors的帮助类
// Helper for retrieving @AspectJ beans from a BeanFactory and building Spring Advisors based on them,
// for use with auto-proxying.
// 5. buildAdvisor from method 中
this.aspectJAdvisorsBuilder =
new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
}
2.2.4 AbstractAdvisorAutoProxyCreator的initBeanFactory
// 4.子类AnnotationAwareAspectJAutoProxyCreator调用父类,触发的
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 这个变量起作用的时机,是在bean对象创建的过程中,由AOP的BeanPostProcessor触发,postProcessAfterInitialization方法
// 这个变量的作用的时机,就是bean对象创建的initializeBean的初始化完成后,被执行的applyBeanPostProcessorsAfterInitialization。
// 【回看,想通的,与BeanFactoryAspectJAdvisorsBuilderAdapter区别,我的理解是,这个是从beanDefiniton中获取的Advisor,即容器中声明过的Advisor;而BeanFactoryAspectJAdvisorsBuilderAdapter这个,我的理解是,从method中构建出Advisor】
this.advisorRetrievalHelper = new BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory);
}
3、AnnotationAwareAspectJAutoProxyCreator的创建代理对象流程
3.1、创建代理的入口【父类AbstractAutoProxyCreator】
持有基本【DefaultListableBeanFactory】的BeanFactory容器
这段代码起作用的时机,是在bean对象被IOC容器创建后,初始化完成该bean对象后,由AOP的BeanPostProcessor触发,判断该对象是否要进行Spring AOP代理。
/**
* Create a proxy with the configured interceptors if the bean is
* identified as one to proxy by the subclass.
* @see #getAdvicesAndAdvisorsForBean
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
// a. spring AOP代理【英文字母Spring AOP代理对象的执行顺序,比如@Aspect】
// 对IOC容器已经创建完的对象进行包装,如果需要代理的话
// 这个包装指的是,是返回原生对象还是代理对象
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
3.2、判断是否要对容器创建完的对象应用代理【AbstractAutoProxyCreator】
/**
* Wrap the given bean if necessary, i.e. if it is eligible for being proxied.
* @param bean the raw bean instance
* @param beanName the name of the bean
* @param cacheKey the cache key for metadata access
* @return a proxy wrapping the bean, or the raw bean instance as-is
*/
AbstractAutoProxyCreator::wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// 已经判断过且明确不需要代理的
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
// shouldSkip中有找是否有Advisor【是否要跳过代理】
// isInfrastructureClass先执行的AnnotationAwareAspectJAutoProxyCreator
// 首先,如果目标类是基类的,就不需要Spring AOP代理
// 其次,如果不是基类的话,再次判断是否需要跳过AOP代理
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
// 如果开启了Spring AOP功能,那么所有IOC容器中的业务bean对象被初始化完成后,都会存放到advisedBean
// 集合中
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
// d 找到是否可以进行SpringAOP代理的
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;
}
3.2.1、AnnotationAwareAspectJAutoProxyCreator的isInfrastructureClass
判断这个目标类是否是基础设施类
@Override
protected boolean isInfrastructureClass(Class<?> beanClass) {
// Previously we setProxyTargetClass(true) in the constructor, but that has too
// broad an impact. Instead we now override isInfrastructureClass to avoid proxying
// aspects. I'm not entirely happy with that as there is no good reason not
// to advise aspects, except that it causes advice invocation to go through a
// proxy, and if the aspect implements e.g the Ordered interface it will be
// proxied by that interface and fail at runtime as the advice method is not
// defined on the interface. We could potentially relax the restriction about
// not advising aspects in the future.
return (super.isInfrastructureClass(beanClass) ||
(this.aspectJAdvisorFactory != null &&
this.aspectJAdvisorFactory.isAspect(beanClass)));
}
3.2.2、AbstractAspectJAdvisorFactory的isAspect
判断目标类是否被@Aspect注解声明,且还不能被AJC编译(原因简单就是在AspectJ的1.5以下的版本中,也有这个注解,但是却不能被Spring AOP使用)
/**
* We consider something to be an AspectJ aspect suitable for use by the Spring AOP system
* if it has the @Aspect annotation, and was not compiled by ajc. The reason for this latter test
* is that aspects written in the code-style (AspectJ language) also have the annotation present
* when compiled by ajc with the -1.5 flag, yet they cannot be consumed by Spring AOP.
*/
@Override
public boolean isAspect(Class<?> clazz) {
return (hasAspectAnnotation(clazz) && !compiledByAjc(clazz));
}
private boolean hasAspectAnnotation(Class<?> clazz) {
return (AnnotationUtils.findAnnotation(clazz, Aspect.class) != null);
}
/**
* We need to detect this as "code-style" AspectJ aspects should not be
* interpreted by Spring AOP.
*/
private boolean compiledByAjc(Class<?> clazz) {
// The AJTypeSystem goes to great lengths to provide a uniform appearance between code-style and
// annotation-style aspects. Therefore there is no 'clean' way to tell them apart. Here we rely on
// an implementation detail of the AspectJ compiler.
for (Field field : clazz.getDeclaredFields()) {
if (field.getName().startsWith(AJC_MAGIC)) {
return true;
}
}
return false;
}
3.2.3、AbstractAutoProxyCreator中的shouldSkip
AbstractAutoProxyCreator提供了默认不跳过代理的实现,其AspectJAwareAdvisorAutoProxyCreator
这段代码被触发的时机是由AbstractAutoProxyCreator中的shouldSkip触发
// b.判断是否要跳过AnnotationAwareAspectJAutoProxyCreator这个SpringAOP后置处理器对bean对象创建初始化完成后的代理处理
@Override
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
// TODO: Consider optimization by caching the list of the aspect names
// 这个findCandidateAdvisors是调用父类AbstractAdvisorAutoProxyCreator的
List<Advisor> candidateAdvisors = findCandidateAdvisors();
for (Advisor advisor : candidateAdvisors) {
if (advisor instanceof AspectJPointcutAdvisor) {
if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {
return true;
}
}
}
// 父类的一直返回false
return super.shouldSkip(beanClass, beanName);
}
3.3、判断是否需要AOP代理【AbstractAutoProxyCreator】
AbstractAutoProxyCreator中的方法是一个模板方法,具体实现在子类AbstractAdvisorAutoProxyCreator中
// e. 由AbstractAutoProxyCreator这个类调用,触发时机在其wrapIfNecessary方法执行完shouldSkip之后
@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
// f. 依据这个判断,是否需要返回创建对象的代理对象
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
// 这个 DO_NOT_PROXY = null,用语义替代null,便于理解
return DO_NOT_PROXY;
}
return advisors.toArray();
}
/**
* Find all eligible Advisors for auto-proxying this class.
* @param beanClass the clazz to find advisors for
* @param beanName the name of the currently proxied bean
* @return the empty List, not {@code null},
* if there are no pointcuts or interceptors
* @see #findCandidateAdvisors
* @see #sortAdvisors
* @see #extendAdvisors
*/
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// f.1 第一步:获取所有的Advisor
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// f.2 第二步:从所有的Advisor中选出能够用于目标类的Advisor
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
3.3.1、从容器中找到所有的Advisor
从容器中找到用自动代理的所有的Advisor
/** AbstractAdvisorAutoProxyCreator
* Find all candidate Advisors to use in auto-proxying.,子类调用
* @return the List of candidate Advisors
*/
protected List<Advisor> findCandidateAdvisors() {
// c.找IOC容器中所有的Advisor
// BeanFactoryAdvisorRetrievalHelper这个类就是为了在Spring容器中找到所有的Advisor。这也解释了为什么该Helper类需要
// beanFactory。
// 因为需要beanFactory中根据type=Advisor来获取该类型的beanName。
// 也就是该BeanPostProcessor为什么要实现BeanFactoryAware方法,提供对BeanFactory中数据的访问。
// ==总结:BeanFactoryAware是Spring容器向外部提供对beanFactory内部方法访问的机制。==
return this.advisorRetrievalHelper.findAdvisorBeans();
}
// 由~Helper这个类具体做从SpringIOC容器中找到所有声明的Advisor
BeanFactoryAdvisorRetrievalHelper::findAdvisorBeans() {
// Determine list of advisor bean names, if not cached already.
String[] advisorNames = null;
synchronized (this) {
// this.cachedAdvisorBeanNames 只调用一次
// BeanFactoryUtils.beanNamesForTypeIncludingAncestors
// 因为这个方法是从IOC容器中所有的beanDefinitionName中查找,因此,缓存的作用
// 尽可能避免了web应用过大所造成的效率低下。
advisorNames = this.cachedAdvisorBeanNames;
if (advisorNames == null) {
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the auto-proxy creator apply to them!
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
this.cachedAdvisorBeanNames = advisorNames;
}
}
if (advisorNames.length == 0) {
return new LinkedList<>();
}
List<Advisor> advisors = new LinkedList<>();
for (String name : advisorNames) {
// 默认的,所有的Advisor都使用Spring AOP代理。该方法实现返回true
if (isEligibleBean(name)) {
// 对正在创建的bean不做代理
if (this.beanFactory.isCurrentlyInCreation(name)) {
if (logger.isDebugEnabled()) {
logger.debug("Skipping currently created advisor '" + name + "'");
}
}
else {
try {
// 使用bean对象的创建流程
advisors.add(this.beanFactory.getBean(name, Advisor.class));
}
catch (BeanCreationException ex) {
Throwable rootCause = ex.getMostSpecificCause();
if (rootCause instanceof BeanCurrentlyInCreationException) {
BeanCreationException bce = (BeanCreationException) rootCause;
String bceBeanName = bce.getBeanName();
if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {
if (logger.isDebugEnabled()) {
logger.debug("Skipping advisor '" + name +
"' with dependency on currently created bean: " + ex.getMessage());
}
// Ignore: indicates a reference back to the bean we're trying to advise.
// We want to find advisors other than the currently created bean itself.
continue;
}
}
throw ex;
}
}
}
}
return advisors;
}
3.3.2、从所有的Advisor中过滤出能应用于目标对象的Advisor
/**
* Search the given candidate Advisors to find all Advisors that
* can apply to the specified bean.
* @param candidateAdvisors the candidate Advisors
* @param beanClass the target's bean class
* @param beanName the target's bean name
* @return the List of applicable Advisors
* @see ProxyCreationContext#getCurrentProxiedBeanName()
*/
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
// g.从候选者集筛选出可以应用到beanClass上的Advisors
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
AopUtils::findAdvisorsThatCanApply(candidateAdvisors, beanClass) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new LinkedList<>();
for (Advisor candidate : candidateAdvisors) {
// 候选Advisor满足两个条件:
// 1. 该Advisor实现了IntroductionAdvisor
// 2. 该Advisor能匹配到目标类
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
// h.具体做Advisors与创建并初始化完后bean的做匹配
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
/**
* Can the given pointcut apply at all on the given class?
* <p>This is an important test as it can be used to optimize
* out a pointcut for a class.
* @param pc the static or dynamic pointcut to check
* @param targetClass the class to test
* @param hasIntroductions whether or not the advisor chain
* for this bean includes any introductions
* @return whether the pointcut can apply on any method
*/
AopUtils::canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
// i.从切点中获取方法匹配器
MethodMatcher methodMatcher = pc.getMethodMatcher();
if (methodMatcher == MethodMatcher.TRUE) {
// No need to iterate the methods if we're matching any method anyway...
return true;
}
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
Set<Class<?>> classes = new LinkedHashSet<>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
classes.add(targetClass);
for (Class<?> clazz : classes) {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
if ((introductionAwareMethodMatcher != null &&
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
// j.@Transactional @Aspect @Async 都是用到这个逻辑匹配
// 只不过是,两者具体的匹配方式不同。
// 从这里不难发现,接口编程的重要性。
// 同时,也能体会到抽象类的重要作用。抽象类一般是提供流程,涉及一些外调,通常是用接口来配合的
// 这样,才能真正发挥抽象类和接口的作用【举例说明】
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
AbstractAdvisorAutoProxyCreator
二、@Transactional的AOP内部机制
1、@Transactional的AOP环境的建立
@Transactional的AOP环境建立比较简单,只需要创建这三个对象:
BeanFactoryTransactionAttributeSourceAdvisor
TransactionAttributeSource:事务属性源,这个存在的作用就是能将AnnotationAttribute转换成TransactionAttribute
TransactionInterceptor:事务拦截器 => Advise
TransactionAttributeSourcePointcut:事务属性源切点 => Pointcut
2、@Transactional的类创建代理对象
// j.1 @Transactional的处理逻辑[要创建的代理对象,匹配逻辑]
BeanFactoryTransactionAttributeSourceAdvisor->TransactionAttributeSourcePointcut::matches(Method method,
Class<?> targetClass) {
if (TransactionalProxy.class.isAssignableFrom(targetClass)) {
return false;
}
// j.1.1 获取的是BeanFactoryTransactionAttributeSourceAdvisor中的TransactionAttributeSource,作用域是在
// BeanFactoryTransactionAttributeSourceAdvisor中的
TransactionAttributeSource tas = getTransactionAttributeSource();
// j.1.2 获取的tas其实是AbstractFallbackTransactionAttributeSource对象
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}
/**
* Determine the transaction attribute for this method invocation.
* <p>Defaults to the class's transaction attribute if no method attribute is found.
* @param method the method for the current invocation (never {@code null})
* @param targetClass the target class for this invocation (may be {@code null})
* @return TransactionAttribute for this method, or {@code null} if the method
* is not transactional
*/
@Override
AbstractFallbackTransactionAttributeSource::getTransactionAttribute(Method method, Class<?> targetClass) {
// First, see if we have a cached value.
// j.1.2.1 判断这个方法的事物是否已存在缓存中
Object cacheKey = getCacheKey(method, targetClass);
Object cached = this.attributeCache.get(cacheKey);
if (cached != null) {
// Value will either be canonical value indicating there is no transaction attribute,
// or an actual transaction attribute.
if (cached == NULL_TRANSACTION_ATTRIBUTE) {
return null;
}
else {
return (TransactionAttribute) cached;
}
}
else {
// We need to work it out.
// j.1.2.2 不在缓存中,就需要获取并重新放进缓存中
TransactionAttribute txAtt = computeTransactionAttribute(method, targetClass);
// j.1.2.3 Put it in the cache.
if (txAtt == null) {
// 不进行事物
this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
}
else {
if (logger.isDebugEnabled()) {
Class<?> classToLog = (targetClass != null ? targetClass : method.getDeclaringClass());
logger.debug("Adding transactional method '" + classToLog.getSimpleName() + "." +
method.getName() + "' with attribute: " + txAtt);
}
// 要事物管理的
this.attributeCache.put(cacheKey, txAtt);
}
return txAtt;
}
}
/**j.1.2.2 判断目标对象的方法是否要进行事物的管理
* Same signature as {@link #getTransactionAttribute}, but doesn't cache the result.
* {@link #getTransactionAttribute} is effectively a caching decorator for this method.
* <p>As of 4.1.8, this method can be overridden.
* @since 4.1.8
* @see #getTransactionAttribute
*/
protected TransactionAttribute computeTransactionAttribute(Method method, Class<?> targetClass) {
// Don't allow no-public methods as required. 【事物必须要public方法】
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;
}
// Ignore CGLIB subclasses - introspect the actual user class.
Class<?> userClass = ClassUtils.getUserClass(targetClass);
// The method may be on an interface, but we need attributes from the target class.
// If the target class is null, the method will be unchanged.
Method specificMethod = ClassUtils.getMostSpecificMethod(method, userClass);
// If we are dealing with method with generic parameters, find the original method.
specificMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
// j.1.2.2.1 First try is the method in the target class.【先从方法中找事物,因此最好不要把@Transactional声明在类上】
TransactionAttribute txAtt = findTransactionAttribute(specificMethod);
if (txAtt != null) {
return txAtt;
}
// j.1.2.2.2 Second try is the transaction attribute on the target class.
txAtt = findTransactionAttribute(specificMethod.getDeclaringClass());
if (txAtt != null) {
return txAtt;
}
if (specificMethod != method) {
// j.1.2.2.3 Fallback is to look at the original method.
txAtt = findTransactionAttribute(method);
if (txAtt != null) {
return txAtt;
}
// j.1.2.2.4 Last fallback is the class of the original method.
return findTransactionAttribute(method.getDeclaringClass());
}
return null;
}
/** [j.1.2.2.1 - j.1.2.2.4] 最终都会调用AnnotationTransactionAttributeSource的下述方法
* Determine the transaction attribute for the given method or class.
* <p>This implementation delegates to configured
* {@link TransactionAnnotationParser TransactionAnnotationParsers}
* for parsing known annotations into Spring's metadata attribute class.
* Returns {@code null} if it's not transactional.
* <p>Can be overridden to support custom annotations that carry transaction metadata.
* @param ae the annotated method or class
* @return TransactionAttribute the configured transaction attribute,
* or {@code null} if none was found
*/
protected TransactionAttribute determineTransactionAttribute(AnnotatedElement ae) {
if (ae.getAnnotations().length > 0) {
for (TransactionAnnotationParser annotationParser : this.annotationParsers) {
// 用的是SpringTransactionAnnotationParser
// 这个作用是将AnnotationAttribute转换成TransactionAttribute
TransactionAttribute attr = annotationParser.parseTransactionAnnotation(ae);
if (attr != null) {
return attr;
}
}
}
return null;
}
3、@Transactional执行事务的流程
这个是事务代理后的对象执行的invoke方法。【cglib代理的】
/**
* General delegate for around-advice-based subclasses, delegating to several other template
* methods on this class. Able to handle {@link CallbackPreferringPlatformTransactionManager}
* as well as regular {@link PlatformTransactionManager} implementations and
* {@link ReactiveTransactionManager} implementations for reactive return types.
* @param method the Method being invoked
* @param targetClass the target class that we're invoking the method on
* @param invocation the callback to use for proceeding with the target invocation
* @return the return value of the method, if any
* @throws Throwable propagated from the target invocation
*/
@Nullable
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
final InvocationCallback invocation) throws Throwable {
// If the transaction attribute is null, the method is non-transactional.
TransactionAttributeSource tas = getTransactionAttributeSource();
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
final TransactionManager tm = determineTransactionManager(txAttr);
if (this.reactiveAdapterRegistry != null && tm instanceof ReactiveTransactionManager) {
ReactiveTransactionSupport txSupport = this.transactionSupportCache.computeIfAbsent(method, key -> {
if (KotlinDetector.isKotlinType(method.getDeclaringClass()) && KotlinDelegate.isSuspend(method)) {
throw new TransactionUsageException(
"Unsupported annotated transaction on suspending function detected: " + method +
". Use TransactionalOperator.transactional extensions instead.");
}
ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(method.getReturnType());
if (adapter == null) {
throw new IllegalStateException("Cannot apply reactive transaction to non-reactive return type: " +
method.getReturnType());
}
return new ReactiveTransactionSupport(adapter);
});
return txSupport.invokeWithinTransaction(
method, targetClass, invocation, txAttr, (ReactiveTransactionManager) tm);
}
PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
// Standard transaction demarcation with getTransaction and commit/rollback calls.
TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);
Object retVal;
try {
// This is an around advice: Invoke the next interceptor in the chain.
// This will normally result in a target object being invoked.
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// target invocation exception
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
cleanupTransactionInfo(txInfo);
}
if (vavrPresent && VavrDelegate.isVavrTry(retVal)) {
// Set rollback-only in case of Vavr failure matching our rollback rules...
TransactionStatus status = txInfo.getTransactionStatus();
if (status != null && txAttr != null) {
retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
}
}
commitTransactionAfterReturning(txInfo);
return retVal;
}
else {
final ThrowableHolder throwableHolder = new ThrowableHolder();
// It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
try {
Object result = ((CallbackPreferringPlatformTransactionManager) ptm).execute(txAttr, status -> {
TransactionInfo txInfo = prepareTransactionInfo(ptm, txAttr, joinpointIdentification, status);
try {
Object retVal = invocation.proceedWithInvocation();
if (vavrPresent && VavrDelegate.isVavrTry(retVal)) {
// Set rollback-only in case of Vavr failure matching our rollback rules...
retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
}
return retVal;
}
catch (Throwable ex) {
if (txAttr.rollbackOn(ex)) {
// A RuntimeException: will lead to a rollback.
if (ex instanceof RuntimeException) {
throw (RuntimeException) ex;
}
else {
throw new ThrowableHolderException(ex);
}
}
else {
// A normal return value: will lead to a commit.
throwableHolder.throwable = ex;
return null;
}
}
finally {
cleanupTransactionInfo(txInfo);
}
});
// Check result state: It might indicate a Throwable to rethrow.
if (throwableHolder.throwable != null) {
throw throwableHolder.throwable;
}
return result;
}
catch (ThrowableHolderException ex) {
throw ex.getCause();
}
catch (TransactionSystemException ex2) {
if (throwableHolder.throwable != null) {
logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
ex2.initApplicationException(throwableHolder.throwable);
}
throw ex2;
}
catch (Throwable ex2) {
if (throwableHolder.throwable != null) {
logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
}
throw ex2;
}
}
}
三、@Async的AOP内部机制
1、@Async的AOP环境的建立
AsyncAnnotationBeanPostProcessor中的setBeanFactory创建AsyncAnnotationAdvisor
@Override
public void setBeanFactory(BeanFactory beanFactory) {
super.setBeanFactory(beanFactory);
Executor executorToUse = this.executor;
if (executorToUse == null) {
try {
// Search for TaskExecutor bean... not plain Executor since that would
// match with ScheduledExecutorService as well, which is unusable for
// our purposes here. TaskExecutor is more clearly designed for it.
// 从这可以看出,容器中只能有一个ThreadPoolTaskExecutor,当配置多个时候的会报错
executorToUse = beanFactory.getBean(TaskExecutor.class);
}
catch (NoUniqueBeanDefinitionException ex) {
try {
executorToUse = beanFactory.getBean(DEFAULT_TASK_EXECUTOR_BEAN_NAME, Executor.class);
}
catch (NoSuchBeanDefinitionException ex2) {
logger.info("More than one TaskExecutor bean found within the context, and none is " +
"named 'taskExecutor'. Mark one of them as primary or name it 'taskExecutor' " +
"(possibly as an alias) in order to use it for async annotation processing.");
}
}
catch (NoSuchBeanDefinitionException ex) {
logger.info("No TaskExecutor bean found for async annotation processing.");
// Giving up -> falling back to default executor within the advisor...
}
}
// executorToUse = ThreadPoolTaskExecutor
// 这里创建@Async的AOP环境。这个AOP环境其实就是【Advisor=Advice + Pointcut】
// AsyncAnnotationAdvisor = AnnotationAsyncExecutionInterceptor + ComposablePointcut
AsyncAnnotationAdvisor advisor = new AsyncAnnotationAdvisor(executorToUse, this.exceptionHandler);
if (this.asyncAnnotationType != null) {
advisor.setAsyncAnnotationType(this.asyncAnnotationType);
}
advisor.setBeanFactory(beanFactory);
this.advisor = advisor;
}
2、@Async注解的类创建代理对象的流程
Async注解的类的对象创建的入口【@Async所在的类要被创建代理对象的触发流程】
// @Async的处理逻辑逻辑(指的是,被@Async声明的类或者它的方法的bean对象创建并初始化完成后,是否要生成代理对象)[@Async注解的类在
// Spring中创建对象的initializeBean中的初始化完成后,由
// AsyncAnnotationBeanPostProcessor这个后置处理器处理]
@Override
AsyncAnnotationBeanPostProcessor::AbstractAdvisingBeanPostProcessor::postProcessAfterInitialization(
Object bean, String beanName) {
if (this.advisor == null || bean instanceof AopInfrastructureBean) {
// Ignore AOP infrastructure such as scoped proxies.
return bean;
}
if (bean instanceof Advised) {
Advised advised = (Advised) bean;
if (!advised.isFrozen() && isEligible(AopUtils.getTargetClass(bean))) {
// Add our local Advisor to the existing proxy's Advisor chain...
if (this.beforeExistingAdvisors) {
advised.addAdvisor(0, this.advisor);
}
else {
advised.addAdvisor(this.advisor);
}
return bean;
}
}
// A.1 判断是否要进行代理对象的创建
if (isEligible(bean, beanName)) {
ProxyFactory proxyFactory = prepareProxyFactory(bean, beanName);
if (!proxyFactory.isProxyTargetClass()) {
evaluateProxyInterfaces(bean.getClass(), proxyFactory);
}
proxyFactory.addAdvisor(this.advisor);
customizeProxyFactory(proxyFactory);
// 默认情况下,创建的JDKDynamicProxy的代理对象
return proxyFactory.getProxy(getProxyClassLoader());
}
// No proxy needed.
return bean;
}
/**
* Check whether the given class is eligible for advising with this
* post-processor's {@link Advisor}.
* <p>Implements caching of {@code canApply} results per bean target class.
* @param targetClass the class to check against
* @see AopUtils#canApply(Advisor, Class)
*/
AbstractAdvisingBeanPostProcessor::isEligible(Class<?> targetClass) {
Boolean eligible = this.eligibleBeans.get(targetClass);
if (eligible != null) {
return eligible;
}
if (this.advisor == null) {
return false;
}
// B.1 @Async匹配,判断Async的advisor是否能用于目标类
eligible = AopUtils.canApply(this.advisor, targetClass);
// 类似缓存了
this.eligibleBeans.put(targetClass, eligible);
return eligible;
}
/**
* Can the given pointcut apply at all on the given class?
* <p>This is an important test as it can be used to optimize
* out a pointcut for a class.
* @param pc the static or dynamic pointcut to check
* @param targetClass the class to test
* @param hasIntroductions whether or not the advisor chain
* for this bean includes any introductions
* @return whether the pointcut can apply on any method
*/
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
MethodMatcher methodMatcher = pc.getMethodMatcher();
if (methodMatcher == MethodMatcher.TRUE) {
// No need to iterate the methods if we're matching any method anyway...
return true;
}
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
Set<Class<?>> classes = new LinkedHashSet<>();
if (!Proxy.isProxyClass(targetClass)) {
classes.add(ClassUtils.getUserClass(targetClass));
}
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
for (Class<?> clazz : classes) {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
if (introductionAwareMethodMatcher != null ?
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
//此时,@Async被执行的是MethodMatchers.matches方法
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
3、@Async的执行代理对象的流程
当程序执行到@Async注解的方法时,会执行动态代理类中的重写的同名方法,如图所示:
3.1、JdkDynamicAopProxy的invoke方法
当程序执行到动态代理的同名方法,继续执行时,会走到这一步:
/**
* Implementation of {@code InvocationHandler.invoke}.
* <p>Callers will see exactly the exception thrown by the target,
* unless a hook method throws an exception.
*/
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
// this.advised = AsyncAnnotationAdvisor
// 什么时候被赋的值?在创建完ProxyFactory之后,proxyFactory.addAdvisor(this.advisor);
// 1. targetSource是代理对象
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// Service invocations on ProxyConfig with the proxy config...
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// Get as late as possible to minimize the time we "own" the target,
// in case it comes from a pool.
// 2. targetSource.getTarget是真正的目标对象
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// Get the interception chain for this method.
// 3. 从目标类中的该方法找到Advice,对于@Async来说,就是AnnotationAsyncExecutionInterceptor
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// Check whether we have any advice. If we don't, we can fallback on direct
// reflective invocation of the target, and avoid creating a MethodInvocation.
if (chain.isEmpty()) {
// We can skip creating a MethodInvocation: just invoke the target directly
// Note that the final invoker must be an InvokerInterceptor so we know it does
// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// 4. We need to create a method invocation...
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
retVal = invocation.proceed();
}
// Massage return value if necessary.
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// Special case: it returned "this" and the return type of the method
// is type-compatible. Note that we can't help if the target sets
// a reference to itself in another returned object.
retVal = proxy;
}
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
3.2、从目标类中的该方法找到Advice
由上述步骤3触发,在AdvisedSupport
/**
* Determine a list of {@link org.aopalliance.intercept.MethodInterceptor} objects
* for the given method, based on this configuration.
* @param method the proxied method
* @param targetClass the target class
* @return a List of MethodInterceptors (may also include InterceptorAndDynamicMethodMatchers)
*/
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
MethodCacheKey cacheKey = new MethodCacheKey(method);
List<Object> cached = this.methodCache.get(cacheKey);
if (cached == null) {
// 真正获取Advice的动作
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this, method, targetClass);
// 放到缓存中
this.methodCache.put(cacheKey, cached);
}
return cached;
}
3.2.1、真正获取Advise的动作
是由DefaultAdvisorChainFactory执行的
@Override
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass) {
// This is somewhat tricky... We have to process introductions first,
// but we need to preserve order in the ultimate list.
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
Advisor[] advisors = config.getAdvisors();
List<Object> interceptorList = new ArrayList<>(advisors.length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
Boolean hasIntroductions = null;
for (Advisor advisor : advisors) {
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
boolean match;
if (mm instanceof IntroductionAwareMethodMatcher) {
if (hasIntroductions == null) {
hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
}
match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
}
else {
// 获取@Async对应的切点的方法匹配器MethodMatchers
match = mm.matches(method, actualClass);
}
if (match) {
// 匹配成功,获取该Advisor的方法拦截器
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
if (mm.isRuntime()) {
// Creating a new object instance in the getInterceptors() method
// isn't a problem as we normally cache created chains.
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
3.2.2、匹配成功后,获取方法拦截器
在经过上述的方法匹配成功后,从DefaultAdvisorAdapterRegistry中获取该Advisor(AsyncAnnotationAdvisor)的方法拦截器
@Override
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList<>(3);
// 本例中,advisor = AsyncAnnotationAdvisor,其advice = AnnotationAsyncExecutionInterceptor
Advice advice = advisor.getAdvice();
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
// 这里再次应用了Adapter适配器模式
// this.adapters总共有三种适配器
// 1.MethodBeforeAdviceAdapter 2. AfterReturningAdviceAdapter 3. ThrowsAdviceAdapter
// 此处的AnnotationAsyncExecutionInterceptor 都不是上述三个
for (AdvisorAdapter adapter : this.adapters) {
if (adapter.supportsAdvice(advice)) {
interceptors.add(adapter.getInterceptor(advisor));
}
}
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
}
return interceptors.toArray(new MethodInterceptor[0]);
}
3.3、执行方法拦截器
获取完方法拦截器后,继续下一步。执行3.1中的第四步,在ReflectiveMethodInvocation中执行。
@Override
@Nullable
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
}
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
// 执行该Advisor(AsyncAnnotationAdvisor)的方法拦截器(AnnotationAsyncExecutionInterceptor
// )中的invoke方法
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
3.4、AnnotationAsyncExecutionInterceptor拦截器的invoke方法执行
以上过程,演示了@Async的方法拦截器如何被调用执行的,执行是在AsyncExecutionInterceptor中。
/**
* Intercept the given method invocation, submit the actual calling of the method to
* the correct task executor and return immediately to the caller.
* @param invocation the method to intercept and make asynchronous
* @return {@link Future} if the original method returns {@code Future}; {@code null}
* otherwise.
*/
@Override
@Nullable
public Object invoke(final MethodInvocation invocation) throws Throwable {
// 1. 获取目标类
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
Method specificMethod = ClassUtils.getMostSpecificMethod(invocation.getMethod(), targetClass);
final Method userDeclaredMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
// 2. 获取异步任务执行器
AsyncTaskExecutor executor = determineAsyncExecutor(userDeclaredMethod);
if (executor == null) {
throw new IllegalStateException(
"No executor specified and no default executor set on AsyncExecutionInterceptor either");
}
// 3. 创建回调任务
Callable<Object> task = () -> {
try {
Object result = invocation.proceed();
if (result instanceof Future) {
return ((Future<?>) result).get();
}
}
catch (ExecutionException ex) {
handleError(ex.getCause(), userDeclaredMethod, invocation.getArguments());
}
catch (Throwable ex) {
handleError(ex, userDeclaredMethod, invocation.getArguments());
}
return null;
};
// 4. 向线程池中提交回调任务,在其父类AsyncExecutionAspectSupport中
return doSubmit(task, executor, invocation.getMethod().getReturnType());
}
// 获取异步执行器
/**
* Determine the specific executor to use when executing the given method.
* Should preferably return an {@link AsyncListenableTaskExecutor} implementation.
* @return the executor to use (or {@code null}, but just if no default executor is available)
*/
@Nullable
protected AsyncTaskExecutor determineAsyncExecutor(Method method) {
AsyncTaskExecutor executor = this.executors.get(method);
if (executor == null) {
Executor targetExecutor;
// @Async注解的属性值value。即定义的ThreadPoolTaskExecutor的beanName
String qualifier = getExecutorQualifier(method);
if (StringUtils.hasLength(qualifier)) {
targetExecutor = findQualifiedExecutor(this.beanFactory, qualifier);
}
else {
// 这个赋值时机在创建AnnotationAsyncExecutionInterceptor时赋值
targetExecutor = this.defaultExecutor.get();
}
if (targetExecutor == null) {
return null;
}
executor = (targetExecutor instanceof AsyncListenableTaskExecutor ?
(AsyncListenableTaskExecutor) targetExecutor : new TaskExecutorAdapter(targetExecutor));
// 相当于放在缓存中,以后再次进入,直接获取。不需要再经过查找
this.executors.put(method, executor);
}
return executor;
}
3.5、@Async的异步线程
子类AsyncExecutionIntercptor中提交自己创建的回调任务。
/**
* Delegate for actually executing the given task with the chosen executor.
* @param task the task to execute
* @param executor the chosen executor
* @param returnType the declared return type (potentially a {@link Future} variant)
* @return the execution result (potentially a corresponding {@link Future} handle)
*/
@Nullable
protected Object doSubmit(Callable<Object> task, AsyncTaskExecutor executor, Class<?> returnType) {
if (CompletableFuture.class.isAssignableFrom(returnType)) {
return CompletableFuture.supplyAsync(() -> {
try {
return task.call();
}
catch (Throwable ex) {
throw new CompletionException(ex);
}
}, executor);
}
else if (ListenableFuture.class.isAssignableFrom(returnType)) {
// 提交创建的回调任务
// 这里需要注意,在对方法使用@Async注解的时候,如果该异步方法有返回值,返回类型只能是Future<?>这种
// <?>这里的?可以指定具体的返回类型
// 创建的异步结果用 return new AsyncResult<?>(result);
// 注意:如果把该方法的返回结果声明为AsyncResult 会报ClassCastException。
// org.springframework.util.concurrent.ListenableFutureTask cannot be cast to
// org.springframework.scheduling.annotation.AsyncResult
// 因为创建的异步任务,执行的是这里
return ((AsyncListenableTaskExecutor) executor).submitListenable(task);
}
else if (Future.class.isAssignableFrom(returnType)) {
// 如果声明的返回类型为Future<?>这种,则就会执行这个提交任务
return executor.submit(task);
}
else {
executor.submit(task);
return null;
}
}
3.6、AsyncAnnotationAdvisor的依赖
该类中两个重要的property:
Advice = AnnotationAsyncExecutionInterceptor
Pointcut = ComposablePointcut
3.7 AsyncAnnotationAdvisor在Spring AOP中扮演的角色及作用
这个通知通过@Async注解激活异步方法的执行。在类或者接口或者方法都可以使用。也会检测EJB3.1的javax.ejb.Asynchronous的注解,就跟@Async效果一样。创建该Advisor代码:
/**
* Create a new {@code AsyncAnnotationAdvisor} for the given task executor.
* @param executor the task executor to use for asynchronous methods
* (can be {@code null} to trigger default executor resolution)
* @param exceptionHandler the {@link AsyncUncaughtExceptionHandler} to use to
* handle unexpected exception thrown by asynchronous method executions
* @see AnnotationAsyncExecutionInterceptor#getDefaultExecutor(BeanFactory)
*/
@SuppressWarnings("unchecked")
public AsyncAnnotationAdvisor(@Nullable Executor executor, @Nullable AsyncUncaughtExceptionHandler exceptionHandler) {
Set<Class<? extends Annotation>> asyncAnnotationTypes = new LinkedHashSet<>(2);
asyncAnnotationTypes.add(Async.class);
try {
asyncAnnotationTypes.add((Class<? extends Annotation>)
ClassUtils.forName("javax.ejb.Asynchronous", AsyncAnnotationAdvisor.class.getClassLoader()));
}
catch (ClassNotFoundException ex) {
// If EJB 3.1 API not present, simply ignore.
}
if (exceptionHandler != null) {
this.exceptionHandler = exceptionHandler;
}
else {
this.exceptionHandler = new SimpleAsyncUncaughtExceptionHandler();
}
// 创建Advice
this.advice = buildAdvice(executor, this.exceptionHandler);
// 创建PointCut
this.pointcut = buildPointcut(asyncAnnotationTypes);
}
@Aspect的执行机制,及执行过程中,更好理解之前创建的各个类的角色及作用
基础结构类infrastructure class 永远不会被代理,比如org.springframework.transaction.config.internalTransactionAdvisor。
在创建该对象的时候,通过debug,重新理解了BeanFactory的singletonsCurrentlyInCreation这个对象集合所存在的意义。
Q:为什么在实际创建对象getSingleton(beanName, ObjectFactory)之前,要先做标记为已创建该对象的操作。
A:以Spring AOP来说,防止已经创建过的bean对象又被AOP代理的过程中再次创建该对象。
Spring AOP 中的基础数据结构
advisedBeans
private final Map<Object, Boolean> advisedBeans = new ConcurrentHashMap<Object, Boolean>(256);
存放所有被Spring容器管理的对象,并且判断他们是否需要被Spring AOP所代理。
Advisor在Spring AOP中扮演的角色及作用
Spring AOP 是基于环绕通知around advice来拦截方法传递的,支持各种类型的通知,诸如前置before通知和后置after通知,这两个通知都不需要通过使用拦截器interception来实现。容纳Advice和Pointcut。
==拦截器 Interceptor extends Advice ==
PointcutAdvisor在Spring AOP中扮演的角色及作用
基于切点pointcut驱动的所有通知的父接口。这包含了几乎所有的通知,除了不使用方法级别匹配的引入通知introduction advisors。
AbstractPointcutAdvisor在Spring AOP中扮演的角色及作用
该类的子类返回指定类型的切点pointcut或者通知advisor。
Spring AOP中的编码规范
- 用语义代替null值,便于理解代码场景,尽量减少代码中的object == null 这种判断。
/**
* Wrap the given bean if necessary, i.e. if it is eligible for being proxied.
* @param bean the raw bean instance
* @param beanName the name of the bean
* @param cacheKey the cache key for metadata access
* @return a proxy wrapping the bean, or the raw bean instance as-is
*/
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (beanName != null && 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.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
// DO_NOT_PROXY 其实就为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;
}
以用户操作日志为例,来说明Spring AOP如何起作用
需求描述:有一个管理系统,我们现在需要对用户的各种操作进行日志记录。首先,联想到的就是利用Spring AOP来完成各种增删改的日志切面。以LoginController的login()为例。
当用户第一次点击登录时,Spring在后台是这样处理的(不包含shiro校验的分析):
调用getBean创建LoginController对象,在创建bean对象的initializeBean中用AnnotationAwareAspectJAutoProxyCreator Bean处理器完成LoginController代理对象的创建。
这个bean后置处理器,找到能够处理LoginController.class的Advisor【怎么去理解Advisor,其实就是包含了切点跟切入方法。所以,一个切面类,有几个切面方法,就有几个对应的Advisor】,在这个过程中,创建了LoginController的代理对象。
当用户再次请求时,走Spring MVC的流程,反射执行方法,注意:执行的是代理对象增强后的login方法。代理对象重写了login方法,当执行的时候,会被拦截。
总结:
- Spring AOP中Advice ,PointCut, Advisor的三者之间的关系:Advisor = Advice + PointCut
- 自定义一个基于Spring AOP的Advisor
- 实现一个继承AbstractPointcutAdvisor的Advisor,如果需要使用IOC容器,外加BeanFactoryAware
- 实现对应的Advice,通常来说,该Advice,会是一个MethodInterceptor
- 创建一个ComposabelPointCut
- MethodInterceptor 不等于Advice,因为,Advice还包括BeforeAdvice,AfterAdvice,AfterReturningAdvice
- @Transactional和@Async,不同之处在于,@Transactional是被AnnotationAwareAspectJAutoProxyCreator处理的,而@Async是被AsyncAnnotationBeanPostProcessor处理的。