概述
IOC,全称"Inverse Of Control",中文意思为:控制反转。那么,这是啥意思?控制什么权限?反转给谁?第一个问题,创建对象的权限;第二个问题,反转给IOC容器。简单来讲,就是将创建对象的权限交给IOC容器,并且,在IOC中的这些对象,有一个统一的名称,叫做Bean。然后,还有个DI,全程"Dependence Injection",中文意思为依赖注入。那依赖注入又是什么?当一个Bean实例引用到了另外一个Bean实例的时候,IOC容器帮助我们创建依赖Bean实例并注入到需要依赖Bean的那个Bean中。两者结合,IOC容器就可以为我们创建各种各样的Bean了,简单来讲,我们平时所说的IOC,就是指具备了IOC和DI功能的IOC容器,有了这个IOC容器,就可以帮我们创建管理各种对象,然后我们只要拿过来用就可以了。
那怎么用呢?我觉得造框架就像造飞机,飞机造好之后,并不是马上拉个人过来就能飞,还得培训一段时间,之后,这个人叫飞行员;框架造好之后,也不是随便塞给一个人就能用,还得培训一段时间,之后,这个人叫程序员。每一种类型的飞机操作起来可能不太一样,飞行员需要了解和学习;每一个框架都有自己的一套规则,程序员使用之前也需要相应的学习。不同的地方大概就是能造框架的程序员还算比较多,能造飞机的飞行员?Spring是一架飞机吗?我觉得把它称为一个机群更合适啊。这个机群由很多战斗机组成,但是有几架是核心的,离开它们这个机群就废了,比如spring-core、spring-bean,IOC容器就在这个核心模块里面。唧唧歪歪这么多,就是想告诉你,看这个之前先学一下IOC怎么用,至于具体怎么用,我不会,自己学啊。
前面已经说了IOC是干嘛的,那么它是怎么实现的?它为我们创建Bean的具体流程是什么?抛开框架来讲,如果我们要实现这么一个功能,会怎么做?大概就是先读取配置文件,然后解析配置文件,然后根据解析结果创建对象吧?其实也就是这样的,不过Spring这个框架除了它本省提供的功能之外,更可贵的是它的设计,而设计这种东西,并不是你dbug一下就能理解的,也许要你要阅读源码很多遍才能体会,也许有一天你突然就明白了。反正我现在的主要目的也是弄清楚它的工作流程,至于设计这种东西,这个不能强求,慢慢体会吧。
如果对Bean生命周期稍有了解的同学都会知道,Bean实例化的时机其实是和你所使用的工厂类有关系的。如果你使用的是DefaultListableBeanFactory,那么它的实例化时机是在第一次使用该Bean的时候。第一次使用它的时候事什么意思?比如这样:factory.getBean("simpleMethodInterceptor"),就是第一次要用到它的时候就会实例化;如果你使用的是ApplicationContext,有关于Bean实例化的时机是要分情况的:
- 如果bean的scope是singleton的,并且lazy-init为false(默认是false,所以可以不用设置),则ApplicationContext启动的时候就实例化该Bean,并且将实例化的Bean放在一个map结构的缓存中,下次再使用该Bean的时候,直接从这个缓存中取
- 如果bean的scope是singleton的,并且lazy-init为true,则是在第一次使用该Bean的时候进行实例化
- 如果bean的scope是prototype的,则是在第一次使用该Bean的时候进行实例化
可以看出,使用ApplicationContext的情况内部流程会复杂一些,但是对我们使用者而言,肯定是使用ApplicationContext更方便。接下来两种情况我都会介绍,其实很多东西都是一样,比如bean解析这一块,肯定是一样的,但我们的目的是研究其内部流程,所以先从简单的开始,简单的理解之后,复杂的理解起来也更容易了。
这里再强调一下,本文的主要目的是分析其内部流程,如果想完完全全的弄懂其源码,还是挺困难的:一方面,你需要对Spring中的各种各样的配置非常熟悉,这样才能很快猜测出代码是什么意思;另一方面,你需要有足够多的时间和耐心去研究。源码值得读,但也不至于这样每行都揪着不放,而且代码这种东西,看第一遍和看第二遍感觉是完全不一样的。刚看一个框架的源码的时候,不要一下子就想着把它每行代码都弄得清清楚楚,了解整个框架的脉络比这更有意义,对感兴趣的地方,再去细读。
Bean生命周期
为什么这里会先介绍Bean的生命周期?因为Bean生命周期是IOC中非常核心的内容,这里也体现了Spring这个框架的设计能力,它为我们预留了很多的接口,让我们在bean实例化前后、初始化前后可以写入一些自己的逻辑,有些情况下,这是非常重要的。
那么什么是bean的生命周期呢?即在我们将xml配置文件中的一个个<bean>标签解析成一个个BeanDefinition之后,我们需要根据BeanDefinition进行bean的实例化(BeanDefinition也是一个非常重要的概念,它是用来做什么的?可以这样理解:xml配置文件中的一个个标签,我们可以认为它是一种描述信息,即它描述了一个bean应该是什么样子,这个注解的效果基本是类似,然后在Spring对xml配置文件进行解析的时候,会将里面的一个个标签解析成一个个BeanDefinition对象,然后在Spring创建bean实例的时候,就直接根据BeanDefinition就可以很方便的创建bean实例的,可以认为BeanDefinition是对xml标签的一种抽象),bean的实例化的简单来讲就是new对象,但是在new对象的前后、初始化对象的前后,Spring为我们预留了非常多的接口,让我们而可以插入自己的逻辑,而整个流程下来,就可以称为bean的生命周期。
1.根据BeanDefinition信息,实例化对象
2.根据BeanDefinition信息,配置Bean的所有属性
3.如果Bean实现了BeanNameAware接口,工厂调用Bean的setBeanName,参数为Bean的id
4.如果Bean实现BeanFactoryAware或者ApplicationContextAware接口,设置工厂setBeanFactory 或者上下文对象 setApplicationContext
5.如果存在类实现了BeanPostProcessor接口,执行这些实现类的postProcessBeforeInitialization方法,这相当于在Bean初始化之前插入逻辑
6.如果Bean实现InitializingBean接口, 执行afterPropertiesSet方法
7.如果Bean指定了init-method方法,就会调用该方法。例:<bean init-method="init">
8.如果存在类实现了BeanPostProcessor接口,执行这些实现类的postProcessAfterInitialization方法,这相当于在Bean初始化之后插入逻辑
9.这个阶段Bean已经可以使用了,scope为singleton的Bean会被缓存在IOC容器中
10.如果Bean实现了DisposableBean接口, 执行destroy方法。
11.如果配置了destory-method方法,就调用该方法。例:<bean destroy-method="customerDestroy">
这里将Bean生命周期这块内容放到最前面,是为了提前让大家对这块内容有个印象。
BeanFactory流程
前面我们说到,主要流程包括 状态配置文件、解析配置文件、创建Bean,那我们现在就按照这个流程来分析吧。在网上看了一些IOC源码解析的文档,大部会从这行代码开始
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
这就是我们上面说到的使用ApplicationContext方式,这是我们第二大章节要介绍的。ApplicationContext在Spring中是一个非常高级的接口了,它继承了很多接口,有非常多的方法,所以我们在使用的是时候,这么一行代码就帮我们创建好了IOC容器。使用的时候肯定很舒服了,但是一上来就用来做源码分析,不太好,里面的功能太多了,看着就怕。
我们就按前面说到的那三个流程来解析,因为Spring中本来也就是这样做的呀,ApplicationContext只不过是为了方便我们使用而封装出的一个更高级的接口。我们先把这三个流程弄清楚,之后再来分析ApplicationContext,这样就很舒服了。
有关于本大章节的测试代码如下:
public class TestBeanFactory {
public static void main(String[] args) {
// 资源加载器
ResourceLoader resLoaderr = new DefaultResourceLoader();
// 获取资源
Resource resource = resLoaderr.getResource("config.xml");
// 工程实现类
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
// XML解析器,将解析后的BeanDefinition 放到 factory 的Map中缓存起来
BeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(factory);
// 解析XML入口
beanDefinitionReader.loadBeanDefinitions(resource);
// 获取Bean实例。实际上,Bean在上面的流程中并没有实例话,只有在首次使用它的时候才会实例化
Object o = factory.getBean("simpleMethodInterceptor");
System.out.println(o);
}
}
加载配置文件
加载配置文件大家首先会想到什么?应该是IO流吧。Spring肯定会做封装,先不要关心这些,以下代码就会为我们加载配置文件到Resource中
// 资源加载器
ResourceLoader resLoaderr = new DefaultResourceLoader();
// 获取资源
Resource resource = resLoaderr.getResource("config.xml");
有关于这两行代码,没有什么特别的东西,可以看一下getResource方法
private final Set<ProtocolResolver> protocolResolvers = new LinkedHashSet<ProtocolResolver>(4);
public Resource getResource(String location) {
Assert.notNull(location, "Location must not be null");
for (ProtocolResolver protocolResolver : this.protocolResolvers) {
Resource resource = protocolResolver.resolve(location, this);
if (resource != null) {
return resource;
}
}
// 判断是不是 "/" 开头, 例如 /aa/bb/bean.xml
if (location.startsWith("/")) {
return getResourceByPath(location);
}
// 判断是不是 "classpath:" 开头, 例如 classpath:aplication.xml
else if (location.startsWith(CLASSPATH_URL_PREFIX)) {
return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());
}
else {
try {
// 尝试通过URL的方式解析这个路径,在我们这个例子会抛出异常
URL url = new URL(location);
return new UrlResource(url);
}
catch (MalformedURLException ex) {
// 在我们这个Demo中,实际会走这里
// No URL -> resolve as resource path.
return getResourceByPath(location);
}
}
}
ProtocolResolver是一个资源解析器接口,我们可以通过实现ProtocolResolver接口来自定义资源解析
public interface ProtocolResolver {
/**
* Resolve the given location against the given resource loader
* if this implementation's protocol matches.
*/
Resource resolve(String location, ResourceLoader resourceLoader);
}
看一下 getResourceByPath 方法
protected Resource getResourceByPath(String path) {
return new ClassPathContextResource(path, getClassLoader());
}
protected static class ClassPathContextResource extends ClassPathResource implements ContextResource {
public ClassPathContextResource(String path, ClassLoader classLoader) {
super(path, classLoader);
}
}
// ClassPathResource 构造方法
public ClassPathResource(String path, ClassLoader classLoader) {
Assert.notNull(path, "Path must not be null");
// 将 window下的 路径符 "\\" 换成 "/"
String pathToUse = StringUtils.cleanPath(path);
if (pathToUse.startsWith("/")) {
pathToUse = pathToUse.substring(1);
}
this.path = pathToUse;
this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader());
}
解析配置文件
有关于这一阶段的时序图
post_002DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
// BeanDefinitionReader 就是XML解析器
BeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(factory);
beanDefinitionReader.loadBeanDefinitions(resource);
解析配置我们这里使用了XmlBeanDefinitionReader,有关于XmlBeanDefinitionReader,创建它的时候需要指定一个BeanDefinitionRegistry对象。但是这里为什么传一个DefaultListableBeanFactory对象进去,可以看看他们的继承关系图。
post_003DefaultListableBeanFactory实现了非常多的接口,其中就包括BeanFactory和 XmlBeanDefinitionReader。
解析配置文件的入口,就在loadBeanDefinitions方法中,接收刚刚创建的Resource对象
private final ThreadLocal<Set<EncodedResource>> resourcesCurrentlyBeingLoaded =
new NamedThreadLocal<Set<EncodedResource>>("XML bean definition resources currently being loaded");
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
// 转换成 EncodedResource
return loadBeanDefinitions(new EncodedResource(resource));
}
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, "EncodedResource must not be null");
if (logger.isInfoEnabled()) {
logger.info("Loading XML bean definitions from " + encodedResource.getResource());
}
// 相当于是个缓存
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet<EncodedResource>(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();
}
}
}
EncodedResource是用来设置编码的,即设置以什么样的编码格式读取文件,这里默认为null
public EncodedResource(Resource resource) {
this(resource, null, null);
}
private EncodedResource(Resource resource, String encoding, Charset charset) {
super();
Assert.notNull(resource, "Resource must not be null");
this.resource = resource;
this.encoding = encoding;
this.charset = charset;
}
从上面的代码中我们可以发现,真正的解析逻辑在doLoadBeanDefinitions方法中。你多阅读一些代码就会发现,在Spring中,干实事的方法都是以 do 开始的。接下来分析一下doLoadBeanDefinitions方法
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
// 获取xml dom树
Document doc = doLoadDocument(inputSource, resource);
// 根据dom树 注册 BeanDefinition
return registerBeanDefinitions(doc, resource);
}
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文件 dom 树,就是将xml 文件解析成一个Document对象
public Document loadDocument(InputSource inputSource, EntityResolver entityResolver,
ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {
DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);
if (logger.isDebugEnabled()) {
logger.debug("Using JAXP provider [" + factory.getClass().getName() + "]");
}
DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);
return builder.parse(inputSource);
}
这个解析dom没什么好说的,主要看看registerBeanDefinitions方法
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
// 用于从 xml document 对象中 获取 BeanDefinition
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
int countBefore = getRegistry().getBeanDefinitionCount();
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
这里引出了一个新对象BeanDefinitionDocumentReader,它的主要功能就是从 document 对象中获取bean,简单来说,就是找到document dom树中的bean对象。那个方法还是有点不一样的
BeanUtils.instantiateClass方法通过无参构造函数创建一个对象,Class.cast 方法用于将一个对象装换为类或者接口,法只能转换当前类型或其子类下的对象,只是简单进行强转。但我不知道这里为啥要这样写啊!
protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {
return BeanDefinitionDocumentReader.class.cast(BeanUtils.instantiateClass(this.documentReaderClass));
}
getRegistry()方法就是返回我们一开始传进去的DefaultListableBeanFactory。这行代码就是返回DefaultListableBeanFactory中beanDefinitionMap中的元素个数,beanDefinitionMap是啥?它缓存当前容器内的BeanDefinition,BeanDefinition是Bean的描述,Spring会先将 xml document 中的节点解析成一个个BeanDefinition,然后在后续阶段将BeanDefinition生成 真正的Bean。也就是说,这里是返回“此刻当前容器中的BeanDefinition个数”。
int countBefore = getRegistry().getBeanDefinitionCount();
这条return语句,代表返回本次创建的 BeanDefinition 个数
return getRegistry().getBeanDefinitionCount() - countBefore;
所以,主要的逻辑代码,在registerBeanDefinitions方法中
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
createReaderContext返回一个XmlReaderContext对象,这个对象里面主要是包括一些参数吧。
public XmlReaderContext createReaderContext(Resource resource) {
return new XmlReaderContext(resource, this.problemReporter, this.eventListener,
this.sourceExtractor, this, getNamespaceHandlerResolver());
}
有关于xml命名空间处理解析器
public NamespaceHandlerResolver getNamespaceHandlerResolver() {
if (this.namespaceHandlerResolver == null) {
this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver();
}
return this.namespaceHandlerResolver;
}
protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() {
return new DefaultNamespaceHandlerResolver(getResourceLoader().getClassLoader());
}
/**
* The location to look for the mapping files. Can be present in multiple JAR files.
*/
public static final String DEFAULT_HANDLER_MAPPINGS_LOCATION = "META-INF/spring.handlers";
public DefaultNamespaceHandlerResolver(ClassLoader classLoader) {
this(classLoader, DEFAULT_HANDLER_MAPPINGS_LOCATION);
}
大概知道有这么些东西就可以了。接下来看看 DefaultBeanDefinitionDocumentReader 中的 registerBeanDefinitions 方法具体实现
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
logger.debug("Loading bean definitions");
Element root = doc.getDocumentElement();
doRegisterBeanDefinitions(root);
}
看到了吗?又是一个do开头的方法,说明这里是干实事的地方
protected void doRegisterBeanDefinitions(Element root) {
// parent是为了处理 <beans> 中嵌套 <beans> 的情况
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(getReaderContext(), root, parent);
// 是否是默认 命名空间 "http://www.springframework.org/schema/beans"
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);
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if (logger.isInfoEnabled()) {
logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
"] not matching: " + getReaderContext().getResource());
}
return;
}
}
}
preProcessXml(root);
parseBeanDefinitions(root, this.delegate);
postProcessXml(root);
this.delegate = parent;
}
这里又引出一个新对象BeanDefinitionParserDelegate,这是一个委托类,所有解析DOM的逻辑都交给这个类来处理。
第一行代码就值得分析一下。Spring解析XML的时候,是以<beans></beans>为最外层标签进行解析的,但是<beans>可以嵌套 <beans>,这种情况下,外层<beans>对应的BeanDefinitionParserDelegate委托类就是里层<beans>中的parent,因为可以从parent中继承一些默认属性。下面举一个例子来说明:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd">
<bean id="BookInterceptor" class="aop.BookInterceptor" />
<beans>
<bean id="simpleMethodInterceptor2" class="aop.SimpleMethodInterceptor" ></bean>
</beans>
</beans>
解析最外层<beans>的时候,parent为null,这时候会创建一个BeanDefinitionParserDelegate委托类 delegate1,然后先解析 <bean id="BookInterceptor" ... /> ,解析完这个标签之后,又遇到一个<beans>,这时候又会调用doRegisterBeanDefinitions方法,将 delegate1 作为parent,同时创建一个 BeanDefinitionParserDelegate委托类 delegate2,这时候的一些默认属性会从delegate1中继承。
这里相当于有个递归调用,遇到<beans>标签就调用doRegisterBeanDefinitionsf方法,同时将外层的委托类赋值给本次调用中的parent,如果没有外层,parent就为nulll
BeanDefinitionParserDelegate parent = this.delegate;
protected BeanDefinitionParserDelegate createDelegate(
XmlReaderContext readerContext, Element root, BeanDefinitionParserDelegate parentDelegate) {
BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);
delegate.initDefaults(root, parentDelegate);
return delegate;
}
public void initDefaults(Element root, BeanDefinitionParserDelegate parent) {
// 设置一些默认属性
populateDefaults(this.defaults, (parent != null ? parent.defaults : null), root);
this.readerContext.fireDefaultsRegistered(this.defaults);
}
public static final String DEFAULT_LAZY_INIT_ATTRIBUTE = "default-lazy-init";
public static final String DEFAULT_MERGE_ATTRIBUTE = "default-merge";
public static final String DEFAULT_AUTOWIRE_ATTRIBUTE = "default-autowire";
public static final String DEFAULT_DEPENDENCY_CHECK_ATTRIBUTE = "default-dependency-check";
public static final String DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE = "default-autowire-candidates";
public static final String DEFAULT_INIT_METHOD_ATTRIBUTE = "default-init-method";
public static final String DEFAULT_DESTROY_METHOD_ATTRIBUTE = "default-destroy-method";
// 设置一些默认属性
protected void populateDefaults(DocumentDefaultsDefinition defaults, DocumentDefaultsDefinition parentDefaults, Element root) {
String lazyInit = root.getAttribute(DEFAULT_LAZY_INIT_ATTRIBUTE);
if (DEFAULT_VALUE.equals(lazyInit)) {
// Potentially inherited from outer <beans> sections, otherwise falling back to false.
lazyInit = (parentDefaults != null ? parentDefaults.getLazyInit() : FALSE_VALUE);
}
defaults.setLazyInit(lazyInit);
String merge = root.getAttribute(DEFAULT_MERGE_ATTRIBUTE);
if (DEFAULT_VALUE.equals(merge)) {
// Potentially inherited from outer <beans> sections, otherwise falling back to false.
merge = (parentDefaults != null ? parentDefaults.getMerge() : FALSE_VALUE);
}
defaults.setMerge(merge);
String autowire = root.getAttribute(DEFAULT_AUTOWIRE_ATTRIBUTE);
if (DEFAULT_VALUE.equals(autowire)) {
// Potentially inherited from outer <beans> sections, otherwise falling back to 'no'.
autowire = (parentDefaults != null ? parentDefaults.getAutowire() : AUTOWIRE_NO_VALUE);
}
defaults.setAutowire(autowire);
// Don't fall back to parentDefaults for dependency-check as it's no longer supported in
// <beans> as of 3.0. Therefore, no nested <beans> would ever need to fall back to it.
defaults.setDependencyCheck(root.getAttribute(DEFAULT_DEPENDENCY_CHECK_ATTRIBUTE));
if (root.hasAttribute(DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE)) {
defaults.setAutowireCandidates(root.getAttribute(DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE));
}
else if (parentDefaults != null) {
defaults.setAutowireCandidates(parentDefaults.getAutowireCandidates());
}
if (root.hasAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE)) {
defaults.setInitMethod(root.getAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE));
}
else if (parentDefaults != null) {
defaults.setInitMethod(parentDefaults.getInitMethod());
}
if (root.hasAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE)) {
defaults.setDestroyMethod(root.getAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE));
}
else if (parentDefaults != null) {
defaults.setDestroyMethod(parentDefaults.getDestroyMethod());
}
defaults.setSource(this.readerContext.extractSource(root));
}
preProcessXml 和 postProcessXml 这两个方法是空的,用户可以通过继承来添加自己的逻辑。主要是parseBeanDefinitions方法,这里面主要就是遍历DOM中的所有Element节点,即标签。如果是默认命名空间下的标签,就调用parseDefaultElement方法,如果不是默认命名空间下的标签,就调用委托类的parseCustomElement方法。其实这里主要即使委托类来实现那了,parseDefaultElement方法里面的主要逻辑也是调用了委托类的方法
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);
}
}
root 就相当于是的<beans>标签,经常会看到判断是否是命名空间,这里的命名空间指的是 "http://www.springframework.org/schema/beans",bean 和 beans 标签都属于默认命名空间。
有关于 org.w3c.dom.Document 下的 Node,Node是一个顶层接口,它下面有几个子接口。在DOM树中,所有东西都可以叫Node,标签也是一种Node,但它实际上上叫Element。举个例子说明:
<book price="100">
<chineseBook>哈利波特.哈哈哈<chineseBook>
</beans>
在以上的代码片段中,price 是属性节点;哈利波特.哈哈哈 是 文本节点;<book price="100">..</book> 和 <chineseBook>哈利波特.哈哈哈<chineseBook> 是Element节点。所以,不要被Node搞晕了
这里主要以/<bean> 标签进行说明,所以主要关注parseDefaultElement方法,可以看到,当是<beans/>标签的时候,又调用了doRegisterBeanDefinitions方法
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)) {
doRegisterBeanDefinitions(ele);
}
}
解析<bean> 标签的processBeanDefinition方法源码如下,这里主要就是委托类BeanDefinitionParserDelegate的主场了
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// 返回一个 BeanDefinition 持有者
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));
}
}
BeanDefinitionParserDelegate # parseBeanDefinitionElement
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
return parseBeanDefinitionElement(ele, null);
}
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
// 如果没有定义name属性,就以id属性的值作为beanName;如果定义了beanName,就以name属性的值作为beanName
String id = ele.getAttribute(ID_ATTRIBUTE);
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
List<String> aliases = new ArrayList<String>();
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()) {
beanName = aliases.remove(0);
if (logger.isDebugEnabled()) {
logger.debug("No XML 'id' specified - using '" + beanName +
"' as bean name and " + aliases + " as aliases");
}
}
// 校验 beanName的唯一性
if (containingBean == null) {
checkNameUniqueness(beanName, aliases, ele);
}
// 主要的解析逻辑就是在这个方法中,解析成功返回一个 AbstractBeanDefinition;解析失败返回 null
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
// 下面主要就是一些后置处理
if (beanDefinition != null) {
if (!StringUtils.hasText(beanName)) {
try {
if (containingBean != null) {
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
}
else {
beanName = this.readerContext.generateBeanName(beanDefinition);
// Register an alias for the plain bean class name, if still possible,
// if the generator returned the class name plus a suffix.
// This is expected for Spring 1.2/2.0 backwards compatibility.
String beanClassName = beanDefinition.getBeanClassName();
if (beanClassName != null &&
beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
aliases.add(beanClassName);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Neither XML 'id' nor 'name' specified - " +
"using generated bean name [" + beanName + "]");
}
}
catch (Exception ex) {
error(ex.getMessage(), ele);
return null;
}
}
String[] aliasesArray = StringUtils.toStringArray(aliases);
// 通过上面生成的 beanDefinition 构造一个 BeanDefinitionHolder
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
return null;
}
创建AbstractBeanDefinition的主要逻辑又是调用了parseBeanDefinitionElement的一个重载方法,其中有很大一部分逻辑是这是BeanDefinition属性,如果想弄的清清楚楚,还是需要花一点时间的,这里就跳过吧,只要明白:这里为BeanDefinition设置这么多属性,都是因为之后生成Bean实例的时候,需要BeanDefinition中维护的信息,BeanDefinition是生成Bean实例的根本,很重要!
public AbstractBeanDefinition parseBeanDefinitionElement(
Element ele, String beanName, BeanDefinition containingBean) {
this.parseState.push(new BeanEntry(beanName));
String className = null;
if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
}
try {
String parent = null;
if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
parent = ele.getAttribute(PARENT_ATTRIBUTE);
}
// 生成一个GenericBeanDefinition并返回,同时根据className创建一个对应的Class对象设置为GenericBeanDefinition的beanClass属性。
AbstractBeanDefinition bd = createBeanDefinition(className, parent);
// 下面这些就是有关于一些属性啥的解析,如果想弄的清清楚楚,还是需要花一点时间的,这里就跳过吧,只要明白:这里为BeanDefinition设置这么多属性,都是因为之后生成Bean实例的时候,需要BeanDefinition中维护的信息,BeanDefinition是生成Bean实例的根本,很重要!
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
parseMetaElements(ele, bd);
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
parseConstructorArgElements(ele, bd);
parsePropertyElements(ele, bd);
parseQualifierElements(ele, bd);
bd.setResource(this.readerContext.getResource());
bd.setSource(extractSource(ele));
return bd;
}
catch (ClassNotFoundException ex) {
error("Bean class [" + className + "] not found", ele, ex);
}
catch (NoClassDefFoundError err) {
error("Class that bean class [" + className + "] depends on not found", ele, err);
}
catch (Throwable ex) {
error("Unexpected failure during bean definition parsing", ele, ex);
}
finally {
this.parseState.pop();
}
return null;
}
生成之后就返回到DefaultBeanDefinitionDocumentReader 中的 processBeanDefinition 方法中,然后又调用BeanDefinitionParserDelegate的decorateBeanDefinitionIfRequiredf方法进行装饰BeanDefinitionHolder
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
......
}
decorateBeanDefinitionIfRequired主要实现如下,具体的不太了解
public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder definitionHolder) {
return decorateBeanDefinitionIfRequired(ele, definitionHolder, null);
}
public BeanDefinitionHolder decorateBeanDefinitionIfRequired(
Element ele, BeanDefinitionHolder definitionHolder, BeanDefinition containingBd) {
BeanDefinitionHolder finalDefinition = definitionHolder;
//装饰自定义属性
// Decorate based on custom attributes first.
NamedNodeMap attributes = ele.getAttributes();
for (int i = 0; i < attributes.getLength(); i++) {
Node node = attributes.item(i);
finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
}
//装饰自定义标签
// Decorate based on custom nested elements.
NodeList children = ele.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node node = children.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
}
}
return finalDefinition;
}
装饰完成之后,继续返回到 DefaultBeanDefinitionDocumentReader 的processBeanDefinition方法,然后注册最终的BeanDefinition。注意该方法的第二个参数,其实就是我们一开始传进去的DefaultListableBeanFactory对象,主要流程就是将当前生成的BeanDefinition放到DefaultListableBeanFactory的一个Map中缓存起来
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// 通过beanName注册 BeanDefinition
String beanName = definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// 如果该bean有别名,为该bean注册别名
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
可以具体看看DefaultListableBeanFactory对象中的registerBeanDefinition方法,大概就是将BeanDefinition放到beanDefinitionMap中缓存起来。
/** Map of bean definition objects, keyed by bean name */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);
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 {
// 简单校验,检验啥 overridden 方法,不太清楚,没用过
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
BeanDefinition oldBeanDefinition;
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
// 检查该BeanDefinition是否在容器中已经存在,如果已经存在,bing且不允许覆盖已经注册的BeanDefinitio,则报错
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
"': There is already [" + oldBeanDefinition + "] bound.");
}
else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (this.logger.isWarnEnabled()) {
this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
oldBeanDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(oldBeanDefinition)) {
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + oldBeanDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + oldBeanDefinition +
"] with [" + beanDefinition + "]");
}
}
// 如果允许覆盖,根据 beanName,用新的 BeanDefinition 覆盖老的 BeanDefinition
this.beanDefinitionMap.put(beanName, beanDefinition);
}
// 首次创建的 BeanDefinition
else {
// 检查此工厂的bean创建阶段是否已经开始?检查当前是不是已经开始实例化了?
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<String>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
else {
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (oldBeanDefinition != null || containsSingleton(beanName)) {
// 如果有覆盖的情况,就刷新缓存
resetBeanDefinition(beanName);
}
}
最后,在DefaultBeanDefinitionDocumentReader对象的processBeanDefinition 方法中发出响应事件,通知相关监听器这个 Bean 已经被加载
// 通过 fireComponentRegistered 方法进行通知监听器解析及注册完成工作,这里的实现只为扩展,当程序开发人员需要对注册BeanDefinition事件进行监听时,可以通过注册监听器的方式并将处理逻辑写入监听器中,目前 Spring 中并没有对此事件做任何处理。
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
至此,有关于解析XML文件的内容就算完事了,接着就是按照方法调用栈返回,最后返回一个该配置文件对应生成BeanDefinition个数。
生成Bean实例
有关于这一阶段的时序图,这个图画的不太好,凑合看一下吧,哭
post_004在第一次使用该Bean的时候进行实例化
// 获取Bean实例。实际上,Bean在上面的流程中并没有实例话,只有在首次使用它的时候才会实例化
Object o = factory.getBean("simpleMethodInterceptor");
System.out.println(o);
DefaultListableBeanFactory 类继承了 AbstractAutowireCapableBeanFactory 抽象类,getBean方法就是在该抽象类中进行实例化的。追踪该方法可以发现,又是一个do开头的方法,说明里面就是具体逻辑了。这个方法还挺长,接下来我们分步解析
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
// 去除前缀 &;如果名称是别名,则跟进别名返回 name
final String beanName = transformedBeanName(name);
Object bean;
// 据beanName从 Map缓存 中获取单例Bean实例
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
// 如果指定名称的Bean在容器中已有单态模式的Bean被创建,直接返回已经创建的Bean实例。当这个bean时FactoryBean的时候,需要特别处理
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
// 缓存中没有,就创建
else {
// 尝试解决循环依赖问题
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
//对IoC容器中是否存在指定名称的BeanDefinition进行检查,首先检查是否
58 //能在当前的BeanFactory中获取的所需要的Bean,如果不能则委托当前容器
59 //的父级容器去查找,如果还是找不到则沿着容器的继承体系向父级容器查找
// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
// 当前容器的父级容器存在,且当前容器中不存在指定名称的Bean
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
// 解析指定Bean名称的原始名称
String nameToLookup = originalBeanName(name);
if (args != null) {
// Delegation to parent with explicit args.
// 委派父级容器根据指定名称和显式的参数查找
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// No args -> delegate to standard getBean method.
// 委派父级容器根据指定名称和类型查找
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
//typeCheckOnly 默认是false,表示是否需要进行类型验证
if (!typeCheckOnly) {
// 这里用于标记该bean已经被创建,其实就是将beanName 放到一个专门用来标记 Bean 是否创建的map中
markBeanAsCreated(beanName);
}
try {
// 将GernericBeanDefinition 转换成 RootBeanDefinition,因为xml解析之后是GernericBeanDefinition,而后续处理是针对RootBeanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 获取当前Bean的依赖Bean,然后实例化依赖Bean,会递归调用
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dependsOnBean : dependsOn) {
if (isDependent(beanName, dependsOnBean)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
}
registerDependentBean(dependsOnBean, beanName);
getBean(dependsOnBean);
}
}
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
// 回调方法,创建Bean实例的逻辑就在这个方法中
@Override
public Object getObject() throws BeansException {
try {
//创建一个指定Bean实例对象,如果有父级继承,则合并子类和父类的定义
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
// 出错了就要从缓存中清除
destroySingleton(beanName);
throw ex;
}
}
});
// 获取给定Bean的实例对象,如果时FactoryBean需要特殊处理
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// scorp 为 原型模式,每次请求都会创建一个
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
//回调beforePrototypeCreation方法,默认的功能是注册当前创建的原型对象
beforePrototypeCreation(beanName);
//创建指定Bean对象实例
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
/回调afterPrototypeCreation方法,默认的功能告诉IoC容器指定Bean的原型对象不再创建了
afterPrototypeCreation(beanName);
}
//如果是FactoryBean,特殊处理
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
// scorp 为其它情况,例如 request session
else {
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// 对创建的Bean实例对象进行类型检查
// Check if required type matches the type of the actual bean instance.
if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
try {
return getTypeConverter().convertIfNecessary(bean, requiredType);
}
catch (TypeMismatchException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type [" +
ClassUtils.getQualifiedName(requiredType) + "]", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
以下主要是为了在必要时去除 & 前缀。我们知道,当我们通过factory.getBean(&+beanName) 方式获取一个Bean的时候,实际上获取的是beanFactory,而不是我们需要的那个bean
final String beanName = transformedBeanName(name);
尝试根据beanName从map缓存中获取bean
Object sharedInstance = getSingleton(beanName);
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
接下来就是一些判断,主要是处理当缓存中有bean的情况,创建新bean的时候,不走那些流程,所以直接到标记处。在开始创建bean实例之前,需要先标记一下,即将该beanName缓存到一个map中
markBeanAsCreated(beanName);
然后就是创建依赖bean
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dependsOnBean : dependsOn) {
if (isDependent(beanName, dependsOnBean)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
}
registerDependentBean(dependsOnBean, beanName);
getBean(dependsOnBean);
}
}
如果Bean是单例模式,就先从 this.singletonObjects 缓存中获取,缓存中有则直接返回,否则创建。在下面的这堆代码中,最核心的就是 singletonFactory.getObject() 这个方法了,创建Bean实例的逻辑在在这个方法中调用的,然后还有Bean的生命周期,需要重点关注一下
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "'beanName' must not be null");
synchronized (this.singletonObjects) {
// 先从缓存中获取
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while the singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
// 将当前Bean设置为正在加载状态并放到缓存中,可以对循环依赖进行检查。inCreationCheckExclusions 里面应该是缓存了一些再创建Bean时需要排除的Bean?
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<Exception>();
}
try {
// 回调方法,真正的实例化Bean逻辑。
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// Has the singleton object implicitly appeared in the meantime ->
// if yes, proceed with it since the exception indicates that state.
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
// Bean创建完成之后,将它的正在创建状态从缓存中移除
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 添加到缓存中
addSingleton(beanName, singletonObject);
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
创建Bean实例的操作就在getObject方法里面,可以看出这是一个回调方法,在这个方法内部,调用了 AbstractAutowireCapableBeanFactory 类的 createBean方法,在这方方法总,主要需要关注两个方法 resolveBeforeInstantiation 和 doCreateBean,前者是试图根据初始化前后处理器返回一个代理实例,后者即真正的创建实例逻辑
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
// 锁定class,根据设置的class属性或者根据className来解析class
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
// 方法覆盖?具体不太清楚
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// 如果Bean配置了初始化前和初始化后的处理器,则试图返回一个需要创建Bean的代理对象,如果成功就直接返回了,下面的流程就不执行了。
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
// 创建Bean实例
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
有关于resolveBeforeInstantiation这个方法,重点解释一下。方法体看起来很简单,如果Bean配置了初始化前和初始化后的处理器,则试图返回一个需要创建Bean的代理对象,如果成功就直接返回了,下面的流程就不执行了。我想了很久才明白到它这里说的代理是什么意思,这里确实要结合AOP这一块的内容。简单从方法体上来看,一个就是在实例化前调用InstantiationAwareBeanPostProcessor是实现类的postProcessBeforeInstantiation方法;在实例化后,调用BeanPostProcessor实现类的postProcessAfterInitialization方法,就相当于是给我们预留的两个修改Bean信息的入口,这是没有什么疑问的。但这里为什么要扯到什么代理呢?这是因为如果我们用了AOP的时候,是需要为一些Bean生成代理类类,resolveBeforeInstantiation方法中就想到了这种情况。因为如果需要为某个Bean生成代理对象的话,在调用BeanPostProcessor是实现类的postProcessAfterInitialization方法之后,代理类就已经生成了,而我们需要的就是代理对象,就没必要再执行下面的实例化、初始化的流程了。
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
// 实例化前
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName)
throws BeansException {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}
// 实例化后 但是这个方法调用不是应该再初始化后吗,为什么在这里调用。可是如果不在这里调用,那就没办法为生成的代理对象处理了,不太懂
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
接下来就是创建Bean实例的doCreateBean方法,里面又有很多的逻辑,分很多步骤,每个步骤都很繁琐。
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
// 实例化之前,将BeanDefinition转换为Wrapper
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 根据指定Bean使用对应的策略创建新的实例,如:构造函数、工厂方法、简单初始化
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
// 允许 MergedBeanDefinitionPostProcessors 实现类修改 Bean 的定义信息,Bean合并后的处理
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
mbd.postProcessed = true;
}
}
// 涉及到循环依赖,看不太懂
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
// 针对 SmartInstantiationAwareBeanPostProcessor 实现类,不太清楚想要干嘛
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
// 准备初始化Bean了
// Initialize the bean instance.
Object exposedObject = bean;
try {
// 将各个属性值注入Bean中,可能存在依赖于其它Bean的属性,会递归调用
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
// 调用初始化方法,比如 init-method
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
// earlySingletonReference只有在检测到有循环依赖的情况下才会不为空
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
// actualDependentBeans 不为空表示当前的Bean创建后其依赖的Bean却没有创建完成,也就是说存在循环依赖
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
try {
// 注册 Bean销毁方法
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
在Spring中解决循环依赖对单例有效,而对于prototype的bean,Spring没有好的解决办法,唯一要做的就是抛出异常。假如A含有B的属性,B又含有A的属性,这就形成了一个循环依赖,此时如果A和B都是单例,那么在Spring中的处理方式就是在创建B的时候,涉及自动注入A的步骤时,并不是直接去再次创建A,而是通过放入缓存的ObjectFactory来创建实例,这样就解决了循环依赖的问题。
接下来看看createBeanInstance方法,这个方法里面很复杂,我就省略了一些代码,看看最关键实例化那个步骤的处理。首先判断BeanDefinition.getMethodOverrides()为空也就是用户没有使用replace或者lookup的配置方法,那么直接使用反射的技术;如果有配置这两个方法,就是用CGLIB进行动态代理,因为可以在创建代理的同时将动态方法织入代理类中。
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
......
return instantiateBean(beanName, mbd);
......
}
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
try {
Object beanInstance;
final BeanFactory parent = this;
if (System.getSecurityManager() != null) {
beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
return getInstantiationStrategy().instantiate(mbd, beanName, parent);
}
}, getAccessControlContext());
}
else {
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
}
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
}
}
@Override
public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {
// Don't override the class with CGLIB if no overrides.
if (bd.getMethodOverrides().isEmpty()) {
Constructor<?> constructorToUse;
synchronized (bd.constructorArgumentLock) {
constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
if (constructorToUse == null) {
final Class<?> clazz = bd.getBeanClass();
if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
}
try {
if (System.getSecurityManager() != null) {
constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor<?>>() {
@Override
public Constructor<?> run() throws Exception {
return clazz.getDeclaredConstructor((Class[]) null);
}
});
}
else {
constructorToUse = clazz.getDeclaredConstructor((Class[]) null);
}
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Throwable ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// Must generate CGLIB subclass.
return instantiateWithMethodInjection(bd, beanName, owner);
}
}
有关于属性填充这一块内容就略过了,直接看初始化方法initializeBean吧
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
// 对特殊Bean处理:Aware、BeanClassLoaderAware、BeanFactoryAware
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 初始化之前调用
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// 初始化之后调用
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
// 初始化之前,会调用所有BeanPostProcessor所有实现类的postProcessBeforeInitialization方法
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
// 初始化之后,会调用所有BeanPostProcessor所有实现类的postProcessAfterInitialization方法
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
Spring中提供了一些Aware相关接口,比如BeanFacrotyAware、ApplicationContextAware、ResourceLoaderAware、ServletContextAware等,实现这些Aware接口的Bean在被初始化前可以获得一些资源,例如实现BeanFacrotyAware的Bean在初始化后,Spring容器会注入BeanFactory的实例。
然后就是激活自定义init方法invokeInitMethods。客户定制的初始化方法除了我们熟知的init-method方法之外,还可以让Bean实现InitializingBean接口,并在afterPropertiesSet方法中实现自定义初始化逻辑
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
throws Throwable {
// 先检查是否实现了InitializingBean接口,实现了就调用afterPropertiesSet方法
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws Exception {
((InitializingBean) bean).afterPropertiesSet();
return null;
}
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
if (mbd != null) {
String initMethodName = mbd.getInitMethodName();
if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
// 调用自定义初始化方法 就是 method.invoke(bean)
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
registerDisposableBeanIfNecessary用于 注册 Bean销毁方法。除了可以配置属性destory-method外,还可以通过实现DestructionAwareBeanpostprocessor接口来统一处理Bean的销毁方法
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
if (mbd.isSingleton()) {
// 单例模式下注册需要销毁的Bean,此方法中会处理实现DisposableBean接口的Bean,b并且对所有Bean使用 DestructionAwareBeanpostprocessor 是实现类 处理
registerDisposableBean(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
else {
// A bean with a custom scope...
Scope scope = this.scopes.get(mbd.getScope());
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
}
scope.registerDestructionCallback(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
}
}
到这里,一个Bean身上该发生的基本上都介绍了,也包括Bean的生命周期,现在返回的Bean,就是我们能够正常使用的Bean了。
ApplicationContext流程
前面有说到过,ApplicationContext是一个非常高级的接口,实现了非常多的接口,可以看看它的继承关系图,很庞大
post_005这一大章节我们主要以ClassPathXmlApplicationContext为切入点,测试代码如下:
public class TestApplicationContext {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("config.xml");
Object o = applicationContext.getBean("simpleMethodInterceptor");
System.out.println(o);
}
}
入口
ClassPathXmlApplicationContext构造函数非常简单,为application contex设置好文件路径后,直接就调用了refresh方法,该方法中几乎包含了ApplicationContext中的所有功能
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
// 容器初始化入口
refresh();
}
}
// 为application contex 设置配置文件路径
public void setConfigLocations(String... locations) {
if (locations != null) {
Assert.noNullElements(locations, "Config locations must not be null");
this.configLocations = new String[locations.length];
for (int i = 0; i < locations.length; i++) {
this.configLocations[i] = resolvePath(locations[i]).trim();
}
}
else {
this.configLocations = null;
}
}
// 以下是抽象类的 AbstractApplicationContext 的方法
public AbstractApplicationContext(ApplicationContext parent) {
this();
setParent(parent);
}
public AbstractApplicationContext() {
this.resourcePatternResolver = getResourcePatternResolver();
}
// 创建一个资源解析器?
protected ResourcePatternResolver getResourcePatternResolver() {
return new PathMatchingResourcePatternResolver(this);
}
public void setParent(ApplicationContext parent) {
this.parent = parent;
if (parent != null) {
Environment parentEnvironment = parent.getEnvironment();
if (parentEnvironment instanceof ConfigurableEnvironment) {
getEnvironment().merge((ConfigurableEnvironment) parentEnvironment);
}
}
}
refresh的默认实现在AbstractApplicationContext抽象类中,它是一个模板方法,refresh方法的作用是:在创建IoC容器前,如果已经有容器存在,则需要把已有的容器销毁和关闭,以保证在refresh之后使用的是新建立起来的IoC容器。refresh的作用类似于对IoC容器的重启,在新建立好的容器中对容器进行初始化,对Bean定义资源进行载入
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识
prepareRefresh();
// 初始化beanFactory,并读取解析XML配置文件
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 对BeanFactory各种填充,例如类加载器、事件处理器等
prepareBeanFactory(beanFactory);
try {
// 子类覆盖方法做额外的处理
postProcessBeanFactory(beanFactory);
// 激活各种BeanFactory处理器
invokeBeanFactoryPostProcessors(beanFactory);
// 注册 拦截Bean创建的Beanc处理器,这里只是注册,起作用是在调用getBean方法的时候
registerBeanPostProcessors(beanFactory);
// 为上下文初始化Message源,即国际化处理
initMessageSource();
// 初始化消息广播器,并插入 'applicationEventMulticaster" 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);
}
// 销毁以创建的单态Bean
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// 取消refresh操作,重置容器的同步标识
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// 重置Spring 的常见核心缓存
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
obtainFreshBeanFactory
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 初始化BeanFactory,并进行xml文件读取解析,并将得到的BeanFactory记录在当前实体的属性中
refreshBeanFactory();
// 返回当前实体的 BeanFactory 属性
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
// AbstractRefreshableApplicationContext # refreshBeanFactory
protected final void refreshBeanFactory() throws BeansException {
// 如果beanFactory 存在,就先销毁,然后再重新创建
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
// 创建 DefaultListableBeanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
// 为序列号指定id
beanFactory.setSerializationId(getId());
//定制BeanFactory,设置相关属性,包括是否允许覆盖同名称的不同定义的对象以及循环依赖,以及设置@Autowired 、 @Qualifier 注解解析器 QualifierAnnotationAutowireCandidateResolver
customizeBeanFactory(beanFactory);
// 初始化DocumentReader,并进行XML文件读取解析
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
AbstractXmlApplicationContext # loadBeanDefinitions
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// 老面孔
// 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);
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);
}
}
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
Assert.notNull(resources, "Resource array must not be null");
int counter = 0;
for (Resource resource : resources) {
counter += loadBeanDefinitions(resource);
}
return counter;
}
// 到这里就完全和我们上面介绍的 Bean解析一模一样了
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
return loadBeanDefinitions(new EncodedResource(resource));
}
先消化一下,以后再写吧,待续。。。
有很多很多内容都是直接跳过的,可以看到Spring对Bean处理这一块真的是太复杂了,不过主要的流程也基本上清楚了,也许看第二遍的似乎就会舒服很多了。
网友评论