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

2022-05-10 16:43:59 浏览数 (1)

  • 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方法---圆回来了

环境搭建

代码语言:javascript复制
@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";
   }
}
代码语言:javascript复制
@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;
   }
}
代码语言:javascript复制
@EnableAspectJAutoProxy
@Configuration
public class MyConfiguration {
    @Bean(name = "bean")
    public MyBean bean(){
      return new MyBean();
    }

    @Bean
    public LogAspect logAspect(){
        return new LogAspect();
    }
}
代码语言:javascript复制
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方式
代码语言:javascript复制
<aop:aspectj-autoproxy/>
  • 注解方式
代码语言:javascript复制
@EnableAspectJAutoProxy

我们下面先依次分析一下,这两种方式是如何通过不同的方式,来启用的注解式aop功能


xml方式–< aop:aspectj-autoproxy/ >

下面这篇文章讲过spring的标签解析过程,aop:aspectj-autoproxy严格来说属于自定义标签,

spring默认和自定义标签的解析过程

代码语言:javascript复制
< aop:aspectj-autoproxy/ >

不属于spring的默认标签,也算自定义标签的行列,因此我们来回顾一下自定义标签的解析过程是什么样子的:

既然是自定义标签,那么对应就需要有一个自定义命名空间的解析器—即NameSpaceHandler,而spring-aop给aop的自定义命名空间,提供一个AopNameSpaceHandler,负责解析aop:开头的命名空间。

代码语言:javascript复制
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标签的,这里我们最关心的是下面这行代码:

代码语言:javascript复制
		registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());

显然AspectJAutoProxyBeanDefinitionParser是用来解析aop:aspectj-autoproxy这个标签的,下面看一下他的parse方法做了什么事情

,因为当spring解析到这个标签的时候,会定位到AspectJAutoProxyBeanDefinitionParser,然后调用其parse方法进行解析


AspectJAutoProxyBeanDefinitionParser —专门解析aop:aspectj-autoproxy标签
代码语言:javascript复制
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方法:

代码语言:javascript复制
	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

代码语言:javascript复制
	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–注册自动代理创建器
代码语言:javascript复制
	public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
			BeanDefinitionRegistry registry, @Nullable Object source) {
//注册还是对代理创建器进行升级
		return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
	}
代码语言:javascript复制
@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完成代理
代码语言:javascript复制
	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中
代码语言:javascript复制
	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

代码语言:javascript复制
//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—为容器注册 自动代理创建器
代码语言:javascript复制
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后置处理器。

代码语言:javascript复制
	public void refresh() throws BeansException, IllegalStateException {
			prepareRefresh();
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
			prepareBeanFactory(beanFactory);
			postProcessBeanFactory(beanFactory);
			//触发调用工厂bean的后置处理器
			invokeBeanFactoryPostProcessors(beanFactory);
        ...

invokeBeanFactoryPostProcessors方法

代码语言:javascript复制
	protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
		PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
...
	}

PostProcessorRegistrationDelegate的invokeBeanFactoryPostProcessors方法
代码语言:javascript复制
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方法
代码语言:javascript复制
	private static void invokeBeanDefinitionRegistryPostProcessors(
			Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry, ApplicationStartup applicationStartup) {

		for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
			StartupStep postProcessBeanDefRegistry = applicationStartup.start("spring.context.beandef-registry.post-process")
					.tag("postProcessor", postProcessor::toString);
			//调用这类工厂bean后置处理器的postProcessBeanDefinitionRegistry方法,向容器中放入一下bean的定义		
			postProcessor.postProcessBeanDefinitionRegistry(registry);
			postProcessBeanDefRegistry.end();
		}
	}

ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法
代码语言:javascript复制
	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
         ....
         //处理配置类中bean的定义    
 		processConfigBeanDefinitions(registry);
	}

ConfigurationClassPostProcessor的processConfigBeanDefinitions方法
代码语言:javascript复制
	public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
		List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
		String[] candidateNames = registry.getBeanDefinitionNames();
       //将容器中所有标注了@Configuration注解的配置类加入configCandidates集合
		for (String beanName : candidateNames) {
			BeanDefinition beanDef = registry.getBeanDefinition(beanName);
			if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
				if (logger.isDebugEnabled()) {
					logger.debug("Bean definition has already been processed as a configuration class: "   beanDef);
				}
			}
			else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
				configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
			}
		}

		// Return immediately if no @Configuration classes were found
		if (configCandidates.isEmpty()) {
			return;
		}

		// Sort by previously determined @Order value, if applicable
		//配置类集合排序---通过配置类上的@order注解决定
		configCandidates.sort((bd1, bd2) -> {
			int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
			int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
			return Integer.compare(i1, i2);
		});

		// Detect any custom bean name generation strategy supplied through the enclosing application context
	//尝试从容器中获取自定义的bean名称生成器,该自定义bean名字生成器的beanName是固定的CONFIGURATION_BEAN_NAME_GENERATOR
		SingletonBeanRegistry sbr = null;
		if (registry instanceof SingletonBeanRegistry) {
			sbr = (SingletonBeanRegistry) registry;
			if (!this.localBeanNameGeneratorSet) {
				BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
						AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
				if (generator != null) {
					this.componentScanBeanNameGenerator = generator;
					this.importBeanNameGenerator = generator;
				}
			}
		}

		if (this.environment == null) {
			this.environment = new StandardEnvironment();
		}

		// Parse each @Configuration class
		//通过ConfigurationClassParser挨个解析每个配置类
		ConfigurationClassParser parser = new ConfigurationClassParser(
				this.metadataReaderFactory, this.problemReporter, this.environment,
				this.resourceLoader, this.componentScanBeanNameGenerator, registry);

		Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
		Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
		do {
			StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
			//parser.parse(candidates);这个过程是解析配置类的关键过程,但是我们这里不进行深入分析,因为本文重点不在于此
			//但是该方法会去拿到import注解上导入的ImportBeanDefinitionRegistrar,然后放入当前后置处理器的对应集合中保存起来
			parser.parse(candidates);
			parser.validate();

			Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
			configClasses.removeAll(alreadyParsed);

			// Read the model and create bean definitions based on its content
			//ConfigurationClassBeanDefinitionReader配置类bean定义信息读取
			if (this.reader == null) {
				this.reader = new ConfigurationClassBeanDefinitionReader(
						registry, this.sourceExtractor, this.resourceLoader, this.environment,
						this.importBeanNameGenerator, parser.getImportRegistry());
			}
			//去加载bean的定义,我们自动代理创建器的那个注册方法在该方法中被调用
			this.reader.loadBeanDefinitions(configClasses);
			alreadyParsed.addAll(configClasses);
			processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();
...
	}

