在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:
- ConfigurationClassPostProcessor
- AutowiredAnnotationBeanPostProcessor
- CommonAnnotationBeanPostProcessor
- EventListenerMethodProcessor
- …
这里主要关注的一个类是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
注解的类的资源,这里涉及到两个类ConfigurationClassParser
和ConfigurationClassBeanDefinitionReader
,一般在启动的时候,我们会传入一个类,这个类上面有@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