Spring读源码系列之AOP--08--aop执行完整源码流程之自动代理创建器导入的两种方式

Posted 大忽悠爱忽悠

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring读源码系列之AOP--08--aop执行完整源码流程之自动代理创建器导入的两种方式相关的知识,希望对你有一定的参考价值。

Spring读源码系列之AOP--08--aop执行完整源码流程之自动代理创建器导入的两种方式


环境搭建

@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生成代理对象的终极奥义