Spring读源码系列之AOP--08--aop执行完整源码流程之自动代理创建器导入的两种方式
Posted 大忽悠爱忽悠
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring读源码系列之AOP--08--aop执行完整源码流程之自动代理创建器导入的两种方式相关的知识,希望对你有一定的参考价值。
Spring读源码系列之AOP--08--aop执行完整源码流程之自动代理创建器导入的两种方式
- 环境搭建
- Spring启用注解式aop的两种方式
- xml方式--< aop:aspectj-autoproxy/ >
- 注解方式-@EnableAspectJAutoProxy
- AspectJAutoProxyRegistrar---为容器注册 自动代理创建器
- AspectJAutoProxyRegistrar的registerBeanDefinitions方法何时被调用---可以一览配置类的解析大致流程
- refresh--> invokeBeanFactoryPostProcessors
- PostProcessorRegistrationDelegate的invokeBeanFactoryPostProcessors方法
- PostProcessorRegistrationDelegate的invokeBeanDefinitionRegistryPostProcessors方法
- ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法
- ConfigurationClassPostProcessor的processConfigBeanDefinitions方法
- ConfigurationClassParser的parse方法
- ConfigurationClassParser的processConfigurationClass方法
- ConfigurationClassParser的doProcessConfigurationClass方法
- ConfigurationClassParser的processImports方法---处理@Import注解的方法
- ConfigurationClassBeanDefinitionReader的loadBeanDefinitions方法
- ConfigurationClassBeanDefinitionReader的loadBeanDefinitionsForConfigurationClass方法
- ConfigurationClassBeanDefinitionReader的loadBeanDefinitionsFromRegistrars方法
- AspectJAutoProxyRegistrar的loadBeanDefinitionsFromRegistrars方法---圆回来了
环境搭建
@Slf4j
@Component
public class Bean
public String say()
log.info("bean's say method is invoke");
return "say";
public String eat()
log.info("bean's eat method is invoke");
return "eat";
@Aspect
@Slf4j
public class LogAspect
@Pointcut("execution(* org.aop.MyBean.*(..))")
public void point()
@Before("point()")
public void beforeLog()
log.info("方法执行,当前时间: "+System.currentTimeMillis());
@AfterReturning("point()")
public void afterReturning()
log.info("获取方法返回结果后,当前时间: "+System.currentTimeMillis());
@After("point()")
public void after()
log.info("方法执行完毕后,当前时间: "+System.currentTimeMillis());
@Around("point()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable
long start = System.currentTimeMillis();
Object proceed = joinPoint.proceed();
long end = System.currentTimeMillis();
log.info("方法执行时间为 ms",end-start);
log.info("-------------------------------------");
return proceed;
@EnableAspectJAutoProxy
@Configuration
public class MyConfiguration
@Bean(name = "bean")
public MyBean bean()
return new MyBean();
@Bean
public LogAspect logAspect()
return new LogAspect();
public class AopMain
public static void main(String[] args)
//AnnotationConfigApplicationContext会自动向容器中注册三个常用后置处理器
//ConfigurationAnnotationProcessor
//AutowiredAnnotationProcessor
//CommonAnnotationProcessor
AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext(MyConfiguration.class);
MyBean bean = (MyBean)applicationContext.getBean("bean");
bean.say();
bean.eat();
Spring启用注解式aop的两种方式
Spring启用注解式aop支持有两种方式:
- XML方式
<aop:aspectj-autoproxy/>
- 注解方式
@EnableAspectJAutoProxy
我们下面先依次分析一下,这两种方式是如何通过不同的方式,来启用的注解式aop功能
xml方式–< aop:aspectj-autoproxy/ >
下面这篇文章讲过spring的标签解析过程,aop:aspectj-autoproxy严格来说属于自定义标签,
spring默认和自定义标签的解析过程
< aop:aspectj-autoproxy/ >
不属于spring的默认标签,也算自定义标签的行列,因此我们来回顾一下自定义标签的解析过程是什么样子的:
既然是自定义标签,那么对应就需要有一个自定义命名空间的解析器—即NameSpaceHandler,而spring-aop给aop的自定义命名空间,提供一个AopNameSpaceHandler,负责解析aop:开头的命名空间。
public class AopNamespaceHandler extends NamespaceHandlerSupport
@Override
public void init()
// In 2.0 XSD as well as in 2.5+ XSDs
registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
// Only in 2.0 XSD: moved to context namespace in 2.5+
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
可以看到这里是注册了一些解析器来解析aop标签的,这里我们最关心的是下面这行代码:
registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
显然AspectJAutoProxyBeanDefinitionParser是用来解析aop:aspectj-autoproxy这个标签的,下面看一下他的parse方法做了什么事情
,因为当spring解析到这个标签的时候,会定位到AspectJAutoProxyBeanDefinitionParser,然后调用其parse方法进行解析
AspectJAutoProxyBeanDefinitionParser —专门解析aop:aspectj-autoproxy标签
class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext)
//注册AspectJAnnotationAutoProxyCreator
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
//对于注解中子类的处理
extendBeanDefinition(element, parserContext);
return null;
...
AopNamespaceUtils—处理xml形式的aop命名空间工具类
下面来看一下AopNamespaceUtils的registerAspectJAnnotationAutoProxyCreatorIfNecessary方法:
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement)
//AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary是重点
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
//检查标签上的proxy-target-class属性是否为true,如果为true的话会强制使用cglib完成代理
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
//注册组件并通知监听器
registerComponentIfNecessary(beanDefinition, parserContext);
AopNamespaceUtils的useClassProxyingIfNecessary
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, @Nullable Element sourceElement)
if (sourceElement != null)
//拿到标签上的proxy-target-class属性
boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
if (proxyTargetClass)
//强制使用cglib代理
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
//拿到exposeProxy属性
boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
if (exposeProxy)
//强制将代理bean暴露到aopcontext中去
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary–注册自动代理创建器
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");
//一般如果不是需要替换自动代理创建器,那么第一次进入该方法时,容器中都是没有这个bean的
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;
//构造一个自动dialing创建器,放入容器中去,自动代理创建器是一个后置处理器,他的优先级被设置为最高
//beanName被设置为了AUTO_PROXY_CREATOR_BEAN_NAME
//角色是ROLE_INFRASTRUCTURE
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.forceAutoProxyCreatorToUseClassProxying—强制使用cglib完成代理
public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry)
//AUTO_PROXY_CREATOR_BEAN_NAME是自动代理创建器再容器中的专属名称--上面已经默认注册过了,因此这里可以直接拿出来
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME))
BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
//设置其proxyTargetClass属性为true,强制该自动代理创建器,创建出来的代理对象都是通过cglib完成的代理
definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
AopConfigUtils.forceAutoProxyCreatorToExposeProxy—将目标对象暴露到aopcontext中
public static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry)
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME))
//拿出容器中已经注册好的自动代理创建器,设置其exposeProxy属性为true,表示该代理创建器创建的所有bean都需要暴露到aopcontext中
BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
注解方式-@EnableAspectJAutoProxy
//Enables support for handling components marked with AspectJ's @code @Aspect annotation,
//similar to functionality found in Spring's @code <aop:aspectj-autoproxy> XML element.
//Note: @code @EnableAspectJAutoProxy applies to its local application context only,(说明此注解只会作用于本容器,对子、父容器是无效得)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy
// 决定该类采用CGLIB代理还是使用JDK的动态代理(需要实现接口),默认为false,表示使用的是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;
当然,最重点的,还是这一句@Import(AspectJAutoProxyRegistrar.class),下面看看它
AspectJAutoProxyRegistrar—为容器注册 自动代理创建器
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)
// 若为true,表示强制指定了要使用CGLIB,那就强制告知到时候使用CGLIB的动态代理方式
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass"))
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
// 告知,强制暴露Bean的代理对象到AopContext
if (enableAspectJAutoProxy.getBoolean("exposeProxy"))
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
和xml的思想一样
AspectJAutoProxyRegistrar的registerBeanDefinitions方法何时被调用—可以一览配置类的解析大致流程
首先明确一点ConfigurationClassPostProcessor负责解析import,configuation注解和处理ImportBeanDefinitionRegistrar 相关回调接口
refresh–> invokeBeanFactoryPostProcessors
ConfigurationClassPostProcessor是一个工厂Bean后置处理器,在refresh方法的invokeBeanFactoryPostProcessors中会去调用所有注册上来的工厂bean后置处理器。
public void refresh() throws BeansException, IllegalStateException
prepareRefresh();
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
prepareBeanFactory(beanFactory);
postProcessBeanFactory(beanFactory);
//触发调用工厂bean的后置处理器
invokeBeanFactoryPostProcessors(beanFactory);
...
invokeBeanFactoryPostProcessors方法
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory)
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
...
PostProcessorRegistrationDelegate的invokeBeanFactoryPostProcessors方法
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors)
Set<String> processedBeans = new HashSet<>();
//处理的是编码设置的工厂bean后置处理器,这里不管
if (beanFactory instanceof BeanDefinitionRegistry)
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors)
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor)
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
//这里会调用 ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
else
regularPostProcessors.add(postProcessor);
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
//获取到容器中所有类型为BeanDefinitionRegistryPostProcessor工厂bean后置处理器
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
...排序啥的,处理一通
//调用后置处理器的invokeBeanDefinitionRegistryPostProcessors方法---我们就重点分析这里,剩余的就先不管了
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
....
PostProcessorRegistrationDelegate的invokeBeanDefinitionRegistryPostProcessors方法
private static void invokeBeanDefinitionRegistryPostProcessors(
Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry, ApplicationStartup applicationStartup)
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) Spring读源码系列之AOP--04---proxyFactory创建代理对象
Spring读源码系列之AOP--02---aop基本概念扫盲---下
Spring读源码系列之AOP--03---aop底层基础类学习
Spring读源码系列之AOP--05---aop常用工具类学习
Spring读源码系列之AOP--07---aop自动代理创建器(拿下AOP的最后一击)
Spring读源码系列之AOP--06---AopProxy===>spring使用jdk和cglib生成代理对象的终极奥义