开启异步调用只需一个注解@EnableAsync

  1. @Target(ElementType.TYPE)
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Documented
  4. @Import(AsyncConfigurationSelector.class)
  5. public @interface EnableAsync {
  6. /**
  7. * Indicate the 'async' annotation type to be detected at either class
  8. * or method level.
  9. * <p>By default, both Spring's @{@link Async} annotation and the EJB 3.1
  10. * {@code @javax.ejb.Asynchronous} annotation will be detected.
  11. * <p>This attribute exists so that developers can provide their own
  12. * custom annotation type to indicate that a method (or all methods of
  13. * a given class) should be invoked asynchronously.
  14. */
  15. Class<? extends Annotation> annotation() default Annotation.class;
  16. /**
  17. * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
  18. * to standard Java interface-based proxies.
  19. * <p><strong>Applicable only if the {@link #mode} is set to {@link AdviceMode#PROXY}</strong>.
  20. * <p>The default is {@code false}.
  21. * <p>Note that setting this attribute to {@code true} will affect <em>all</em>
  22. * Spring-managed beans requiring proxying, not just those marked with {@code @Async}.
  23. * For example, other beans marked with Spring's {@code @Transactional} annotation
  24. * will be upgraded to subclass proxying at the same time. This approach has no
  25. * negative impact in practice unless one is explicitly expecting one type of proxy
  26. * vs. another &mdash; for example, in tests.
  27. */
  28. boolean proxyTargetClass() default false;
  29. /**
  30. * Indicate how async advice should be applied.
  31. * <p><b>The default is {@link AdviceMode#PROXY}.</b>
  32. * Please note that proxy mode allows for interception of calls through the proxy
  33. * only. Local calls within the same class cannot get intercepted that way; an
  34. * {@link Async} annotation on such a method within a local call will be ignored
  35. * since Spring's interceptor does not even kick in for such a runtime scenario.
  36. * For a more advanced mode of interception, consider switching this to
  37. * {@link AdviceMode#ASPECTJ}.
  38. */
  39. AdviceMode mode() default AdviceMode.PROXY;
  40. /**
  41. * Indicate the order in which the {@link AsyncAnnotationBeanPostProcessor}
  42. * should be applied.
  43. * <p>The default is {@link Ordered#LOWEST_PRECEDENCE} in order to run
  44. * after all other post-processors, so that it can add an advisor to
  45. * existing proxies rather than double-proxy.
  46. */
  47. int order() default Ordered.LOWEST_PRECEDENCE;
  48. }

  AsyncConfigurationSelector的作用是从两个异步配置类中选择一个来完成底层异步代理的工作。这个两个配置类分别是AspectJAsyncConfiguration、ProxyAsyncConfiguration。

  1. @Override
  2. @Nullable
  3. public String[] selectImports(AdviceMode adviceMode) {
  4. switch (adviceMode) {
  5. case PROXY:
  6. return new String[] {ProxyAsyncConfiguration.class.getName()};
  7. case ASPECTJ:
  8. return new String[] {ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME};
  9. default:
  10. return null;
  11. }
  12. }

  其中adviceMode就是@EnableAsync注解中mode()方法的值,默认是”PROXY”。接下来着重看一下ProxyAsyncConfiguration做了哪些事情。

  1. @Configuration
  2. @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
  3. public class ProxyAsyncConfiguration extends AbstractAsyncConfiguration {
  4. @Bean(name = TaskManagementConfigUtils.ASYNC_ANNOTATION_PROCESSOR_BEAN_NAME)
  5. @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
  6. public AsyncAnnotationBeanPostProcessor asyncAdvisor() {
  7. Assert.notNull(this.enableAsync, "@EnableAsync annotation metadata was not injected");
  8. AsyncAnnotationBeanPostProcessor bpp = new AsyncAnnotationBeanPostProcessor();
  9. bpp.configure(this.executor, this.exceptionHandler);
  10. Class<? extends Annotation> customAsyncAnnotation = this.enableAsync.getClass("annotation");
  11. if (customAsyncAnnotation != AnnotationUtils.getDefaultValue(EnableAsync.class, "annotation")) {
  12. bpp.setAsyncAnnotationType(customAsyncAnnotation);
  13. }
  14. bpp.setProxyTargetClass(this.enableAsync.getBoolean("proxyTargetClass"));
  15. bpp.setOrder(this.enableAsync.<Integer>getNumber("order"));
  16. return bpp;
  17. }
  18. }

  ProxyAsyncConfiguration主要是创建了一个基于异步调用的后置处理器(AsyncAnnotationBeanPostProcessor),改BPP中设置了executor(异步线程池)、exceptionHandler(异常处理器)、AsyncAnnotationType(异步注解类型)、proxyTargetClass(代理创建模式)、order(后置处理器执行顺序)。那么executor和exceptionHandler是哪里来的呢、默认值是什么?接着继续向父集探索。

  1. @Configuration
  2. public abstract class AbstractAsyncConfiguration implements ImportAware {
  3. .....
  4. /**
  5. * Collect any {@link AsyncConfigurer} beans through autowiring.
  6. */
  7. @Autowired(required = false)
  8. void setConfigurers(Collection<AsyncConfigurer> configurers) {
  9. if (CollectionUtils.isEmpty(configurers)) {
  10. return;
  11. }
  12. if (configurers.size() > 1) {
  13. throw new IllegalStateException("Only one AsyncConfigurer may exist");
  14. }
  15. AsyncConfigurer configurer = configurers.iterator().next();
  16. this.executor = configurer::getAsyncExecutor;
  17. this.exceptionHandler = configurer::getAsyncUncaughtExceptionHandler;
  18. }
  19. }

  由此可见,executor和exceptionHandler可以通过AsyncConfigurer自定义配置。需要注意的是,spring容器中只能有一个AsyncConfigurer类型的实例呦。

  进入异步实现的正题了,当然是好好研究一下AsyncAnnotationBeanPostProcessor这个后置处理做了哪些事情了。

  1. public class AsyncAnnotationBeanPostProcessor extends AbstractBeanFactoryAwareAdvisingPostProcessor {
  2. ....
  3. @Override
  4. public void setBeanFactory(BeanFactory beanFactory) {
  5. super.setBeanFactory(beanFactory);
  6. AsyncAnnotationAdvisor advisor = new AsyncAnnotationAdvisor(this.executor, this.exceptionHandler);
  7. if (this.asyncAnnotationType != null) {
  8. advisor.setAsyncAnnotationType(this.asyncAnnotationType);
  9. }
  10. advisor.setBeanFactory(beanFactory);
  11. this.advisor = advisor;
  12. }
  13. }

  1、添加一个AOP advisor(AsyncAnnotationAdvisor),识别带有@Async注解或者指定类型注解的方法,创建代理类。

  2、找一个合适的TaskExecutor来异步调用带有@Async注解或者指定类型注解的方法。

  3、如果方法在异步调用过程中抛出异常,将使用合适的ExceptionHandler进行处理。

  看到这里,已经有两个疑问了。AsyncAnnotationAdvisor做了什么?如何创建的异步调用代理类?

  大家都知道,Spring Aop中,一个advisor包含一个advice(通知)、pointcut(切点)。

  创建advice

  1. protected Advice buildAdvice(
  2. @Nullable Supplier<Executor> executor, @Nullable Supplier<AsyncUncaughtExceptionHandler> exceptionHandler) {
  3. AnnotationAsyncExecutionInterceptor interceptor = new AnnotationAsyncExecutionInterceptor(null);
  4. interceptor.configure(executor, exceptionHandler);
  5. return interceptor;
  6. }

  AnnotationAsyncExecutionInterceptor是一个方法拦截器,父级接口是我们最熟悉的org.aopalliance.intercept.MethodInterceptor。这个拦截器有个优秀的功能,可以根据不同的方法选择不同的taskexecutor来异步执行,即Async#value()方法的值。

  1. public Object invoke(final MethodInvocation invocation) throws Throwable {
  2. Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
  3. Method specificMethod = ClassUtils.getMostSpecificMethod(invocation.getMethod(), targetClass);
  4. final Method userDeclaredMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
  5. AsyncTaskExecutor executor = determineAsyncExecutor(userDeclaredMethod);
  6. if (executor == null) {
  7. throw new IllegalStateException(
  8. "No executor specified and no default executor set on AsyncExecutionInterceptor either");
  9. }
  10. Callable<Object> task = () -> {
  11. try {
  12. Object result = invocation.proceed();
  13. if (result instanceof Future) {
  14. return ((Future<?>) result).get();
  15. }
  16. }
  17. catch (ExecutionException ex) {
  18. handleError(ex.getCause(), userDeclaredMethod, invocation.getArguments());
  19. }
  20. catch (Throwable ex) {
  21. handleError(ex, userDeclaredMethod, invocation.getArguments());
  22. }
  23. return null;
  24. };
  25. return doSubmit(task, executor, invocation.getMethod().getReturnType());
  26. }

  拦截器的invoke方法看一下瞬间豁然开朗,寻找方法对应的桥接方法、选择一个合适的异步执行的executor、创建Callback实例(异常的处理)、提交异步调用任务到executor中。

  创建pointcut

  1. public interface Pointcut {
  2. /**
  3. * Return the ClassFilter for this pointcut.
  4. * @return the ClassFilter (never {@code null})
  5. */
  6. ClassFilter getClassFilter();
  7. /**
  8. * Return the MethodMatcher for this pointcut.
  9. * @return the MethodMatcher (never {@code null})
  10. */
  11. MethodMatcher getMethodMatcher();
  12. /**
  13. * Canonical Pointcut instance that always matches.
  14. */
  15. Pointcut TRUE = TruePointcut.INSTANCE;
  16. }
  17. public interface Pointcut {
  18. /**
  19. * Return the ClassFilter for this pointcut.
  20. * @return the ClassFilter (never {@code null})
  21. */
  22. ClassFilter getClassFilter();
  23. /**
  24. * Return the MethodMatcher for this pointcut.
  25. * @return the MethodMatcher (never {@code null})
  26. */
  27. MethodMatcher getMethodMatcher();
  28. /**
  29. * Canonical Pointcut instance that always matches.
  30. */
  31. Pointcut TRUE = TruePointcut.INSTANCE;
  32. }

  一个切点主要包含两个对象ClassFilter(class过滤器)、MethodMatcher(方法匹配器)。AnnotationMatchingPointcut主要匹配注有@Async或者指定类型注解的class或者方法。

  继续回到AsyncAnnotationBeanPostProcessor这个后置处理器,父类AbstractBeanFactoryAwareAdvisingPostProcessor是和AbstractAutoProxyCreator(Spring Aop中最常见的创建Aop Proxy的BPP)同一级别的,主要是曝光代理对象的class、强制设置target-class mode。

  1. @Override
  2. protected ProxyFactory prepareProxyFactory(Object bean, String beanName) {
  3. if (this.beanFactory != null) {
  4. AutoProxyUtils.exposeTargetClass(this.beanFactory, beanName, bean.getClass());
  5. }
  6. ProxyFactory proxyFactory = super.prepareProxyFactory(bean, beanName);
  7. if (!proxyFactory.isProxyTargetClass() && this.beanFactory != null &&
  8. AutoProxyUtils.shouldProxyTargetClass(this.beanFactory, beanName)) {
  9. proxyFactory.setProxyTargetClass(true);
  10. }
  11. return proxyFactory;
  12. }

  如何判断bean是否需要创建proxy呢?

  1. @Override
  2. protected boolean isEligible(Object bean, String beanName) {
  3. return (!AutoProxyUtils.isOriginalInstance(beanName, bean.getClass()) &&
  4. super.isEligible(bean, beanName));
  5. }
  1. AbstractAdvisingBeanPostProcessor.java
  2. protected boolean isEligible(Class<?> targetClass) {
  3. Boolean eligible = this.eligibleBeans.get(targetClass);
  4. if (eligible != null) {
  5. return eligible;
  6. }
  7. if (this.advisor == null) {
  8. return false;
  9. }
  10. eligible = AopUtils.canApply(this.advisor, targetClass);
  11. this.eligibleBeans.put(targetClass, eligible);
  12. return eligible;
  13. }
  1. AopUtils.java
  2. public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
  3. if (advisor instanceof IntroductionAdvisor) {
  4. return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
  5. }
  6. else if (advisor instanceof PointcutAdvisor) {
  7. PointcutAdvisor pca = (PointcutAdvisor) advisor;
  8. return canApply(pca.getPointcut(), targetClass, hasIntroductions);
  9. }
  10. else {
  11. // It doesn't have a pointcut so we assume it applies.
  12. return true;
  13. }
  14. }

  首先当前处理的bean是最原始的实例,然后通过advisor的pointcut去判断。

  继续追踪父级AbstractAdvisingBeanPostProcessor。

  1. public Object postProcessAfterInitialization(Object bean, String beanName) {
  2. if (this.advisor == null || bean instanceof AopInfrastructureBean) {
  3. // Ignore AOP infrastructure such as scoped proxies.
  4. return bean;
  5. }
  6. if (bean instanceof Advised) {
  7. Advised advised = (Advised) bean;
  8. if (!advised.isFrozen() && isEligible(AopUtils.getTargetClass(bean))) {
  9. // Add our local Advisor to the existing proxy's Advisor chain...
  10. if (this.beforeExistingAdvisors) {
  11. advised.addAdvisor(0, this.advisor);
  12. }
  13. else {
  14. advised.addAdvisor(this.advisor);
  15. }
  16. return bean;
  17. }
  18. }
  19. if (isEligible(bean, beanName)) {
  20. ProxyFactory proxyFactory = prepareProxyFactory(bean, beanName);
  21. if (!proxyFactory.isProxyTargetClass()) {
  22. evaluateProxyInterfaces(bean.getClass(), proxyFactory);
  23. }
  24. proxyFactory.addAdvisor(this.advisor);
  25. customizeProxyFactory(proxyFactory);
  26. return proxyFactory.getProxy(getProxyClassLoader());
  27. }
  28. // No proxy needed.
  29. return bean;
  30. }

  这个抽象类中实现了BPP的postProcessAfterInitialization方法。如果bean是Advised,则将AsyncAnnotationAdvisor添加到Advised实例中去;如果是一个可以创建异步调用代理的bean,通过ProxyFactory创建代理对象。

  1. @Configuration
  2. public class MyAsyncConfigurer extends AsyncConfigurerSupport {
  3. private static Logger LOGGER = LoggerFactory.getLogger(MyAsyncConfigurer.class);
  4. @Override
  5. public Executor getAsyncExecutor() {
  6. ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
  7. taskExecutor.setCorePoolSize(2);
  8. taskExecutor.setMaxPoolSize(4);
  9. taskExecutor.setQueueCapacity(10);
  10. taskExecutor.setRejectedExecutionHandler((runnable, executor) -> LOGGER.error("异步线程池拒绝任务..." + runnable));
  11. taskExecutor.setThreadFactory(new MyAsyncThreadFactory());
  12. taskExecutor.initialize();
  13. return taskExecutor;
  14. }
  15. static class MyAsyncThreadFactory implements ThreadFactory {
  16. private static final AtomicInteger poolNumber = new AtomicInteger(1);
  17. private final ThreadGroup group;
  18. private final AtomicInteger threadNumber = new AtomicInteger(1);
  19. private final String namePrefix;
  20. MyAsyncThreadFactory() {
  21. SecurityManager s = System.getSecurityManager();
  22. group = (s != null) ? s.getThreadGroup() :
  23. Thread.currentThread().getThreadGroup();
  24. namePrefix = "myasync-pool-" +
  25. poolNumber.getAndIncrement() +
  26. "-thread-";
  27. }
  28. @Override
  29. public Thread newThread(Runnable r) {
  30. Thread t = new Thread(group, r,
  31. namePrefix + threadNumber.getAndIncrement(),
  32. 0);
  33. if (t.isDaemon())
  34. t.setDaemon(false);
  35. if (t.getPriority() != Thread.NORM_PRIORITY)
  36. t.setPriority(Thread.NORM_PRIORITY);
  37. return t;
  38. }
  39. }
  40. }
  1. @Component
  2. public class MyAsyncTask {
  3. private static Logger LOGGER = LoggerFactory.getLogger(MyAsyncConfigurer.class);
  4. /**
  5. * Lazy 功能
  6. *
  7. * @see DefaultListableBeanFactory#resolveDependency(DependencyDescriptor, String, Set, TypeConverter)
  8. * <p>
  9. * Spring Bean创建-解决依赖 参考链接:https://blog.csdn.net/finalcola/article/details/81537380
  10. */
  11. @Lazy
  12. @Autowired
  13. private MyInnerAsyncTask myInnerAsyncTask;
  14. @Autowired
  15. private AsyncWrapped asyncWrapped;
  16. @Async
  17. public void async() {
  18. LOGGER.error("async");
  19. }
  20. public void asyncInner() {
  21. myInnerAsyncTask.async();
  22. }
  23. public void asyncWrapped() {
  24. asyncWrapped.asyncProcess(() -> LOGGER.error("async wrapped"), null, null);
  25. }
  26. public void asyncWrappedWithRetry() {
  27. Retry retry = new Retry(2, 1000);
  28. asyncWrapped.asyncProcess(() -> {
  29. throw new RuntimeException("async wrapped with retry");
  30. }, null, retry);
  31. }
  32. public void asyncWrappedWithRetry2() {
  33. try {
  34. asyncWrapped.asyncProcess(() -> {
  35. throw new RuntimeException("async wrapped with retry2");
  36. });
  37. } catch (Exception e) {
  38. LOGGER.error("异步调用异常...", e);
  39. }
  40. }
  41. private class MyInnerAsyncTask {
  42. @Async
  43. public void async() {
  44. LOGGER.error("async inner");
  45. }
  46. }
  47. @Configuration
  48. public static class MyAsyncTaskConfiguration {
  49. @Bean
  50. public MyInnerAsyncTask myInnerAsyncTask(MyAsyncTask myAsyncTask) {
  51. return myAsyncTask.new MyInnerAsyncTask();
  52. }
  53. }
  54. }
  1. @Component
  2. public class AsyncWrapped {
  3. protected static Logger LOGGER = LoggerFactory.getLogger(AsyncWrapped.class);
  4. @Async
  5. public void asyncProcess(Runnable runnable, Callback callback, Retry retry) {
  6. try {
  7. if (retry == null) {
  8. retry = new Retry(1);
  9. }
  10. retry.execute(ctx -> {
  11. runnable.run();
  12. return null;
  13. }, ctx -> {
  14. if (callback != null) {
  15. callback.call();
  16. }
  17. return null;
  18. });
  19. } catch (Exception e) {
  20. LOGGER.error("异步调用异常...", e);
  21. }
  22. }
  23. @Async
  24. @Retryable(value = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 2000, multiplier = 1.5))
  25. public void asyncProcess(Runnable runnable) throws Exception {
  26. System.out.println("重试中...");
  27. runnable.run();
  28. }
  29. @FunctionalInterface
  30. public interface Runnable {
  31. void run() throws Exception;
  32. }
  33. @FunctionalInterface
  34. public interface Callback {
  35. void call();
  36. }
  37. }

  本来没有写这块的东西,Spring异步调用整合了Spring Retry功能之后,就像看一下二者是如何协调工作的。

  开启异步和重试功能,仅需要加上这两个注解@EnableAsync、@EnableRetry。

  大家可以看一下RetryConfiguration这个类,直接告诉大家了,它是一个advisor,直接注册到spring容器当中的。AbstractAutoProxyCreator会拿到这个advisor,对具有@Retryable注解的bean创建代理类。分析流程和AsyncAnnotationAdvisor一致,大家可以按照上面讲过的流程分析一下Spring Retry的底层实现原理,这里就不详细说明了。

  如下是AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization()方法。

  1. @Override
  2. public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
  3. throws BeansException {
  4. Object result = existingBean;
  5. for (BeanPostProcessor processor : getBeanPostProcessors()) {
  6. Object current = processor.postProcessAfterInitialization(result, beanName);
  7. if (current == null) {
  8. return result;
  9. }
  10. result = current;
  11. }
  12. return result;
  13. }

  

  上图中AnnotationAwareAspectJAutoProxyCreator是AbstractAdvisorAutoProxyCreator的实例。也就是说AbstractAdvisorAutoProxyCreator类型的后置处理器优先于AsyncAnnotationBeanPostProcessor类型的后置处理器执行。AbstractAdvisorAutoProxyCreator BPP通过BeanFactoryAdvisorRetrievalHelper从当前的BeanFactory中拿到所有的advisor。

  

  然后针对当前的bean(beanName = asyncWrapped )筛选出合适的advisor集合(包含RetryConfiguration实例)。最后是通过ProxyFactory创建的代理类,具体如下。

  

  ProxyFactory通过默认AopProxyFactory即DefaultAopProxyFactory来创建Aop Proxy。

  

  到这里,beanName = asyncWrapped 关于Retryable的代理对象已经创建完毕,并返回代理对象替代当前的bean。然后继续到AsyncAnnotationBeanPostProcessor#postProcessAfterInitialization()方法,处理关于带有@Async注解的bean。

  1. //如果是advised
    if
    (bean instanceof Advised) {
  2. Advised advised = (Advised) bean;
  3. if (!advised.isFrozen() && isEligible(AopUtils.getTargetClass(bean))) {
  4. // Add our local Advisor to the existing proxy's Advisor chain...
  5. if (this.beforeExistingAdvisors) {
  6. advised.addAdvisor(0, this.advisor);
  7. }
  8. else {
  9. advised.addAdvisor(this.advisor);
  10. }
  11. return bean;
  12. }
  13. }
  14. //这里的逻辑不会执行了
  15. if (isEligible(bean, beanName)) {
  16. ProxyFactory proxyFactory = prepareProxyFactory(bean, beanName);
  17. if (!proxyFactory.isProxyTargetClass()) {
  18. evaluateProxyInterfaces(bean.getClass(), proxyFactory);
  19. }
  20. proxyFactory.addAdvisor(this.advisor);
  21. customizeProxyFactory(proxyFactory);
  22. return proxyFactory.getProxy(getProxyClassLoader());
  23. }

  以前总以为多个注解,就会多次创建代理,一层一层嵌套。现在明白了,是通过拦截器链来完成的。此时beanName = asyncWrapped对应的bean已经是Advised类型的实例了,然后将AsyncAnnotationAdvisor实例添加到Advised实例的advisors集合中。

  为啥beanName = asyncWrapped对应的bean是Advised类型的实例?那还要从对beanName = asyncWrapped的bean创建代理类说起。那么接着回到通过DefaultAopProxyFactory来创建Aop Proxy。这里看一下CglibAopProxy,JdkDynamicAopProxy请自行查看。以下代码来自CglibAopProxy#getProxy()方法。

  1. ......
    //设置需要代理的接口
  2. enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
  3. ......
    //获取callbacks
  4. Callback[] callbacks = getCallbacks(rootClass);
    ......
    //设置callback filter
    enhancer.setCallbackFilter(new ProxyCallbackFilter(
  5. this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
  6. .....

  设置需要代理的接口,除了目标类包含的接口,还需要添加一些额外的接口。如下是AopProxyUtils#completeProxiedInterfaces()方法中的内容。

  1. ......
  2. if (addSpringProxy) {
  3. proxiedInterfaces[index] = SpringProxy.class;
  4. index++;
  5. }
  6. if (addAdvised) {
  7. proxiedInterfaces[index] = Advised.class;
  8. index++;
  9. }
  10. if (addDecoratingProxy) {
  11. proxiedInterfaces[index] = DecoratingProxy.class;
  12. }
  13. ......

  看到了Advised.class哈,这就是为啥最终的代理对象是Advised类型的实例了。

  获取callbacks集合注意this.advisedDispatcher在数组中的索引是4,下面会用到。

  1. Callback[] mainCallbacks = new Callback[] {
  2. aopInterceptor, // for normal advice
  3. targetInterceptor, // invoke target without considering advice, if optimized
  4. new SerializableNoOp(), // no override for methods mapped to this
  5. targetDispatcher, this.advisedDispatcher,
  6. new EqualsInterceptor(this.advised),
  7. new HashCodeInterceptor(this.advised)
  8. };

  设置callback filters,如下是ProxyCallbackFilter#accept(Method method)部分源码。

  1. ......
  2. if (!this.advised.isOpaque() && method.getDeclaringClass().isInterface() &&
  3. method.getDeclaringClass().isAssignableFrom(Advised.class)) {
  4. if (logger.isTraceEnabled()) {
  5. logger.trace("Method is declared on Advised interface: " + method);
  6. }
  7. return DISPATCH_ADVISED;
  8. }
  9. ......

  ProxyCallbackFilter的作用主要是根据不同类型的method,返回callbacks数组的索引。上面的DISPATCH_ADVISED变量的值是4

  这个AdvisedDispatcher是干什么的呢?

  1. //Dispatcher for any methods declared on the Advised class.
    private static class AdvisedDispatcher implements Dispatcher, Serializable {
  2. private final AdvisedSupport advised;
  3. public AdvisedDispatcher(AdvisedSupport advised) {
  4. this.advised = advised;
  5. }
  6. @Override
  7. public Object loadObject() throws Exception {
  8. return this.advised;
  9. }
  10. }

  也就是如果method是Advised.class声明的,则使用AdvisedDispatcher进行分发。

  1. AsyncAnnotationBeanPostProcessor#postProcessAfterInitialization()
  2. //如果是advised
  3. if (bean instanceof Advised) {
  4. Advised advised = (Advised) bean;
  5. if (!advised.isFrozen() && isEligible(AopUtils.getTargetClass(bean))) {
  6. // Add our local Advisor to the existing proxy's Advisor chain...
  7. if (this.beforeExistingAdvisors) {
  8. advised.addAdvisor(0, this.advisor);
  9. }
  10. else {
  11. advised.addAdvisor(this.advisor);
  12. }
  13. return bean;
  14. }
  15. }

  上面的advised.addAdvisor(0, this.advisor); 相当于如下代码。

  1. //spring aop cglib代理对象
    public
    class XXXX$$EnhancerBySpringCGLIB$$8f47b115 implements Advised {
  2. private org.springframework.cglib.proxy.Dispatcher advisedDispatcher;//AdvisedDispatcher实例
  3. ......
  4. @Override
  5. public void addAdvisor(int pos, Advisor advisor) throws AopConfigException() {
  6. advisedDispatcher.loadObject().addAdvisor(pos, advisor);
  7. }
  8. ......
  9. }

   还需要补充的一个地方就是callbacks数组中有个aopInterceptor,对应的类型是DynamicAdvisedInterceptor(General purpose AOP callback. Used when the target is dynamic or when the proxy is not frozen.)。

    

  如上图所示,intercept方法中会通过advised(AdvisedSupport type, The configuration used to configure this proxy.)实例获取一个拦截器链,如果不为空,则返回一个CglibMethodInvocation实例。

  至此,Spring异步调用原理及SpringAop拦截器链都已经分析完毕,希望对大家使用spring异步调用有所帮助。另外我自己也重新温习了spring aop相关的知识,也希望大家对spring aop有一个新的认识。如果有需要源码的同学,请f访问我的github。Spring异步调用原理及实现方案demo

版权声明:本文为hujunzheng原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/hujunzheng/p/10549849.html