千家信息网

Springboot中EnableAspectJAutoProxy的作用是什么

发表于:2025-02-03 作者:千家信息网编辑
千家信息网最后更新 2025年02月03日,本篇文章给大家分享的是有关Springboot中EnableAspectJAutoProxy的作用是什么,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编
千家信息网最后更新 2025年02月03日Springboot中EnableAspectJAutoProxy的作用是什么

本篇文章给大家分享的是有关Springboot中EnableAspectJAutoProxy的作用是什么,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。

摘要:

Spring Framwork的两大核心技术就是IOCAOPAOPSpring的产品线中有着大量的应用。如果说反射是你通向高级的基础,那么代理就是你站稳高级的底气。AOP的本质也就是大家所熟悉的CGLIB动态代理技术,在日常工作中想必或多或少都用过但是它背后的秘密值得我们去深思。本文主要从Spring AOP运行过程上,结合一定的源码整体上介绍Spring AOP的一个运行过程。知其然,知其所以然,才能更好的驾驭这门核心技术。

    @Target({ElementType.TYPE})    @Retention(RetentionPolicy.RUNTIME)    @Documented    @Import({AspectJAutoProxyRegistrar.class})    public @interface EnableAspectJAutoProxy {        //表明该类采用CGLIB代理还是使用JDK的动态代理        boolean proxyTargetClass() default false;             /**         * @since 4.3.1 代理的暴露方式:解决内部调用不能使用代理的场景  默认为false表示不处理         * true:这个代理就可以通过AopContext.currentProxy()获得这个代理对象的一个副本(ThreadLocal里面),从而我们可以很方便得在Spring框架上下文中拿到当前代理对象(处理事务时很方便)         * 必须为true才能调用AopContext得方法,否则报错:Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available.         */        boolean exposeProxy() default false;    }

所有的EnableXXX驱动技术都得看他的@Import,所以上面最重要的是这一句@Import(AspectJAutoProxyRegistrar.class),下面看看它

    class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {        AspectJAutoProxyRegistrar() {        }        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是一个项容器注册自动代理创建器

    @Nullable            public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(                            BeanDefinitionRegistry registry, @Nullable Object source) {                    return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);            }

说明spring容器的注解代理创建器就是AnnotationAwareAspectJAutoProxyCreator

    @Nullable        private static BeanDefinition registerOrEscalateApcAsRequired(Class cls, BeanDefinitionRegistry registry, @Nullable Object source) {            Assert.notNull(registry, "BeanDefinitionRegistry must not be null");          //这里如果我们自己定义了这样一个自动代理创建器就是用我们自定义的            if (registry.containsBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator")) {                BeanDefinition apcDefinition = registry.getBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator");                if (!cls.getName().equals(apcDefinition.getBeanClassName())) {                    int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());                  /**                    *用户注册的创建器,必须是InfrastructureAdvisorAutoProxyCreator                   *AspectJAwareAdvisorAutoProxyCreator,AnnotationAwareAspectJAutoProxyCreator之一                  */                    int requiredPriority = findPriorityForClass(cls);                    if (currentPriority < requiredPriority) {                        apcDefinition.setBeanClassName(cls.getName());                    }                }                return null;            }           //若用户自己没有定义,那就用默认的AnnotationAwareAspectJAutoProxyCreator          RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);                      beanDefinition.setSource(source);          //此处注意,增加了一个属性:最高优先级执行,后面会和@Async注解一起使用的时候起关键作用                    beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);                    beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);                    registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);                    return beanDefinition;        }

我们就成功的注入了一个BeanAnnotationAwareAspectJAutoProxyCreator 基于注解的自动代理创建器

Spring中自动创建代理器

由此可见,Spring使用BeanPostProcessor让自动生成代理。基于BeanPostProcessor的自动代理创建器的实现类,将根据一些规则在容器实例化Bean时为匹配的Bean生成代理实例。

AbstractAutoProxyCreator是对自动代理创建器的一个抽象实现。最重要的是,它实现了SmartInstantiationAwareBeanPostProcessor接口,因此会介入到Spring IoC容器Bean实例化的过程。

SmartInstantiationAwareBeanPostProcessor继承InstantiationAwareBeanPostProcessor所以它最主要的 职责是在bean的初始化前,先会执行所有的InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation,谁第一个返回了不为nullBean,后面就都不会执行了 。然后会再执行BeanPostProcessor#postProcessAfterInitialization

    protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {                    Object exposedObject = bean;                    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {                            for (BeanPostProcessor bp : getBeanPostProcessors()) {                                    if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {                                            SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;                                            exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);                                    }                            }                    }                    return exposedObject;            }

说明:这个方法是spring的三级缓存中的其中一环,当你调用Object earlySingletonReference = getSingleton(beanName, false);时候就会触发,其实还有一个地方exposedObject = initializeBean(beanName, exposedObject, mbd);也会触发导致返回一个代理对象。

    protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {                    if (System.getSecurityManager() != null) {                            AccessController.doPrivileged((PrivilegedAction) () -> {                                    invokeAwareMethods(beanName, bean);                                    return null;                            }, getAccessControlContext());                    }                    else {                            invokeAwareMethods(beanName, bean);                    }                    Object wrappedBean = bean;                    if (mbd == null || !mbd.isSynthetic()) {                            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);                    }                    try {                            invokeInitMethods(beanName, wrappedBean, mbd);                    }                    catch (Throwable ex) {                            throw new BeanCreationException(                                            (mbd != null ? mbd.getResourceDescription() : null),                                            beanName, "Invocation of init method failed", ex);                    }                    if (mbd == null || !mbd.isSynthetic()) {                            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);                    }                    return wrappedBean;            }

强调: 这2个地方虽然都有后置增强的作用,但是@Async所使用的AsyncAnnotationBeanPostProcessor不是SmartInstantiationAwareBeanPostProcessor的实现类,所以此处会导致@Transactional@Async处理循环依赖时候的不一致性。对于循环依赖后续会有单独章节进行分享。

以上就是Springboot中EnableAspectJAutoProxy的作用是什么,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注行业资讯频道。

0