@EnableAsync
上述注解的作用是注册了一个Bean,而这个bean实现了BeanPostProcessor
接口,可以参与Bean的初始化。
...
@Import(AsyncConfigurationSelector.class)
public @interface EnableAsync {
Class extends Annotation> annotation() default Annotation.class;
boolean proxyTargetClass() default false;
AdviceMode mode() default AdviceMode.PROXY;
int order() default Ordered.LOWEST_PRECEDENCE;
}
该注解可以定义一些属性,且“导入”了一个AsyncConfigurationSelector
。
该类会注册ProxyAsyncConfiguration
。
public class AsyncConfigurationSelector extends AdviceModeImportSelector {
private static final String ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME =
"org.springframework.scheduling.aspectj.AspectJAsyncConfiguration";
@Override
@Nullable
public String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:
return new String[] {ProxyAsyncConfiguration.class.getName()};
case ASPECTJ:
return new String[] {ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME};
default:
return null;
}
}
}
即注册了AsyncAnnotationBeanPostProcessor
,可以完成bean的代理。
@Configuration
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyAsyncConfiguration extends AbstractAsyncConfiguration {
@Bean(name = TaskManagementConfigUtils.ASYNC_ANNOTATION_PROCESSOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public AsyncAnnotationBeanPostProcessor asyncAdvisor() {
Assert.notNull(this.enableAsync, "@EnableAsync annotation metadata was not injected");
AsyncAnnotationBeanPostProcessor bpp = new AsyncAnnotationBeanPostProcessor();
bpp.configure(this.executor, this.exceptionHandler);
Class extends Annotation> customAsyncAnnotation = this.enableAsync.getClass("annotation");
if (customAsyncAnnotation != AnnotationUtils.getDefaultValue(EnableAsync.class, "annotation")) {
bpp.setAsyncAnnotationType(customAsyncAnnotation);
}
bpp.setProxyTargetClass(this.enableAsync.getBoolean("proxyTargetClass"));
bpp.setOrder(this.enableAsync.getNumber("order"));
return bpp;
}
}
AsyncAnnotationBeanPostProcessor
完成的代理工作,但是如下图所示,代理工作是在父类中完成的。AsyncAnnotationBeanPostProcessor
仅仅实现的是setBeanFactory
方法。在此方法中,定义了AsyncAnnotationAdvisor
增强器。
AbstractBeanFactoryAwareAdvisingPostProcessor
又实现了那些方法?AbstractAdvisingBeanPostProcessor
两个方法,大概作用就是筛选“合格”的Advisor
以及处理代理工厂ProxyFactory
。AbstractAdvisingBeanPostProcessor
才是实现bean代理的核心方法。代理的实现,依赖的是AbstractAdvisingBeanPostProcessor
实现的BeanPostProcessor
定义的方法。
在上文中,由于多个自动代理器
均代理同一个bean时,可能存在bean的二次代理问题。当然AbstractAdvisingBeanPostProcessor
明显考虑到这个问题。
从Spring命名分析:AbstractAdvisingBeanPostProcessor抽象增强后置处理器。
而事务依赖AbstractAutoProxyCreator抽象的自动代理处理器。
即
AbstractAdvisingBeanPostProcessor
发现bean是代理对象时,直接增加Advisor
。而AbstractAutoProxyCreator
发现bean是代理对象时,会发生二次代理。
public abstract class AbstractAdvisingBeanPostProcessor extends ProxyProcessorSupport implements BeanPostProcessor {
//定义了增强器,由子类setBeanFactory实现。
@Nullable
protected Advisor advisor;
protected boolean beforeExistingAdvisors = false;
//将“合格”的Bean缓存下来,value=true;
private final Map, Boolean> eligibleBeans = new ConcurrentHashMap(256);
public void setBeforeExistingAdvisors(boolean beforeExistingAdvisors) {
this.beforeExistingAdvisors = beforeExistingAdvisors;
}
//并未实现Bean,直接返回。
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
//完成代理
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (this.advisor == null || bean instanceof AopInfrastructureBean) {
// Ignore AOP infrastructure such as scoped proxies.
return bean;
}
//代理对象实现了Advised接口,那么直接增加Advisor即可。
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;
}
}
//若不是代理对象,判断该bean是是否可以被增强器增强?(该方法是父类实现)
if (isEligible(bean, beanName)) {
//获取代理工厂,创建代理
ProxyFactory proxyFactory = prepareProxyFactory(bean, beanName);
if (!proxyFactory.isProxyTargetClass()) {
evaluateProxyInterfaces(bean.getClass(), proxyFactory);
}
proxyFactory.addAdvisor(this.advisor);
customizeProxyFactory(proxyFactory);
return proxyFactory.getProxy(getProxyClassLoader());
}
return bean;
}
//判断bean是否能被增强?(该方法由子类实现)
protected boolean isEligible(Object bean, String beanName) {
return isEligible(bean.getClass());
}
protected boolean isEligible(Class> targetClass) {
Boolean eligible = this.eligibleBeans.get(targetClass);
if (eligible != null) {
return eligible;
}
if (this.advisor == null) {
return false;
}
//判断bean能否使用advisor增强?
eligible = AopUtils.canApply(this.advisor, targetClass);
this.eligibleBeans.put(targetClass, eligible);
return eligible;
}
//预处理ProxyFactory对象(该方法由子类实现)
protected ProxyFactory prepareProxyFactory(Object bean, String beanName) {
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
proxyFactory.setTarget(bean);
return proxyFactory;
}
//自定义处理代理工厂
protected void customizeProxyFactory(ProxyFactory proxyFactory) {
}
}
当然,我们使用了@Async
使用的是AsyncAnnotationBeanPostProcessor
完成处理,由2中分析,我们可知子类重写了isEligible
/prepareProxyFactory
/setBeanFactory
方法。继续分析子类重写的方法。
Spring提供了一个工具方法,AopUtils.canApply()
方法,当然,这个方法以及可以脱离Spring容器使用:
@Test
public void test2(){
//定义一个Advisor
DefaultPointcutAdvisor advisor=new DefaultPointcutAdvisor();
NameMatchMethodPointcut pointcut=new NameMatchMethodPointcut();
pointcut.addMethodName("run*");
//设置切点
advisor.setPointcut(pointcut);
System.out.println(AopUtils.canApply(advisor, TService.class));
System.out.println(AopUtils.canApply(advisor, XUserService.class));
}
@Aysnc校验bean流程
将源码关键部分抽取出来,重点分析 Spring如何校验bean是否能被@Async
增强。
public class MyBeanFactoryAware implements BeanFactoryAware {
@Nullable
private ConfigurableListableBeanFactory beanFactory;
private Advisor advisor;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = (beanFactory instanceof ConfigurableListableBeanFactory ?
(ConfigurableListableBeanFactory) beanFactory : null);
//默认为null
AsyncAnnotationAdvisor advisor = new AsyncAnnotationAdvisor();
advisor.setBeanFactory(beanFactory);
this.advisor=advisor;
}
//注解的自动代理
public boolean isEligible(Class> targetClass){
return AopUtils.canApply(advisor,targetClass);
}
}
@Configurable
public class MyConfig {
@Bean
public MyBeanFactoryPostProcessor myBeanFactoryPostProcessor(){
return new MyBeanFactoryPostProcessor();
}
}
@Slf4j
public class TestProxyDemo {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicatiOnContext=
new AnnotationConfigApplicationContext(MyConfig.class);
MyBeanFactoryAware myBeanFactoryAware = (MyBeanFactoryAware)applicationContext.getBean("myBeanFactoryAware");
boolean eligible = myBeanFactoryAware.isEligible(TService.class);
boolean uS = myBeanFactoryAware.isEligible(UService.class);
System.out.println(eligible);
System.out.println(uS);
}
}
启动项目,查看bean是否能被增强。
校验方法或类上是否存在@Async注解。
源码位置:org.springframework.aop.support.MethodMatchers.UnionMethodMatcher
@Override
public boolean matches(Method method, Class> targetClass) {
//(判断类上是否存在@Async注解 && 默认true)||(判断target是否是候选bean&& 判断方法上是否存在@Async注解)
return (matchesClass1(targetClass) && this.mm1.matches(method, targetClass)) ||
(matchesClass2(targetClass) && this.mm2.matches(method, targetClass));
}
matchesClass1(targetClass)方法
使用org.springframework.aop.support.annotation.AnnotationClassFilter#matches
进行验证类上是否存在@Async
注解?
@Override
public boolean matches(Class> clazz) {
return (this.checkInherited ? AnnotatedElementUtils.hasAnnotation(clazz, this.annotationType) :
clazz.isAnnotationPresent(this.annotationType));
}
checkInherited
意思是是否检查父类上存在注解?默认true
@Test
public void test5(){
//@Async注解在IAccount上;
System.out.println(AnnotatedElementUtils.hasAnnotation(AccountImpl.class, Async.class)); //true
System.out.println(AccountImpl.class.isAnnotationPresent(Async.class)); //false
}
this.mm2.matches(method, targetClass)
源码:org.springframework.aop.support.annotation.AnnotationMethodMatcher#matches
@Override
public boolean matches(Method method, Class> targetClass) {
//该方法和AnnotationClassFilter#matches代码相同;
if (matchesMethod(method)) {
return true;
}
//如果target是代理对象,直接返回false,即不能再次代理;
if (Proxy.isProxyClass(targetClass)) {
return false;
}
// The method may be on an interface, so let's check on the target class as well.
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
return (specificMethod != method && matchesMethod(specificMethod));
}
AbstractAdvisingBeanPostProcessor
是一个增强BeanPostProcessor
,在处理器内部定义了Advisor
。
是在org.springframework.scheduling.annotation.AsyncAnnotationBeanPostProcessor#setBeanFactory
该方法中定义了Advisor。
public void setBeanFactory(BeanFactory beanFactory) {
super.setBeanFactory(beanFactory);
AsyncAnnotationAdvisor advisor = new AsyncAnnotationAdvisor(this.executor, this.exceptionHandler);
if (this.asyncAnnotationType != null) {
advisor.setAsyncAnnotationType(this.asyncAnnotationType);
}
advisor.setBeanFactory(beanFactory);
this.advisor = advisor;
}
源码:org.springframework.aop.framework.autoproxy.AbstractBeanFactoryAwareAdvisingPostProcessor
配置ProxyFactory
,以便生成Proxy代理对象。
@Override
protected ProxyFactory prepareProxyFactory(Object bean, String beanName) {
if (this.beanFactory != null) {
AutoProxyUtils.exposeTargetClass(this.beanFactory, beanName, bean.getClass());
}
ProxyFactory proxyFactory = super.prepareProxyFactory(bean, beanName);
if (!proxyFactory.isProxyTargetClass() && this.beanFactory != null &&
AutoProxyUtils.shouldProxyTargetClass(this.beanFactory, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
return proxyFactory;
}
protected ProxyFactory prepareProxyFactory(Object bean, String beanName) {
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
proxyFactory.setTarget(bean);
return proxyFactory;
}
this
对象即AsyncAnnotationBeanPostProcessor。因为实现了ProxyConfig
接口(代理配置类)。所以可以影响ProxyFactory
的创建过程。
当然,开发者可以修改AsyncAnnotationBeanPostProcessor
的BeanDefinition,定义Proxy对象。
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition beanDefinition =
beanFactory.getBeanDefinition(TaskManagementConfigUtils.ASYNC_ANNOTATION_PROCESSOR_BEAN_NAME);
beanDefinition.getPropertyValues().add("exposeProxy", true);
}
}