spring源码解析AnnotationConfigApplicationContext启动流程分析,加载Bean信息

2022-06-14 08:37:46

在spring中提供了多种类型的ApplicationContext,其中AnnotationConfigApplicationContext用来支持基于注解的bean的生成和管理,其类继承结构如下:
在这里插入图片描述
一般启动AnnotationConfigApplicationContext如下:

@Configuration@ComponentScanpublicclassAnnotationContextTest{publicstaticvoidmain(String[] args){
        AnnotationConfigApplicationContext context=newAnnotationConfigApplicationContext(AnnotationContextTest.class);//AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.leo.test.annotation.test");
        HelloWorldService service= context.getBean(HelloWorldService.class);
        service.sayHello();}}

我们深入其源码,来看看其启动流程:

publicAnnotationConfigApplicationContext(){this.reader=newAnnotatedBeanDefinitionReader(this);this.scanner=newClassPathBeanDefinitionScanner(this);}

其默认构造如上,看起来平平无奇,只是新建了两个类,但是在AnnotatedBeanDefinitionReader里面大有文章:

publicAnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry){this(registry,getOrCreateEnvironment(registry));}publicAnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment){
		Assert.notNull(registry,"BeanDefinitionRegistry must not be null");
		Assert.notNull(environment,"Environment must not be null");this.registry= registry;this.conditionEvaluator=newConditionEvaluator(registry, environment, null);
		AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);}

从这里看,在实例化AnnotatedBeanDefinitionReader的构造方法中,调用了AnnotationConfigUtils.registerAnnotationConfigProcessors,从名称上看,这里是注册了很多的对注解的Processor,还记得之前说的,spring中这些processor的处理时机吗,可以看看这里spring中BeanFactoryPostProcessor、BeanPostProcessor、Aware接口
这里注册的类有大用处。我们看看到底注册了哪些类:

// AnnotationConfigUtilspublicstatic Set<BeanDefinitionHolder>registerAnnotationConfigProcessors(
			BeanDefinitionRegistry registry,@Nullable Object source){

		DefaultListableBeanFactory beanFactory=unwrapDefaultListableBeanFactory(registry);if(beanFactory!= null){if(!(beanFactory.getDependencyComparator()instanceofAnnotationAwareOrderComparator)){
				beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);}if(!(beanFactory.getAutowireCandidateResolver()instanceofContextAnnotationAutowireCandidateResolver)){
				beanFactory.setAutowireCandidateResolver(newContextAnnotationAutowireCandidateResolver());}}

		Set<BeanDefinitionHolder> beanDefs=newLinkedHashSet<>(8);if(!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)){
			RootBeanDefinition def=newRootBeanDefinition(ConfigurationClassPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));}if(!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)){
			RootBeanDefinition def=newRootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));}// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.if(jsr250Present&&!registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)){
			RootBeanDefinition def=newRootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));}// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.if(jpaPresent&&!registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)){
			RootBeanDefinition def=newRootBeanDefinition();try{
				def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
						AnnotationConfigUtils.class.getClassLoader()));}catch(ClassNotFoundException ex){thrownewIllegalStateException("Cannot load optional framework class: "+ PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);}
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));}if(!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)){
			RootBeanDefinition def=newRootBeanDefinition(EventListenerMethodProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));}if(!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)){
			RootBeanDefinition def=newRootBeanDefinition(DefaultEventListenerFactory.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));}return beanDefs;}

可以看到这里注册了如下Processor:

  1. ConfigurationClassPostProcessor
  2. AutowiredAnnotationBeanPostProcessor
  3. CommonAnnotationBeanPostProcessor
  4. EventListenerMethodProcessor

  5. 这里主要关注的一个类是ConfigurationClassPostProcessor,其类结构层次如下:
    在这里插入图片描述

之前我们在分析基于 xml的容器分析过程
spring容器启动过程分析,以ClassPathXmlApplicationContext为例说明 ,我们可以看到,在获取BeanFactory的时候:

protected ConfigurableListableBeanFactoryobtainFreshBeanFactory(){// refresh beanFactory实际上就是销毁之前旧的beanFactory,创建新的beanFactory,这里的refresh实际上就是生成一个新的beanFactoryrefreshBeanFactory();returngetBeanFactory();}

refreshBeanFactory的时候,其有两个实现类:
在这里插入图片描述
通过之前的分析我们知道,AbstractRefreshableApplicationContext在这里进行Bean信息的提取,也就是loadBeanDefinitions,

protectedfinalvoidrefreshBeanFactory()throws BeansException{//如果已经有了BeanFactory先销毁关闭它if(hasBeanFactory()){destroyBeans();closeBeanFactory();}try{//直接new 了一个 DefaultListableBeanFactory,// 并且在其继承父类中 AbstractAutowireCapableBeanFactory配置忽略自动装配的配置
			DefaultListableBeanFactory beanFactory=createBeanFactory();
			beanFactory.setSerializationId(getId());customizeBeanFactory(beanFactory);//这是重要的步骤,加载所有bean的配置,这是一个模板方法,由具体子类去实现loadBeanDefinitions(beanFactory);synchronized(this.beanFactoryMonitor){this.beanFactory= beanFactory;}}catch(IOException ex){thrownewApplicationContextException("I/O error parsing bean definition source for "+getDisplayName(), ex);}}

但是在GenericApplicationContext仅仅只是给了BeanFactory设置了一个ID,那么Bean相关信息是怎么载入的?

//GenericApplicationContextprotectedfinalvoidrefreshBeanFactory()throws IllegalStateException{if(!this.refreshed.compareAndSet(false,true)){thrownewIllegalStateException("GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");}this.beanFactory.setSerializationId(getId());}

这里就要说到上面介绍的ConfigurationClassPostProcessor,其实现BeanFactoryPostProcessor.postProcessBeanFactory方法中:

publicvoidpostProcessBeanFactory(ConfigurableListableBeanFactory beanFactory){int factoryId= System.identityHashCode(beanFactory);if(this.factoriesPostProcessed.contains(factoryId)){thrownewIllegalStateException("postProcessBeanFactory already called on this post-processor against "+ beanFactory);}this.factoriesPostProcessed.add(factoryId);if(!this.registriesPostProcessed.contains(factoryId)){// BeanDefinitionRegistryPostProcessor hook apparently not supported...// Simply call processConfigurationClasses lazily at this point then.processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);}enhanceConfigurationClasses(beanFactory);
		beanFactory.addBeanPostProcessor(newImportAwareBeanPostProcessor(beanFactory));}publicvoidprocessConfigBeanDefinitions(BeanDefinitionRegistry registry){
		List<BeanDefinitionHolder> configCandidates=newArrayList<>();
		String[] candidateNames= registry.getBeanDefinitionNames();for(String beanName: candidateNames){
			BeanDefinition beanDef= registry.getBeanDefinition(beanName);if(ConfigurationClassUtils.isFullConfigurationClass(beanDef)||
					ConfigurationClassUtils.isLiteConfigurationClass(beanDef)){if(logger.isDebugEnabled()){
					logger.debug("Bean definition has already been processed as a configuration class: "+ beanDef);}}elseif(ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef,this.metadataReaderFactory)){
				configCandidates.add(newBeanDefinitionHolder(beanDef, beanName));}}// Return immediately if no @Configuration classes were foundif(configCandidates.isEmpty()){return;}// Sort by previously determined @Order value, if applicable
		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
		SingletonBeanRegistry sbr= null;if(registryinstanceofSingletonBeanRegistry){
			sbr=(SingletonBeanRegistry) registry;if(!this.localBeanNameGeneratorSet){
				BeanNameGenerator generator=(BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);if(generator!= null){this.componentScanBeanNameGenerator= generator;this.importBeanNameGenerator= generator;}}}if(this.environment== null){this.environment=newStandardEnvironment();}// Parse each @Configuration class
		ConfigurationClassParser parser=newConfigurationClassParser(this.metadataReaderFactory,this.problemReporter,this.environment,this.resourceLoader,this.componentScanBeanNameGenerator, registry);

		Set<BeanDefinitionHolder> candidates=newLinkedHashSet<>(configCandidates);
		Set<ConfigurationClass> alreadyParsed=newHashSet<>(configCandidates.size());do{
			parser.parse(candidates);
			parser.validate();

			Set<ConfigurationClass> configClasses=newLinkedHashSet<>(parser.getConfigurationClasses());
			configClasses.removeAll(alreadyParsed);// Read the model and create bean definitions based on its contentif(this.reader== null){this.reader=newConfigurationClassBeanDefinitionReader(
						registry,this.sourceExtractor,this.resourceLoader,this.environment,this.importBeanNameGenerator, parser.getImportRegistry());}this.reader.loadBeanDefinitions(configClasses);
			alreadyParsed.addAll(configClasses);

			candidates.clear();if(registry.getBeanDefinitionCount()> candidateNames.length){
				String[] newCandidateNames= registry.getBeanDefinitionNames();
				Set<String> oldCandidateNames=newHashSet<>(Arrays.asList(candidateNames));
				Set<String> alreadyParsedClasses=newHashSet<>();for(ConfigurationClass configurationClass: alreadyParsed){
					alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());}for(String candidateName: newCandidateNames){if(!oldCandidateNames.contains(candidateName)){
						BeanDefinition bd= registry.getBeanDefinition(candidateName);if(ConfigurationClassUtils.checkConfigurationClassCandidate(bd,this.metadataReaderFactory)&&!alreadyParsedClasses.contains(bd.getBeanClassName())){
							candidates.add(newBeanDefinitionHolder(bd, candidateName));}}}
				candidateNames= newCandidateNames;}}while(!candidates.isEmpty());// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classesif(sbr!= null&&!sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)){
			sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());}if(this.metadataReaderFactoryinstanceofCachingMetadataReaderFactory){// Clear cache in externally provided MetadataReaderFactory; this is a no-op// for a shared cache since it'll be cleared by the ApplicationContext.((CachingMetadataReaderFactory)this.metadataReaderFactory).clearCache();}}

在spring的BeanFactor设置好之后,触发该方法,这里可以看到,主要就是扫描了代用@Cofiguration注解的类的资源,这里涉及到两个类ConfigurationClassParserConfigurationClassBeanDefinitionReader,一般在启动的时候,我们会传入一个类,这个类上面有@Cofiguration注解,这里就会对该类进行处理,在ConfigurationClassParser.parse中对带有@Cofiguration注解的类进行处理:

// ConfigurationClassParser.javapublicvoidparse(Set<BeanDefinitionHolder> configCandidates){for(BeanDefinitionHolder holder: configCandidates){
			BeanDefinition bd= holder.getBeanDefinition();try{if(bdinstanceofAnnotatedBeanDefinition){parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());}elseif(bdinstanceofAbstractBeanDefinition&&((AbstractBeanDefinition) bd).hasBeanClass()){parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());}else{parse(bd.getBeanClassName(), holder.getBeanName());}}...............}this.deferredImportSelectorHandler.process();}protectedfinalvoidparse(AnnotationMetadata metadata, String beanName)throws IOException{processConfigurationClass(newConfigurationClass(metadata, beanName));}protectedfinal SourceClassdoProcessConfigurationClass
  • 作者:Leo Han
  • 原文链接:https://blog.csdn.net/LeoHan163/article/details/114417017
    更新时间:2022-06-14 08:37:46