这个方法非常关键,但是对于我们要探究自动代理配置器的注册过程而言,只需要重点关注parser.parse(candidates);和this.reader.loadBeanDefinitions(configClasses);方法即可


ConfigurationClassParser的parse方法
代码语言:javascript复制
	protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
		processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
	}

ConfigurationClassParser的processConfigurationClass方法
代码语言:javascript复制
	protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
	...
		do {
		//真正处理解析配置类的方法
			sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
		}
		while (sourceClass != null);

		this.configurationClasses.put(configClass, configClass);
	}

ConfigurationClassParser的doProcessConfigurationClass方法
代码语言:javascript复制
	protected final SourceClass doProcessConfigurationClass(
			ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
			throws IOException {
....
		// Process any @Import annotations
		//关注这里***
		processImports(configClass, sourceClass, getImports(sourceClass), filter, true);

	...
	}

ConfigurationClassParser的processImports方法—处理@Import注解的方法
代码语言:javascript复制
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
			Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
			boolean checkForCircularImports) {

		if (importCandidates.isEmpty()) {
			return;
		}

		if (checkForCircularImports && isChainedImportOnStack(configClass)) {
			this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
		}
		else {
			this.importStack.push(configClass);
			try {
			//拿到import导入的所有bean,挨个处理
				for (SourceClass candidate : importCandidates) {
					//如果导入的bean继承了ImportSelector,那么进行相关处理
					if (candidate.isAssignable(ImportSelector.class)) {
				...
					}
					//如果导入的bean继承了ImportBeanDefinitionRegistrar,那么进行相关处理
					//这不就是AspectJAutoProxyRegistrar继承的父接口吗
					else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
						// Candidate class is an ImportBeanDefinitionRegistrar ->
						// delegate to it to register additional bean definitions
						//实例化该导入bean定义的注册器
						Class<?> candidateClass = candidate.loadClass();
						ImportBeanDefinitionRegistrar registrar =
								ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
										this.environment, this.resourceLoader, this.registry);
						//添加到	configClass的相关属性集合中去			
						configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
					}
					else {
						// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
						// process it as an @Configuration class
						this.importStack.registerImport(
								currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
						processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
					}
				}
			}
...
		}
	}

到这里我们已经知道了import导入的bean如果继承了ImportBeanDefinitionRegistrar接口,那么会被放到ConfigurationClass的ImportBeanDefinitionRegistrars集合中进行保存


ConfigurationClassBeanDefinitionReader的loadBeanDefinitions方法
代码语言:javascript复制
			// Read the model and create bean definitions based on its content
			if (this.reader == null) {
				this.reader = new ConfigurationClassBeanDefinitionReader(
						registry, this.sourceExtractor, this.resourceLoader, this.environment,
						this.importBeanNameGenerator, parser.getImportRegistry());
			}
			this.reader.loadBeanDefinitions(configClasses);

分析一下该方法:

代码语言:javascript复制
	public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
		TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
		for (ConfigurationClass configClass : configurationModel) {
			loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
		}
	}

ConfigurationClassBeanDefinitionReader的loadBeanDefinitionsForConfigurationClass方法
代码语言:javascript复制
	private void loadBeanDefinitionsForConfigurationClass(
			ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {

		if (trackedConditionEvaluator.shouldSkip(configClass)) {
			String beanName = configClass.getBeanName();
			if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
				this.registry.removeBeanDefinition(beanName);
			}
			this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
			return;
		}

		if (configClass.isImported()) {
			registerBeanDefinitionForImportedConfigurationClass(configClass);
		}
		for (BeanMethod beanMethod : configClass.getBeanMethods()) {
			loadBeanDefinitionsForBeanMethod(beanMethod);
		}

		loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
		//看这里---详细大家应该猜到了,configClass在parse步骤就已经拿到了当前配置类上的ImportBeanDefinitionRegistrar
		//并保存在其自身的属性集合中
		loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
	}

ConfigurationClassBeanDefinitionReader的loadBeanDefinitionsFromRegistrars方法
代码语言:javascript复制
	private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
		registrars.forEach((registrar, metadata) ->
				registrar.registerBeanDefinitions(metadata, this.registry, this.importBeanNameGenerator));
	}

依次调用每个BeanDefinitionsFromRegistrar的registerBeanDefinitions方法


AspectJAutoProxyRegistrar的loadBeanDefinitionsFromRegistrars方法—圆回来了
代码语言:javascript复制
	public void registerBeanDefinitions(
			AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

		AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

		AnnotationAttributes enableAspectJAutoProxy =
				AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
		if (enableAspectJAutoProxy != null) {
			if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
				AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
			}
			if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
				AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
			}
		}
	}

AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary方法已经分析过了,这里不再多讲

0 人点赞