一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第27天,点击查看活动详情。
2.2.6、ComposablePointcut切点
AnnotationMatchingPointcut : 针对于指定的类上注解、方法上注解 。依不同构造方法的入参来指定注解类型 ComposablePointcut : 组合用法。 可以(intersection 交集 或 union 并集)多个pointcut, ClassFilter、 MethodMatcher
ComposablePointcut result = null;
for (Class<? extends Annotation> asyncAnnotationType : asyncAnnotationTypes) {
Pointcut cpc = new AnnotationMatchingPointcut(asyncAnnotationType, true);
Pointcut mpc = new AnnotationMatchingPointcut(null, asyncAnnotationType, true);
if (result == null) {
result = new ComposablePointcut(cpc);
}
else {
result.union(cpc);
}
result = result.union(mpc);
}
return (result != null ? result : Pointcut.TRUE);
}
对于单个pointcut由MethodMatcher (方法匹配)与 ClassFilter (类匹配)组合构成。
2.2.7、调用入口
回到AsyncAnnotationBeanPostProcessor,其父类AbstractBeanFactoryAwareAdvisingPostProcessor不仅仅继承BeanFactoryAware, 而且还实现了BeanPostProcessor接口!
PS: 后置处理器,在Spring容器的创建过程中(具体为Bean初始化前后)会回调BeanPostProcessor中定义的两个方法 在执行postProcessAfterInitialization方法内, 通过isEligible 方法对bean进行判定是否需要构建代理
public Object 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;
}
}
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());
}
// No proxy needed.
return bean;
}
会优先通过Pointcut的ClassFilter进行判定, 其次是MethodMatcher!
2.3、总结
@Async注解使用默认模式时,本质是代理,动态代理就是在运行期间,动态的生成了一个class在 jvm 中,然后通过这个class的实例调用真正的实现类的方法,所以必须获取被代理对象,代理才能生效;
如下方式会使@Async失效:
- 异步方法使用static修饰
- 异步类没有使用@Component注解(或其他注解)导致spring无法扫描到异步类
- 异步方法不能与被调用的异步方法在同一个类中
- 类中需要使用@Autowired或@Resource等注解自动注入,不能自己手动new对象
- 如果使用SpringBoot框架必须在启动类 or 配置类中增加@EnableAsync注解