当前位置 : 主页 > 编程语言 > java >

Spring5 AOP——@EnableAspectJAutoProxy

来源:互联网 收集:自由互联 发布时间:2023-02-04
前言 在这个注解比较流行的年代里,当我们想要使用spring 的某些功能时只需要加上一行代码就可以了,比如: @EnableAspectJAutoProxy开启AOP, @EnableTransactionManagement开启spring事务管理, @EnableCach

前言

在这个注解比较流行的年代里,当我们想要使用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

上一篇:Spring5 AOP——TargetSource
下一篇:没有了
网友评论