Springboot源码分析之EnableAspectJAutoProxy
2019-08-22 22:26
1571 查看
摘要:
Spring Framwork的两大核心技术就是
IOC和
AOP,
AOP在
Spring的产品线中有着大量的应用。如果说反射是你通向高级的基础,那么代理就是你站稳高级的底气。
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; }
我们就成功的注入了一个Bean:
AnnotationAwareAspectJAutoProxyCreator基于注解的自动代理创建器
Spring中自动创建代理器
由此可见,
Spring使用
BeanPostProcessor让自动生成代理。基于
BeanPostProcessor的自动代理创建器的实现类,将根据一些规则在容器实例化
Bean时为匹配的
Bean生成代理实例。
AbstractAutoProxyCreator是对自动代理创建器的一个抽象实现。最重要的是,它实现了
SmartInstantiationAwareBeanPostProcessor接口,因此会介入到
Spring IoC容器
Bean实例化的过程。
SmartInstantiationAwareBeanPostProcessor继承
InstantiationAwareBeanPostProcessor所以它最主要的 职责是在
bean的初始化前,先会执行所有的
InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation,谁第一个返回了不为
null的
Bean,后面就都不会执行了 。然后会再执行
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<Object>) () -> { 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处理循环依赖时候的不一致性。对于循环依赖后续会有单独章节进行分享。
AbstractAdvisorAutoProxyCreator
如何创建代理对象后续文章在进行分析。
相关文章推荐
- 从@EnableAspectJAutoProxy分析Spring AOP原理
- 6、AOP-@Aspect、@PointCut、@EnableAspectJAutoProxy、@After
- Spring5.0.4 AOP 使用AspectJ方式自动代理注解(@EnableAspectJAutoProxy)
- SPRING IN ACTION 第4版笔记-第四章ASPECT-ORIENTED SPRING-005-定义切面使用@Aspect、@EnableAspectJAutoProxy、<aop:aspectj-autoproxy>
- The prefix "aop" for element "aop:aspectj-autoproxy" is not bound.
- <aop:aspectj-autoproxy proxy-target-class="false"/>导致出现404状态码
- spring中BeanNameAutoProxyCreator和AnnotationAwareAspectJAutoProxyCreator两种AOP代理方式使用总结
- spring: 使用Aspectj代理EnabelAspectjAutoProxy
- SpringAop源码情操陶冶-AspectJAwareAdvisorAutoProxyCreator
- AnnotationAwareAspectJAutoProxyCreator is only available on Java 1.5 and higher
- spring的启动过程04.2-AnnotationAwareAspectJAutoProxyCreator处理器
- The prefix "aop" for element "aop:aspectj-autoproxy" is not bound.
- <aop:aspectj-autoproxy />作用
- but no declaration can be found for element 'aop:aspectj-autoproxy'.
- but no declaration can be found for element 'aop:aspectj-autoproxy'.
- AnnotationAwareAspectJAutoProxyCreator is only available on Java 1.5 and higher
- Spring配置项之<aop:aspectj-autoproxy />
- <aop:aspectj-autoproxy proxy-target-class="false"/>导致出现404状态码
- spring添加<aop:aspectj-autoproxy>让注解自为类生成代理对象时出错
- The prefix "aop" for element "aop:aspectj-autoproxy" is not bound.