Spring源码分析
第五章 Spring Ioc的初始化前言
这一章,我们主要分析一下 Spring Ioc的初始化详细流程,在分析详细流程之前,简单了解一下spring Ioc的容器体系及Spring Bean的生命周期
一、Spring IoC的容器体系
IoC容器是Spring的核心模块,是抽象了对象管理、依赖关系管理的框架解决⽅案。Spring 提供了很多 的容器,其中BeanFactory 是顶层容器(根容器),不能被实例化,它定义了所有 IoC 容器 必须遵从的⼀套原则,具体的容器实现可以增加额外的功能,比如我们常⽤到的ApplicationContext,其下更具 体的实现如ClassPathXmlApplicationContext 包含了解析 xml 等⼀系列的内容,AnnotationConfigApplicationContext 则是包含了注解解析等⼀系列的内容。Spring IoC 容器继承体系⾮常聪明,需要使⽤哪个层次⽤哪个层次即可,不必使⽤功能⼤而全的。
BeanfFactory顶级接⼝方法栈如下:
BeanFactory 容器继承体系:
通过其接⼝设计,我们可以看到我们⼀贯使⽤的 ApplicationContext
除了继承BeanFactory的⼦接⼝,还继承了ResourceLoader、MessageSource等接⼝,因此其提供的功能也就更丰富了。
二、Spring Bean的生命周期
Spring
对Bean
进行实例化(相当于程序中的new Xx()
)Spring
将值和Bean
的引用注入进Bean
对应的属性中- 如果
Bean
实现了BeanNameAware
接口,Spring
将Bean
的ID
传递给setBeanName()
方法(实现BeanNameAware
主要是为了通过Bean
的引用来获得Bean
的ID
,一般业务中是很少有用到Bean
的ID
的) - 如果
Bean
实现了BeanFactoryAware
接口,Spring
将调用setBeanDactory
(BeanFactory
bf
)方法并把BeanFactory
容器实例作为参数传入。(实现BeanFactoryAware
主要目的是为了获取Spring
容器,如Bean
通过Spring
容器发布事件等) - 如果
Bean
实现了ApplicationContextAwaer
接口,Spring
容器将调用setApplicationContext
(ApplicationContext
ctx
)方法,把y应用上下文作为参数传入.(作用与BeanFactory
类似都是为了获取Spring
容器,不同的是Spring
容器在调用setApplicationContext
方法时会把它自己作为setApplicationContext
的参数传入,而Spring容器在调用setBeanDactory
前需要程序员自己指定(注入)setBeanFactory
里的参数BeanFactory
) - 如果
Bean
实现了BeanPostProcess
接口,Spring
将调用它们的postProcessBeforeInitialization
(预初始化)方法(作用是在Bean
实例创建成功后对进行增强处理,如对Bean
进行修改,增加某个功能) - 如果
Bean
实现了InitializingBean
接口,Spring
将调用它们的afterPropertiesSet
方法,作用与在配置文件中对Bean
使用init-method
声明初始化的作用一样,都是在Bean
的全部属性设置成功后执行的初始化方法。 - 如果
Bean
实现了BeanPostProcess
接口,Spring
将调用它们的postProcessAfterInitialization
(后初始化)方法(作用与6的一样,只不过6是在Bean
初始化前执行的,而这个是在Bean
初始化后执行的,时机不同 ) - 经过以上的工作后,
Bean
将一直驻留在应用上下文中给应用使用,直到应用上下文被销毁 - 如果
Bean
实现了DispostbleBean
接口,Spring
将调用它的destory
方法,作用与在配置文件中对Bean
使用destory-method
属性的作用一样,都是在Bean
实例销毁前执行的方法。
三、Spring Ioc的初始化过程
相信大家对这段代码都很熟悉:
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
LagouBean lagouBean = applicationContext.getBean(LagouBean.class);
System.out.println(lagouBean);
上面代码中,在创建ApplicationContext
实例对象过程中会创建一个spring
容器,该容器会读取配置文件cjj/models/beans.xml
,并统一管理由该文件中定义好的所有bean
实例对象,如果要获取某个bean实例,使用getBean
方法就行了。
回到正题上来,关于Spirng IoC容器的初始化过程在《Spirng技术内幕:深入解析Spring架构与设计原理》一书中有明确的指出,IoC容器的初始化过程可以分为三步:
Resource
定位(Bean的定义文件定位)- 将
Resource
定位好的资源载入到BeanDefinition
- 将
BeanDefiniton
注册到容器中
下面就通过源码分析来具体研究一下Spirng IoC
容器的初始化过程。
四、Spring Ioc的初始化过程详解
启动一下测试代码:
public void testIoC() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
LagouBean lagouBean = applicationContext.getBean(LagouBean.class);
System.out.println(lagouBean);
}
可以看到程序进入:
ClassPathXmlApplicationContext.java
//创建一个新的ClassPathXmlApplicationContext,加载定义
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
// 继续执行
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)throws BeansException {
// 初始化父类
super(parent);
// 设置本地的配置信息
setConfigLocations(configLocations);
// 初始化操作
if (refresh) {
refresh();
}
}
点击进入refresh
方法当中:
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
//刷新前的预处理;
prepareRefresh();
//获取BeanFactory;默认实现是DefaultListableBeanFactory,在创建容器的时候创建的
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//BeanFactory的预准备工作(BeanFactory进行一些设置,比如context的类加载器,BeanPostProcessor和XXXAware自动装配等)
prepareBeanFactory(beanFactory);
try {
//BeanFactory准备工作完成后进行的后置处理工作
postProcessBeanFactory(beanFactory);
//执行BeanFactoryPostProcessor的方法;
invokeBeanFactoryPostProcessors(beanFactory);
//注册BeanPostProcessor(Bean的后置处理器),在创建bean的前后等执行
registerBeanPostProcessors(beanFactory);
//初始化MessageSource组件(做国际化功能;消息绑定,消息解析);
initMessageSource();
//初始化事件派发器
initApplicationEventMulticaster();
//子类重写这个方法,在容器刷新的时候可以自定义逻辑;如创建Tomcat,Jetty等WEB服务器
onRefresh();
//注册应用的监听器。就是注册实现了ApplicationListener接口的监听器bean,这些监听器是注册到ApplicationEventMulticaster中的
registerListeners();
//初始化所有剩下的非懒加载的单例bean
finishBeanFactoryInitialization(beanFactory);
//完成context的刷新。主要是调用LifecycleProcessor的onRefresh()方法,并且发布事件(ContextRefreshedEvent)
finishRefresh();
}
......
}
可以看得出来,spring容器的启动,创建bean,bean的初始化等一系列过程都在这个refresh方法里面进行调用。我们先来看下这段代码:
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
这段代码,主要是用于获取BeanFactory
,默认实现是DefaultListableBeanFactory
,我们点击进入看下实现:
AbstractApplicationContext.java
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
return getBeanFactory();
}
可以猜到,getBeanFactory()
方法应该是获取ConfigurableListableBeanFactory
对象的一个方法,在这之前BeanFactory
应该已经完成创建,所以我们进入refreshBeanFactory()
方法,了解一下该方法的具体实现:
@Override
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
// 实例化DefaultListableBeanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
// 设置序列化Id
beanFactory.setSerializationId(getId());
// 自定义bean工厂的一些属性(是否允许覆盖 循环依赖)
customizeBeanFactory(beanFactory);
// 加载应用中的BeanDefinitions
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
简单解释下这段代码:
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
这一小段代码主要是用于判断是否已经存在一个BeanFactory,若果要是存在就将其销毁然后关闭;可以简单看下hasBeanFactory()
方法:
AbstractApplicationContext.java
protected final boolean hasBeanFactory() {
synchronized (this.beanFactoryMonitor) {
return (this.beanFactory != null);
}
}
接下来,我们来看下try...catch...
代码块里面的内容:
// 实例化DefaultListableBeanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
// 设置序列化Id
beanFactory.setSerializationId(getId());
// 自定义bean工厂的一些属性(是否允许覆盖 循环依赖)
customizeBeanFactory(beanFactory);
// 加载应用中的BeanDefinitions
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
DefaultListableBeanFactory
是bean
加载的核心部分,是Spring
注册及加载的默认实现。先来看下DefaultListableBeanFactory
的类图:
先概述接口部分:
BeanFactory
是Spring
的最根的接口,类的工厂接口。HierarchicalBeanFactory
接口是在继承BeanFactory
的基础上,实现BeanFactory
的父子关系。AutowireCapableBeanFactory
接口是在继承BeanFactory
的基础上,实现Bean
的自动装配功能ListableBeanFactory
接口是在继承BeanFactory
的基础上,实现Bean
的list
集合操作功能ConfigurableBeanFactory
接口是在继承HierarchicalBeanFactory
的基础上,实现BeanFactory
的全部配置管理功能,SingletonBeanRegistry
是单例bean
的注册接口ConfigurableListableBeanFactory
接口是继承AutowireCapableBeanFactory
,ListableBeanFactory
,ConfigurableBeanFactory
三个接口的一个综合接口
再概述类部分:
AliasRegistry
接口是别名注册接口,SimpleAliasRegistry
类是简单的实现别名注册接口的类。DefaultSingletonBeanRegistry
是默认的实现SingletonBeanRegistry
接口的类,同时,继承类SimpleAliasRegistry
。FactoryBeanRegistrySupport
是实现FactoryBean
注册的功能实现。继承类DefaultSingletonBeanRegistry
。AbstractBeanFactory
是部分实现接口ConfigurableBeanFactory
,并继承类FactoryBeanRegistrySupport
。AbstractAutowireCapableBeanFactory
是实现接口AutowireCapableBeanFactory
,并继承类AbstractBeanFactory
。DefaultListableBeanFactory
实现接口ConfigurableListableBeanFactory
、BeanDefinitionRegistry
(bean
定义的注册接口), 并继承AbstractAutowireCapableBeanFactory
,实现全部类管理的功能。
DefaultListableBeanFactory
其实要实现的功能就是以list集合的方式操作bean
,为什么要拆成这么多的类和接口呢。这里面可能基于几点考虑。
- 功能的不同维度,分不同的接口,方便以后的维护和其他人的阅读。如:
AutowireCapableBeanFactory
、ListableBeanFactory
、HierarchicalBeanFactory
等 - 不同接口的实现,分布在不同的之类里,方便以后不同接口多种实现的扩展
- 从整个类图的分布,可以看出
spring
在这块是面向接口编程,后面类的实现,他们认为只是接口功能实现的一种,随时可以拓展成多种实现以拓展成多种实现
最后来说下DefaultListableBeanFactory
的内部都维护了一些什么:
/** Optional id for this factory, for serialization purposes. */
@Nullable
private String serializationId;
/** Whether to allow re-registration of a different definition with the same name. */
private boolean allowBeanDefinitionOverriding = true;
/** Whether to allow eager class loading even for lazy-init beans. */
private boolean allowEagerClassLoading = true;
/** Optional OrderComparator for dependency Lists and arrays. */
@Nullable
private Comparator<Object> dependencyComparator;
/** Resolver to use for checking if a bean definition is an autowire candidate. */
private AutowireCandidateResolver autowireCandidateResolver = new SimpleAutowireCandidateResolver();
/** Map from dependency type to corresponding autowired value. */
private final Map<Class<?>, Object> resolvableDependencies = new ConcurrentHashMap<>(16);
/** Map of bean definition objects, keyed by bean name. */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
/** Map of singleton and non-singleton bean names, keyed by dependency type. */
private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<>(64);
/** Map of singleton-only bean names, keyed by dependency type. */
private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<>(64);
/** List of bean definition names, in registration order. */
private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
/** List of names of manually registered singletons, in registration order. */
private volatile Set<String> manualSingletonNames = new LinkedHashSet<>(16);
/** Cached array of bean definition names in case of frozen configuration. */
@Nullable
private volatile String[] frozenBeanDefinitionNames;
/** Whether bean definition metadata may be cached for all beans. */
private volatile boolean configurationFrozen = false;
可以看到,DefaultListableBeanFactory
内部维护了超级多的一些东西。我们主要关注两个属性:
// BeanDefinition 的存储 Map 其中 key 为 beanName
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
// BeanName 的集合
private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
正如注释所说,DefaultListableBeanFactory
内部维护了一个ConcurrentHashMap
,用于存储 beanName
与BeanDefinition
的映射关系。
简单了解了DefaultListableBeanFactory
之后,我们回到org.springframework.context.support.AbstractRefreshableApplicationContext#refreshBeanFactory
继续往下走:
// 设置序列化Id
beanFactory.setSerializationId(getId());
// 自定义bean工厂的一些属性(是否允许覆盖 循环依赖)
customizeBeanFactory(beanFactory);
这两行代码,一个是设置序列化相关的序列化ID
,另一个定义了bean
工厂的一些自定义属性,类似循环依赖,关于循环依赖暂时不做详细说明,放到下一节讨论,我们继续向下:
// 加载应用中的BeanDefinitions
loadBeanDefinitions(beanFactory);
这段代码用于加载应用中的BeanDefinitions
,我们来看下具体实现:
AbstractXmlApplicationContext.java
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// 给指定的BeanFactory创建一个XmlBeanDefinitionReader读取器对象,用于解析xml对象
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// 设置一些context应用上下文的环境属性
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// 为子类实现提供一些自定义的初始化策略
initBeanDefinitionReader(beanDefinitionReader);
// 加载BeanDefinitions
loadBeanDefinitions(beanDefinitionReader);
}
我们直接看最后一段代码
loadBeanDefinitions(beanDefinitionReader);
AbstractBeanDefinitionReader
类中loadBeanDefinitions
方法,使用beanDefinitionReader
解析xml
为beanDefinition
并填充到IOC
容器中,我们来看下具体实现:
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
// 从Resource资源对象加载BeanDefinitions
Resource[] configResources = getConfigResources();
if (configResources != null) {
//当ApplicationContext的入参是一个Resource对象的时候 走这个流程
//核心方法 BeanDefinitionReader 开始加载解析beanDefinitions
reader.loadBeanDefinitions(configResources);
}
// 从xml配置文件加载BeanDefinitions
String[] configLocations = getConfigLocations();
if (configLocations != null) {
//当ApplicationContext的入参是一个String形式的字符串路径的时候 走这个流程
//核心方法 BeanDefinitionReader 开始加载解析beanDefinitions
reader.loadBeanDefinitions(configLocations);
}
}
然后我们再来看下reader.loadBeanDefinitions(configLocations)
的具体实现:
AbstractBeanDefinitionReader.java
@Override
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
Assert.notNull(locations, "Location array must not be null");
int count = 0;
// 如果有多个配置文件,循环加载,并返回加载了多少个配置文件
for (String location : locations) {
count += loadBeanDefinitions(location);
}
return count;
}
这段代码中的for循环实际上就是循环加载配置文件,并把加载了多少个返回回去,我们继续向下进行,看一下loadBeanDefinitions(location)方法是如何加载配置文件的:
AbstractBeanDefinitionReader.java
@Override
public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
return loadBeanDefinitions(location, null);
}
public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
// 获取上下文的资源加载器
ResourceLoader resourceLoader = getResourceLoader();
if (resourceLoader == null) {
throw new BeanDefinitionStoreException(
"Cannot load bean definitions from location [" + location + "]: no ResourceLoader available");
}
// 判断资源加载器类型
if (resourceLoader instanceof ResourcePatternResolver) {
// Resource pattern matching available.
try {
// 统一转化为Resource
Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
// 加载配置中的eanDefinitions对象 并返回数量
int count = loadBeanDefinitions(resources);
if (actualResources != null) {
Collections.addAll(actualResources, resources);
}
if (logger.isTraceEnabled()) {
logger.trace("Loaded " + count + " bean definitions from location pattern [" + location + "]");
}
return count;
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"Could not resolve bean definition resource pattern [" + location + "]", ex);
}
}
else {
// Can only load single resources by absolute URL.
Resource resource = resourceLoader.getResource(location);
int count = loadBeanDefinitions(resource);
if (actualResources != null) {
actualResources.add(resource);
}
if (logger.isTraceEnabled()) {
logger.trace("Loaded " + count + " bean definitions from location [" + location + "]");
}
return count;
}
}
这一段没什么特殊的,我们点击进入 loadBeanDefinitions(resources);
方法:
@Override
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
Assert.notNull(resources, "Resource array must not be null");
int count = 0;
for (Resource resource : resources) {
count += loadBeanDefinitions(resource);
}
return count;
}
似曾相识的一个方法,只不过循环的东西不一样,刚刚的是xml
,这次循环加载的是Resource
;我们点击进入loadBeanDefinitions(resource)
方法中:
XmlBeanDefinitionReader.java
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
return loadBeanDefinitions(new EncodedResource(resource));
}
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, "EncodedResource must not be null");
if (logger.isTraceEnabled()) {
logger.trace("Loading XML bean definitions from " + encodedResource);
}
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet<>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
try {
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
inputStream.close();
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
}
finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
}
这一段进行了一些校验,并把xml文件流封装为InputSource对象;然后进入doLoadBeanDefinitions(inputSource, encodedResource.getResource());
方法中,该方法执行了具体的加载逻辑;
XmlBeanDefinitionReader.java
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
//读取XML信息,并将Xml信息保存到Document 对象中
Document doc = doLoadDocument(inputSource, resource);
//解析Document,封装BeanDefinitions并进行注册
int count = registerBeanDefinitions(doc, resource);
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + count + " bean definitions from " + resource);
}
return count;
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (SAXParseException ex) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(),
"Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
}
catch (SAXException ex) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(),
"XML document from " + resource + " is invalid", ex);
}
catch (ParserConfigurationException ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"Parser configuration exception parsing XML from " + resource, ex);
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"IOException parsing XML document from " + resource, ex);
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"Unexpected exception parsing XML document from " + resource, ex);
}
}
到这一步,解析XML
基本完成。这一段代码主要进行了BeanDefinitions
的封装及注册,具体逻辑在registerBeanDefinitions(doc, resource)
方法当中,我们看一下这个方法的实现:
XmlBeanDefinitionReader.java
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
// 定义BeanDefinitionDocumentReader 对象,用于处理传入的Document对象
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
// 获取已有的BeanDefinition对象数量
int countBefore = getRegistry().getBeanDefinitionCount();
// 注册BeanDefinition
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
// 返回新注册的BeanDefinition数量
return getRegistry().getBeanDefinitionCount() - countBefore;
}
getRegistry().getBeanDefinitionCount();
这个方法实际上就是从一个Map
中获取已经注册了多少个BeanDefinition
对象;新注册的BeanDefinition
也会放在这个集合中
我们主要关注如何注册的,所以点击进入documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
方法,看一下他的实现:
DefaultBeanDefinitionDocumentReader.java
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
doRegisterBeanDefinitions(doc.getDocumentElement());
}
protected void doRegisterBeanDefinitions(Element root) {
// 定义一个有状态的委托类,用来解析Xml中bean的定义
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(getReaderContext(), root, parent);
if (this.delegate.isDefaultNamespace(root)) {
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
// We cannot use Profiles.of(...) since profile expressions are not supported
// in XML config. See SPR-12458 for details.
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if (logger.isDebugEnabled()) {
logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec +
"] not matching: " + getReaderContext().getResource());
}
return;
}
}
}
//解析前的处理,DefaultBeanDefinitionDocumentReader没有实现它,子类可以实现,来扩展功能
preProcessXml(root);
// 解析root内的XML标签,如<import> <alias> <bean>等
parseBeanDefinitions(root, this.delegate);
// 解析后的处理,同样没有实现它,子类可以实现。
postProcessXml(root);
this.delegate = parent;
}
然后我们再来看下具体的解析方法:parseBeanDefinitions(root, this.delegate)
方法
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);
}
}
这一段代码循环去处理解析对应的标签(默认标签和自定义标签),我们看下默认标签是如何解析的:
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
// import 元素处理
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
// alias元素处理
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
// bean元素处理
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
// 嵌套beans处理
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
主要看下bean
元素处理:
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// 解析bean元素为BeanDefinition,但是此时使用BeanDefinitionHolder,实际上BeanDefinitionHolder就已经持有了一个BeanDefinition
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
// 处理自定义标签
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// 完成BeanDefinition注册
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));
}
}
继续点击BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// 获取beanName
String beanName = definitionHolder.getBeanName();
// 注册
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// 获取别名
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
// 存储别名
registry.registerAlias(beanName, alias);
}
}
}
继续向下,进入registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
方法:
DefaultListableBeanFactory.java
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
else if (existingDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (logger.isInfoEnabled()) {
logger.info("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
existingDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(existingDefinition)) {
if (logger.isDebugEnabled()) {
logger.debug("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
// 是否已经开始创建实例化
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
removeManualSingletonName(beanName);
}
}
else {
// 放入beanDefinitionMap 也就是注册
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
到此为止,就完成了xml的解析->BeanDefinition->注册的一个全流程