美文网首页
Spring5AOP——@EnableAspectJAutoPr

Spring5AOP——@EnableAspectJAutoPr

作者: 小波同学 | 来源:发表于2020-07-04 15:54 被阅读0次

前言

在这个注解比较流行的年代里,当我们想要使用spring 的某些功能时只需要加上一行代码就可以了,比如:

  • @EnableAspectJAutoProxy开启AOP,

  • @EnableTransactionManagement开启spring事务管理,

  • @EnableCaching开启spring缓存

  • @EnableWebMvc 开启webMvc

对于我们使用者而言十分简单便利,然而其背后所做的事,却远远比一个注解复杂的多了,本篇只是简略的介绍一下@EnableAspectJAutoProxy背后所发生的那些事,了解其工作原理,才能更好的运用,并从中领略大师的智慧。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
//引入AspectJAutoProxyRegistrar
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {

    /**
     * 表明该类采用CGLIB代理还是使用JDK的动态代理
     */
    boolean proxyTargetClass() default false;

    /**
     * 解决内部调用不能使用代理的场景  默认为false表示不处理
     * true则表示这个代理对象的副本就可以通过AopContext.currentProxy()获得(ThreadLocal里面),
     * 从而我们可以很方便得在Spring框架上下文中拿到当前代理对象(处理事务时很方便)
     */
    boolean exposeProxy() default false;

}

这里核心是@Import(AspectJAutoProxyRegistrar.class);在AspectJAutoProxyRegistrar里。

通过注解将类当做Bean管理起来的方式
  • 1、@Controller、@Service、@Repository、@Component等注解标记的类
  • 2、@Bean标记的方法
  • 3、@Import注解

AspectJAutoProxyRegistrar 是一个ImportBeanDefinitionRegistrar。

ImportBeanDefinitionRegistrar 是@Import 导入组件的一种方式

@Import导入bean的三种方式:
  • 1、普通bean
  • 2、ImportSelector
  • 3、ImportBeanDefinitionRegistrar

注册了AnnotationAwareAspectJAutoProxyCreator类的定义信息(bean definition)。

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {


    @Override
    public void registerBeanDefinitions(
            AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        //向容器注册了一个基于注解的自动代理创建器
        AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

        AnnotationAttributes enableAspectJAutoProxy =
                AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
        if (enableAspectJAutoProxy != null) {
            //表示强制指定了要使用CGLIB
            if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
                AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
            }
            //表示强制暴露Bean的代理对象到AopContext
            if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
                AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
            }
        }
    }

}

AspectJAutoProxyRegistrar 核心的地方是

AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
public abstract class AopConfigUtils {

    @Nullable
    public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
        return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
    }

    @Nullable
    public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
            BeanDefinitionRegistry registry, @Nullable Object source) {

        return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
    }

    @Nullable
    private static BeanDefinition registerOrEscalateApcAsRequired(
            Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {

        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        //如果已经存在了自动代理创建器且存在的自动代理创建器与现在要注册的不一致(一般除非用户自定义,基本上不会有)
        // 那么需要根据优先级来判断到底需要使用哪个
        if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
            BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
            if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
                int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
                int requiredPriority = findPriorityForClass(cls);
                if (currentPriority < requiredPriority) {
                    apcDefinition.setBeanClassName(cls.getName());
                }
            }
            return null;
        }
        //若用户自己没有定义,那就用默认的AnnotationAwareAspectJAutoProxyCreator
        RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
        beanDefinition.setSource(source);
        beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
        beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
        registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
        return beanDefinition;
    }
}

AopConfigUtils一个AOP的工具类,这个工具类的主要作用是把AnnotationAwareAspectJAutoProxyCreator这个类定义为BeanDefinition放到spring容器中,这是通过实现ImportBeanDefinitionRegistrar接口来装载的,具体装载过程不是本篇的重点,这里就不赘述,我们重点看AnnotationAwareAspectJAutoProxyCreator这个类。

Spring AOP的总体流程

  • 1、注册解析AOP的服务
  • 2、解析和加载横切逻辑
  • 3、将横切逻辑织入目标Bean中

参考:
https://segmentfault.com/a/1190000015830477

https://www.cnblogs.com/foreveravalon/p/8653832.html

相关文章

网友评论

      本文标题:Spring5AOP——@EnableAspectJAutoPr

      本文链接:https://www.haomeiwen.com/subject/gcuuqktx.html