本文是Spring系列文章的一部分。其他相关文章见
Spring系列文章导航
本文详解解析Configuration标记的配置类的过程。
前言
前边提到**register(componentClasses)**将完成@Configuration标记的配置类的解析,本文就详解该方法。
一、回顾流程
首先贴代码。
/**
* Create a new AnnotationConfigApplicationContext, deriving bean definitions
* from the given component classes and automatically refreshing the context.
* @param componentClasses one or more component classes — for example,
* {@link Configuration @Configuration} classes
*/
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
register(componentClasses);
refresh();
}
从注解中,我们可以了解到,在AnnotationConfigApplicationContext初始化的时候,需要给容器传入一个被Configuration标记的配置类,register负责解析。
二、详解register解析过程
@Override
public void register(Class<?>... componentClasses) {
Assert.notEmpty(componentClasses, "At least one component class must be specified");
this.reader.register(componentClasses);
}
public void register(Class<?>... componentClasses) {
for (Class<?> componentClass : componentClasses) {
registerBean(componentClass);
}
}
public void registerBean(Class<?> beanClass) {
doRegisterBean(beanClass, null, null, null, null);
}
上边过程没有分支和子类重写问题,轻易能跟到doRegisterBean方法。
将细节去掉,剩下如下几行代码:
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
将beanClass封装成BeanDefiniton,将BeanDefiniton交给BeanDefinitionHolder,注册。
进入registerBeanDefinition方法,忽略其他,重要的可以只看下边两行代码。再之后是注册别名,这不是本文的主线,所以忽略。为什么要用Holder封装呢?这里也可以忽略,因为初学者一定要抓主线。
String beanName = definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
再跟一步,发现是个抽象类,该看哪个类的实现,读者先想一下,再看答案1。
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
this.beanFactory.registerBeanDefinition(beanName, beanDefinition);
}
是不是非常熟悉了。和前文是同一个方法,注册BeanDefinition。
//向map中注入<beanName, beanDefinition>的映射
this.beanDefinitionMap.put(beanName, beanDefinition);
//向set中注入beanName元素
this.beanDefinitionNames.add(beanName);
总结
配置类的BeanDefinition注册,到这里结束。
GenericApplicationContext ↩︎