为什么@Async注解会存在循环问题?
参考:https://juejin.cn/post/6844904048001286158;
参考:https://cloud.tencent.com/developer/article/1497689
从中可知@Async产生循环依赖的原因: 对于AOP解决循环依赖的思路是: AnnotationAwareAspectJAutoProxyCreator是AOP处理类,实现了SmartInstantiationAwareBeanPostProcessor接口,利用getEarlyBeanReference可以实现AOP代理对象,后置处理postProcessAfterInitialization方法中发现这个对象已经进行过代理,因此就不再处理。
@Async 处理类AsyncAnnotationBeanPostProcessor,没有实现SmartInstantiationAwareBeanPostProcessor接口,它对循环依赖的处理并不像AnnotationAwareAspectJAutoProxyCreator一样,放到三级缓存的 ObjectFactory对象可以利用getEarlyBeanReference可以识别AOP并且产生代理对象,@Async只有在postProcessAfterInitialization方法中产生代理;如下图代码,生成A bean对象,按照bean的生命周期
- 先实例化A对象ObjectFactoryA放到三级缓存中
- A开始对象开始对属性B赋值,B先实例化,然后对属性A赋值,先从三级缓存ObjectFactoryA开始执行 getEarlyBeanReference方法,由于没有实现SmartInstantiationAwareBeanPostProcessor接 口,获取的是原始的对象A;
- 后面A继续初始化,会执行AsyncAnnotationBeanPostProcessor的 postProcessAfterInitialization方法,最终得到是一个代理对象proxyA,和2中的对象A不是同一 个对象
@Service public class A implements AInterface {
@Autowired
private BInterface b;
@Async
@Override
public void funA() {
}
}
@Service public class B implements BInterface {
@Autowired private AInterface a;
@Override
public void funB() {
a.funA();
}
}
@Async是否能和AOP一样解决循环依赖问题
查看@Transactional的处理是通过TransactionInterceptor的invoke方法处理的,前提是先设置Advice的拦截器,
@Async 是否也可以这样处理?我尝试自定义注解实现下
定义注解@AsyncT
@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface AsyncT {
String value() default "";
}
写一个方法增强拦截器,参考spring的AsyncExecutionInterceptor实现 `
@Slf4j
@Component
public class AsyncTInterceptor implements MethodInterceptor, Ordered, BeanFactoryAware {
@Nullable
private BeanFactory beanFactory;
private final Map<Method, AsyncTaskExecutor> executors = new ConcurrentHashMap<>(16);
@Override
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
Method specificMethod = ClassUtils.getMostSpecificMethod(invocation.getMethod(), targetClass);
final Method userDeclaredMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
AsyncTaskExecutor executor = determineAsyncExecutor(userDeclaredMethod);
if (executor == null) {
throw new IllegalStateException(
"No executor specified and no default executor set on AsyncExecutionInterceptor either");
}
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;
};
return doSubmit(task, executor, invocation.getMethod().getReturnType());
}
protected void handleError(Throwable ex, Method method, Object... params) throws Exception {
log.error(" AsyncTInterceptor handleError execute failed:{}", ex);
if (Future.class.isAssignableFrom(method.getReturnType())) {
ReflectionUtils.rethrowException(ex);
}
}
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
}
@Nullable
protected AsyncTaskExecutor determineAsyncExecutor(Method method) {
AsyncTaskExecutor executor = this.executors.get(method);
if (executor == null) {
Executor targetExecutor;
String qualifier = getExecutorQualifier(method);
if (StringUtils.hasLength(qualifier)) {
targetExecutor = findQualifiedExecutor(this.beanFactory, qualifier);
}
else {
//没有默认值
targetExecutor = null;
}
if (targetExecutor == null) {
return null;
}
executor = (targetExecutor instanceof AsyncListenableTaskExecutor ?
(AsyncListenableTaskExecutor) targetExecutor : new TaskExecutorAdapter(targetExecutor));
this.executors.put(method, executor);
}
return executor;
}
@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)) {
return ((AsyncListenableTaskExecutor) executor).submitListenable(task);
}
else if (Future.class.isAssignableFrom(returnType)) {
return executor.submit(task);
}
else {
executor.submit(task);
return null;
}
}
@Nullable
protected String getExecutorQualifier(Method method) {
// Maintainer's note: changes made here should also be made in
// AnnotationAsyncExecutionAspect#getExecutorQualifier
Async async = AnnotatedElementUtils.findMergedAnnotation(method, Async.class);
if (async == null) {
async = AnnotatedElementUtils.findMergedAnnotation(method.getDeclaringClass(), Async.class);
}
return (async != null ? async.value() : null);
}
@Nullable
protected Executor findQualifiedExecutor(@Nullable BeanFactory beanFactory, String qualifier) {
if (beanFactory == null) {
throw new IllegalStateException("BeanFactory must be set on " + getClass().getSimpleName() +
" to access qualified executor '" + qualifier + "'");
}
return BeanFactoryAnnotationUtils.qualifiedBeanOfType(beanFactory, Executor.class, qualifier);
}
}
`
加入拦截器
@Configuration
public class InterceptorConfig {
public static final String traceExecution = "@annotation(xx.annotation.AsyncT)";//自己包路径
@Resource
private AsyncTInterceptor asyncTaskInterceptor;
@Bean
public DefaultPointcutAdvisor asyncTaskAdvisor() {
DefaultPointcutAdvisor asyncTaskAdvisor = new DefaultPointcutAdvisor()
asyncTaskAdvisor.setPointcut(getPointcut());
asyncTaskAdvisor.setAdvice(asyncTaskInterceptor);
return asyncTaskAdvisor;
}
private Pointcut getPointcut() {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression(traceExecution);
return pointcut;
}
}
测试是可以成功的,这里就不贴测试代码了,偷懒,在项目中是可以运行的,自己动手多dubug就行