关于java:一AOP-如何注入SpringBoot中

28次阅读

共计 4786 个字符,预计需要花费 12 分钟才能阅读完成。

次要内容

SpringBoot 如何将 AOP 相干的类注入 BeanFactory 中,如何起作用呢?

梳理概要

  1. AopAutoConfiguration:主动注入 AOP 相干的配置类;AnnotationAwareAspectJAutoProxyCreator;
  2. 在 populateBean 的时候,每个 bean 都会扫描是否有切面,匹配一下;AnnotationAwareAspectJAutoProxyCreator.postProcessAfterInitialization;
  3. 匹配胜利,则会通过 cglib 动静代理生成一个新的代理类;

具体的源码过程

1.1 主动配置类加载 AOP 相干的类;

  1. 加载 AopAutoConfiguration
  2. 在加载 CglibAutoProxyFactory 的时候,外面有注解 @EnableAspectJAutoProxy 的时候有一个 @Import 注解,AspectJAutoProxyRegistrar;这个 Registrar 很重要!!!

    其在 ConfigurationClassPostProcessor 类扫描加载 bean 的时候,解决 loadBeanDefinitionsFromRegistrars 的时候;加载进去;

    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
    .....

    registerAspectJAnnotationAutoProxyCreatorIfNecessary() 的时候,
    把 AnnotationAwareAspectJAutoProxyCreator 封装成 BeanDefinition,对应的 key=internalAutoProxyCreator;

    @Nullable
     public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, @Nullable Object source) {
    // 把 AnnotationAwareAspectJAutoProxyCreator 封装成一个 BeanDefinition;return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
     }

1.2 应用代理类(AnnotationAwareAspectJAutoProxyCreator)


InitializeBean — 初始化 bean 的时候,会对立调用所有的 BeanPostProcessor.postProcessAfterInitialization;其中就会调用到 AnnotationAwareAspectJAutoProxyCreator;进行查看是否有符合要求的切面办法;
调用办法如下:

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    ......

// 重点如下:找到这个 bean 的所有切面办法,而后调用 createProxy 创立代理类;返回即可。// Create proxy if we have advice.
        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;
    }

1.3 找所有的适合的告诉

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 1 找到所有的候选告诉
        List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 2 进行匹配,查看是否适合
        List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
        extendAdvisors(eligibleAdvisors);
        if (!eligibleAdvisors.isEmpty()) {
// 3 这里排序 Advisor?eligibleAdvisors = sortAdvisors(eligibleAdvisors);
        }
        return eligibleAdvisors;
    }

1.3.1 findCandidateAdvisors

    protected List<Advisor> findCandidateAdvisors() {
        // Add all the Spring advisors found according to superclass rules.
// 从所有带 @Advisor 注解的切面类;List<Advisor> advisors = super.findCandidateAdvisors();
        // Build Advisors for all AspectJ aspects in the bean factory.
        if (this.aspectJAdvisorsBuilder != null) {// 开始找 @AspectJ 的注解类;advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
        }
        return advisors;
    }

this.aspectJAdvisorsBuilder.buildAspectJAdvisors()
次要逻辑:

  1. 遍历 BeanDefinitionMap,查看是否有 @AspectJ 注解,
  2. 如果有,则会遍历 method,查看是否是一个告诉,如果是一个告诉,则会封装成一个 InstantiationModelAwarePointcutAdvisorImpl 类;
  3. 而后封装返回;
    在这个办法外面还有一个排序!!在 getAdvisorMethod 中

    private List<Method> getAdvisorMethods(Class<?> aspectClass) {List<Method> methods = new ArrayList<>();
         ReflectionUtils.doWithMethods(aspectClass, methods::add, adviceMethodFilter);
         if (methods.size() > 1) {methods.sort(adviceMethodComparator);
         }
         return methods;
     }
    

依照什么排序呢?

    private static final Comparator<Method> adviceMethodComparator;

    static {
        // Note: although @After is ordered before @AfterReturning and @AfterThrowing,
        // an @After advice method will actually be invoked after @AfterReturning and
        // @AfterThrowing methods due to the fact that AspectJAfterAdvice.invoke(MethodInvocation)
        // invokes proceed() in a `try` block and only invokes the @After advice method
        // in a corresponding `finally` block.
        Comparator<Method> adviceKindComparator = new ConvertingComparator<>(
                new InstanceComparator<>(Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class),
                (Converter<Method, Annotation>) method -> {AspectJAnnotation<?> ann = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
                    return (ann != null ? ann.getAnnotation() : null);
                });
        Comparator<Method> methodNameComparator = new ConvertingComparator<>(Method::getName);
        adviceMethodComparator = adviceKindComparator.thenComparing(methodNameComparator);
    }

咱们发现,他是依照 Around、Before、After、AfterReturning 进行排序,如果有雷同,则依照 methodName 进行排序;

1.3.2 findAdvisorsThatCanApply

查看这个类是否和 PointCut 匹配胜利,匹配胜利,即返回列表;

    protected List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {ProxyCreationContext.setCurrentProxiedBeanName(beanName);
        try {
// 查看这个类是否和 PointCut 匹配胜利,匹配胜利,即 ok;return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
        }
        finally {ProxyCreationContext.setCurrentProxiedBeanName(null);
        }
    }

1.3.3 findAdvisorsThatCanApply

比拟两个类的 order 大小;

1.4 createProxy

这个不在细追,
主题逻辑:

  1. 找到所有的 Advisor
  2. 创立指定的拦截器,比方:dynamicAdvisorInterceptor 退出到 callback 办法中;
  3. Enhancer.create();

总结

  1. 先想好,再去做;
  2. 命名艺术,AutoProxyCreator、AspectJAdvisor、AspectJAdvisorBuilder、XXFactory
  3. 封装成对象,便于当前的扩大

正文完
 0