文章目录
- 1. prepareRefresh()方法进行准备工作
- 2. obtainFreshBeanFactory()方法获取BeanFactory
- 3. prepareBeanFactory(beanFactory)
- 4. postProcessBeanFactory(beanFactory);
- 5. invokeBeanFactoryPostProcessors(beanFactory);
- 6. registerBeanPostProcessors(beanFactory);
- 7. initMessageSource();
- 8. initApplicationEventMulticaster();
- 9. onRefresh();
- 10. registerListeners();
- 11. finishBeanFactoryInitialization(beanFactory);
- 12.finishRefresh();
不管是ClassPathXmlApplicationContext还是AnnotationConfigApplicationContext,在构造方法中都会调用refreh()方法来刷新上下文,创建BeanFactory以及BeanDefinition。
AbstractApplicationContext中创建BeanFactory的方法,主要是在refresh()这个方法中:
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 准备好刷新上下文(设置一些变量)
prepareRefresh();
/**
* obtainFreshBeanFactory()方法中根据实现类的不同调用不同的refreshBeanFactory()方法
* <----- 注解模式 ----->
* 1. 如果是使用AnnotationConfigApplicationContext来初始化环境
* 调用的是GenericApplicationContext#refreshBeanFactory()方法
* {@link GenericApplicationContext#refreshBeanFactory()}
* 在该方法中只是对beanFactory的一些变量进行设置
* <----- XML配置模式 ----->
* 2. 如果是使用ClassPathXmlApplicationContext来初始化环境
* 调用的是{@link AbstractRefreshableApplicationContext#refreshBeanFactory()}
* 由于还没有对beanFactory进行初始化,所以在该方法中,完成了对beanFactory的初始化操作
* 并对设置的资源位置进行扫描, 解析
* 注意:此方法是使用ClassPathXmlApplicationContext来初始化上下文是解析注册bean的重要入口 <-------------------重要
*/
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//对beanFactory进行属性设置
prepareBeanFactory(beanFactory);
try {
//允许在子类中对bean工厂进行后处理。
postProcessBeanFactory(beanFactory);
/**
* <----- 注解模式 ----->
* 1. 如果是使用AnnotationConfigApplicationContext来初始化环境(该方法是解析注册bean的重要入口) <--------------------重要
* 在该方法中执行了
* {@link org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions} 方法
* 对配置类进行解析(如果该注解bean是配置类则在这个方法里完成了包扫描操作) <--------------- 重要
* 注意:
* 1. 一般情况下, 此时beanFactory中只注册了这一个BeanFactoryPostProcessor类-->ConfigurationClassPostProcessor
* 在{@link AnnotationConfigUtils#registerAnnotationConfigProcessors(org.springframework.beans.factory.support.BeanDefinitionRegistry)}中注册的
* 2. 注解模式下,此时BeanDefinitionMap中含有6个Spring内部处理器类, 其中通过ConfigurationClassPostProcessor类来解析配置类,完成包扫描,bean注册等操作
* 然而, 在xml配置模式下, 此时BeanDefinitionMap只有自定义配置的BeanDefinition信息
*
* <----- XML配置模式 ----->
* 2. 如果是使用ClassPathXmlApplicationContext来初始化环境
* 默认情况下, 此时BeanDefinitionMap只有自定义配置的BeanDefinition信息, 并没有任何Spring内部所定义的BeanFactory后处理器
* 除非用户自定义了BeanFactory后处理器, 需要对BeanFactory进行修改, 那么才会执行对应后处理器里面的方法;
*
*/
invokeBeanFactoryPostProcessors(beanFactory);
//注册拦截bean创建的bean后处理处理器。
registerBeanPostProcessors(beanFactory);
//为上下文初始化Message源,即不同的语言体,国际化处理
initMessageSource();
// 初始化应用消息广播,并放入"appliactionEventMulitcaster"bean中
initApplicationEventMulticaster();
// 留给子类来初始化其他的Bean
onRefresh();
//在所有注册的bean中查找listener bean,注册到消息广播器中
registerListeners();
// 初始化剩下的单例(非延迟加载的,延迟加载的单例在第一次调用的时候初始化)
finishBeanFactoryInitialization(beanFactory);
//最后一步:完成刷新过程,通知生命周期处理器lifecycleProcessor刷新过程,同时发出ContextRefreshEvent通知别人
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// 销毁已创建的单例以避免资源悬空。
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
resetCommonCaches();
}
}
}
1. prepareRefresh()方法进行准备工作
protected void prepareRefresh() {
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
// Initialize any placeholder property sources in the context environment
//空实现
initPropertySources();
// Validate that all properties marked as required are resolvable
// see ConfigurablePropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties();
// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}
属性校验AbstractEnvironment.validateRequiredProperties():
@Override
public void validateRequiredProperties() throws MissingRequiredPropertiesException {
this.propertyResolver.validateRequiredProperties();
}
2. obtainFreshBeanFactory()方法获取BeanFactory
-
如果是使用AnnotationConfigApplicationContext来初始化环境: 调用的是
GenericApplicationContext#refreshBeanFactory()
方法,在该方法中只是对beanFactory的一些变量进行设置; -
如果是使用ClassPathXmlApplicationContext来初始化环境: 调用的是
AbstractRefreshableApplicationContext#refreshBeanFactory()
, 由于还没有对beanFactory进行初始化, 所以在该方法中, 完成了对beanFactory的初始化操作, 并对设置的资源位置进行扫描, 解析。具体分析一下AbstractRefreshableApplicationContext#refreshBeanFactory():
@Override
protected final void refreshBeanFactory() throws BeansException {
//如果已经存在,那么销毁之前的
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
//创建了一个DefaultListableBeanFactory对象
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
2.1 实例化一个DefaultListableBeanFactory对象
调用createBeanFactory()方法:
protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}
BeanFactory接口接口实际上就是Bean容器,其继承体系:
2.2 BeanFactory定制
AbstractRefreshableApplicationContext.customizeBeanFactory方法用于给子类提供一个自由配置的机会,默认实现:
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
if (this.allowBeanDefinitionOverriding != null) {
//默认false,不允许覆盖
beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
if (this.allowCircularReferences != null) {
//默认false,不允许循环引用
beanFactory.setAllowCircularReferences(this.allowCircularReferences);
}
}
2.3 Bean加载
Bean就是被Spring管理的对象,其实源码中并没有Bean这个东西,只有一个注解@Bean。但是有一个BeanDefinition来描述Bean。BeanDefinition就是Bean这个概念在Spring中的描述,有了BeanDefinition我们就可以创建Bean,BeanDefinition是Bean在spring中的定义形态。
BeanDefinition数据结构:
AbstractXmlApplicationContext.loadBeanDefinitions,这个便是核心的bean加载过程了:
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
//默认空实现
initBeanDefinitionReader(beanDefinitionReader);
loadBeanDefinitions(beanDefinitionReader);
}
XmlBeanDefinitionReader 就是负责从XML配置文件中解析BeanDefinition的。ResourceEntityResolver用于schema和dtd的解析。
(1)配置文件加载
而这个loadBeanDefinitions(beanDefinitionReader)方法内部,实际上就是调用了XmlBeanDefinitionReader的loadBeanDefinitions()方法:
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
Resource[] configResources = getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
String[] configLocations = getConfigLocations();
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}
最终都会调用loadBeanDefinitions(EncodedResource encodedResource) 这个方法:
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
// 注释 1.7 从资源文件中获取输入流
InputStream inputStream = encodedResource.getResource().getInputStream();
InputSource inputSource = new InputSource(inputStream);
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
再执行doLoadBeanDefinitions()方法:
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {
try {
Document doc = doLoadDocument(inputSource, resource);
int count = registerBeanDefinitions(doc, resource);
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + count + " bean definitions from " + resource);
}
return count;
catch (Exception ex) {
throw ex;
}
}
其实重点是就是两行代码doLoadDocument()和registerBeanDefinitions()方法
- doLoadDocument(inputSource, resource)是用来将xml文件解析成Document对象:
protected Document doLoadDocument(InputSource inputSource, Resource resource) {
return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
getValidationModeForResource(resource), isNamespaceAware());
}
(2) Bean解析注册
而registerBeanDefinitions(doc, resource)用来解析注册BeanDefinition的:
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
int countBefore = getRegistry().getBeanDefinitionCount();
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
(2.1). 创建解析器
createBeanDefinitionDocumentReader():
protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {
return BeanDefinitionDocumentReader.class.cast
//反射
(BeanUtils.instantiateClass(this.documentReaderClass));
}
documentReaderClass默认是DefaultBeanDefinitionDocumentReader,这其实也是策略模式,通过setter方法可以更换其实现。
createReaderContext():
public XmlReaderContext createReaderContext(Resource resource) {
return new XmlReaderContext(resource, this.problemReporter, this.eventListener,
this.sourceExtractor, this, getNamespaceHandlerResolver());
}
problemReporter是一个FailFastProblemReporter对象。
eventListener是EmptyReaderEventListener对象,此类里的方法都是空实现。
sourceExtractor是NullSourceExtractor对象,直接返回空,也是空实现。
getNamespaceHandlerResolver默认返回DefaultNamespaceHandlerResolver对象,用来获取xsd对应的处理器。
XmlReaderContext的作用感觉就是这一堆参数的容器,糅合到一起传给DocumentReader,并美其名为Context。可以看出,Spring中到处都是策略模式,大量操作被抽象成接口。
registerBeanDefinitions():
DefaultBeanDefinitionDocumentReader是BeanDefinitionDocumentReader的一个具体实现类,它的registerBeanDefinitions()方法实际调用的是doRegisterBeanDefinitions(doc.getDocumentElement())这个方法:
protected void doRegisterBeanDefinitions(Element root) {
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(getReaderContext(), root, parent);
//默认的命名空间即
//http://www.springframework.org/schema/beans
if (this.delegate.isDefaultNamespace(root)) {
//检查profile属性
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
//profile属性可以以,分割
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
return;
}
}
}
preProcessXml(root);
parseBeanDefinitions(root, this.delegate);
postProcessXml(root);
this.delegate = parent;
}
先调用createDelegate()方法创建一个BeanDefinitionParserDelegate对象,delegate的作用在于处理beans标签的嵌套。例如:
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean class="base.SimpleBean"></bean>
<beans>
<bean class="java.lang.Object"></bean>
</beans>
</beans>
preProcessXml()方法是个空实现,供子类去覆盖,目的在于给子类一个把我们自定义的标签转为Spring标准标签的机会, 想的真周到。
(2.2). 命名空间解析
parseBeanDefinitions()是重点方法:
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
parseDefaultElement(ele, delegate);
} else {
delegate.parseCustomElement(ele);
}
}
}
} else {
delegate.parseCustomElement(root);
}
}
对于非默认命名空间的元素交由delegate处理。如果是默认命名空间的元素值直接调用parseDefaultElement()方法解析。
默认命名空间解析
默认命名空间解析,即import, alias, bean, 以及嵌套的beans
四种标签。parseDefaultElement():
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
//"import"
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
- importBeanDefinitionResource()解析import标签。
- processAliasRegistration()解析alias标签。
- doRegisterBeanDefinitions(ele);就是处理嵌套的beans标签,实际即使递归调用doRegisterBeanDefinitions()这个方法。
- processBeanDefinition()解析bean标签,bean标签是Spring配置文件中最最常见的节点了。看一下processBeanDefinition(ele, delegate);这个方法是怎么处理bean标签的:
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
BeanDefinitionReaderUtils.registerBeanDefinition
(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event.
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
首先就是通过delegate.delegate.parseBeanDefinitionElement(ele, bdHolder)获得一个BeanDefinitionHolder对象。然后调用BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());注册bdHolder。
前面说到非默认的标签会交给delegate.parseCustomElement(ele)方法处理,到这一步一看,默认的标签交给了delegate.parseBeanDefinitionElement(ele)方法处理。其实都是交给BeanDefinitionParserDelegate这个类来处理,只不过是不同的方法。直接看parseBeanDefinitionElement()方法:
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
// 获取 ID 属性
String id = ele.getAttribute(ID_ATTRIBUTE);
// 获取 NAME 属性
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
List<String> aliases = new ArrayList<>();
if (StringUtils.hasLength(nameAttr)) {
// 名称按照 , ; 进行分割
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}
String beanName = id;
if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
// 如果没有指定 id,将 name 的第一个值作为 id
beanName = aliases.remove(0);
}
// 默认 null
if (containingBean == null) {
// 检查名字是否唯一,如果 id 重复了,将抛出错误
// 内部 usedNames 是一个 HashSet,将会存储加载过的 name 和 aliases
checkNameUniqueness(beanName, aliases, ele);
}
// 将公共属性放入 AbstractBeanDefinition,具体实现在子类 GenericBeanDefinition
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
if (!StringUtils.hasText(beanName)) {
if (containingBean != null) {
// 如果 id 和 name 都是空,那个 spring 会给它生成一个默认的名称
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
}
else {
beanName = this.readerContext.generateBeanName(beanDefinition);
String beanClassName = beanDefinition.getBeanClassName();
if (beanClassName != null &&
beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
aliases.add(beanClassName);
}
}
}
}
String[] aliasesArray = StringUtils.toStringArray(aliases);
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
return null;
}
该方法主要工作流程如下:
- 提取元素中的 id, name 属性
- 进一步解析其它所有属性并统一封装到 GenericBeanDefinition 类型的实例中
- 检测到 bean 没有指定 beanName 使用默认规则生成 beanName
- 再通过parseBeanDefinitionElement(ele, beanName, containingBean);方法解析其他属性,同时创建了一个GenericBeanDefinition对象。
- 将获取到的信息封装到 BeanDefinitionHolder 的实例中
也就是在parseBeanDefinitionElement()这个方法里面获取了bean标签中的id和name以及其他属性
,然后返回一个BeanDefinitionHolder对象
。
(2.3). 注册BeanDefinition
在DefaultBeanDefinitionDocumentReader的processBeanDefinition()方法中,拿到BeanDefinitionHolder对象对象之后,调用BeanDefinitionReaderUtils.registerBeanDefinition (bdHolder, getReaderContext().getRegistry())
进行注册:
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) {
// Register bean definition under primary name.
String beanName = definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// Register aliases for bean name, if any.
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
registry其实就是DefaultListableBeanFactory对象,DefaultListableBeanFactory的registerBeanDefinition()方法其实主要就干了这么两件事:
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
}
beanDefinitionMap其实就是BeanFactory中的一个ConcurrentHashMap:
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
beanDefinitionNames是BeanFactory中的一个List:
private volatile List beanDefinitionNames = new ArrayList<>(256);
然后registerAlias()方法的实现在其祖先类SimpleAliasRegistry,就是把beanName和alias键值对放在了一个ConcurrentHashMap里:
private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);
看一下BeanDefinition在BeanFactory中的有关数据结构如下图:
到这里BeanDefinition也就解析生成并且注册到BeanFactory中了。
3. prepareBeanFactory(beanFactory)
准备类加载器的环境,对前面获取到的 beanFactory(ConfigurationListableBeanFactory) 进行“特征”相关的设置,包括:
(1)BeanExpressionResolver
这便是Spring3.0开始出现的Spel表达式的解释器。
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
(2)PropertyEditorRegistrar
用于向Spring注册java.beans.PropertyEditor。在编写xml配置时,我们设置的值都是字符串形式,所以在使用时肯定需要转为我们需要的类型,PropertyEditor接口正是定义了这么个东西。
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
(3)环境注入
在Spring中我们自己的bean可以通过实现EnvironmentAware等一系列Aware接口获取到Spring内部的一些对象。
// Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
(4)依赖解析忽略
此部分设置哪些接口在进行依赖注入的时候应该被忽略:
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
beanFactory.ignoreDependencyInterface(ApplicationStartup.class);
(5)bean伪装
有些对象并不在BeanFactory中,但是我们依然想让它们可以被装配,这就需要伪装一下:
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
伪装关系保存在一个Map<Class<?>, Object>里。
(6)LoadTimeWeaver
添加静态aop处理所需要的类:
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
(7)注册环境
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().
getSystemEnvironment());
}
4. postProcessBeanFactory(beanFactory);
// Allows post-processing of the bean factory in context subclasses.
此方法允许子类在所有的bean尚未初始化之前注册BeanPostProcessor。空实现,留给子类实现, 允许在子类中对bean工厂进行后处理
5. invokeBeanFactoryPostProcessors(beanFactory);
// Invoke factory processors registered as beans in the context.
实例化并调用所有注册的 BeanFactoryPostProcessorBean,这些是后处理器,处理类型是 BeanFactory, Spring 容器允许在实例化 bean 前,读取 bean 信息和修改它的属性。
相当于在实例化前,给用户最后一次机会去修改 bean 信息。
还有一点,执行也可以有先后顺序,依据这些处理器是否实现 PriorityOrdered 、Order 接口,根据 order 值进行排序。
(1) 如果是使用AnnotationConfigApplicationContext来初始化环境(该方法是解析注册bean的重要入口)在该方法中执行了ConfigurationClassPostProcessor#processConfigBeanDefinitions} 方法对配置类进行解析(如果该注解bean是配置类则在这个方法里完成了包扫描操作)
(2) 如果是使用ClassPathXmlApplicationContext来初始化环境, 默认情况下, 此时BeanDefinitionMap只有自定义配置的BeanDefinition信息, 并没有任何Spring内部所定义的BeanFactory后处理器; 除非用户自定义了BeanFactory后处理器, 需要对BeanFactory进行修改, 那么才会执行对应后处理器里面的方法;
注意: 注解模式下,此时BeanDefinitionMap中含有6个Spring内部处理器类(但是只有一个BeanFactoryPostProcessor类的实例–>ConfigurationClassPostProcessor), 其中通过ConfigurationClassPostProcessor类来解析配置类,完成包扫描,bean注册等操作; 然而, 在xml配置模式下, 此时BeanDefinitionMap只有自定义配置的BeanDefinition信息
6. registerBeanPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
上面BeanFactoryPostProcessor是BeanFactory后置处理器,这里BeanPostProcessor是Bean后置处理器。此部分实质上是在BeanDefinitions中寻找BeanPostProcessor,之后调用BeanFactory.addBeanPostProcessor方法保存在一个List中,注意添加时仍然有优先级的概念,优先级高的在前面。
7. initMessageSource();
初始化此上下文的消息源,即不同的语言体,国际化处理。
8. initApplicationEventMulticaster();
//Initialize event multicaster for this context.
初始化应用消息广播,并放入"appliactionEventMulitcaster"bean中
9. onRefresh();
// Initialize other special beans in specific context subclasses.
模板方法,可被重写以添加特定于上下文的刷新工作。
在实例化单例之前调用特殊 bean 的初始化。
此实现为空,留给子类来初始化其他的Bean。
10. registerListeners();
// Check for listener beans and register them.
在所有注册的bean中查找listener bean,注册到消息广播器中
11. finishBeanFactoryInitialization(beanFactory);
// Instantiate all remaining (non-lazy-init) singletons.
完成 bean 容器的初始化,初始化剩下的非延迟加载的单例(延迟加载的单例在第一次需要调用的时候初始化)。
12.finishRefresh();
// Last step: publish corresponding event.
真真注册的最后一步,用来清除缓存,重置 Spring 核心中的公共内省缓存,因为我们可能再也不需要单例 bean 的元数据了。完成刷新过程,通知生命周期处理器lifecycleProcessor刷新过程,同时发出ContextRefreshEvent通知别人
参考:
- IOC容器初始化方式四: AnnotationConfigApplicationContext[Java配置类方式]
- 源码
- Spring ApplicationContext 中的getBean方法的深入分析
- 源码解析
- 源码分析
- Spring使用
THE END.