Spring Ioc源码解析:从何处切入Ioc源码核心?
- 内容介绍
- 文章标签
- 相关推荐
本文共计2232个文字,预计阅读时间需要9分钟。
《Spring IoC源码解析系列--IoC源码入口分析+本系列文章代码基于Spring Framework 5.2.x+前言+上一篇文章Spring IoC源码解析系列--IoC的基础知识介绍了IoC的基本概念以及Spring IoC体系的组成部分》
Spring Ioc源码分析系列--Ioc源码入口分析前言本系列文章代码基于Spring Framework 5.2.x
上一篇文章Spring Ioc源码分析系列--Ioc的基础知识准备介绍了Ioc的基础概念以及Spring Ioc体系的部分基础知识。那么这一篇就会真正通过一个例子,启动Ioc容器,获取容器里的bean。
首先说明,本文的例子是基于xml配置文件去完成的。
为什么是xml?因为xml是Spring的灵魂,可能我们初学Spring都会有畏难情绪,看到繁杂的xml就会打退堂鼓。但是实际上不然,xml的格式是相当清晰的,一个配置文件可以说没有一行配置是多余的。现在大部分的配置是用注解去完成的,相比xml而言是简洁许多,但是对于我们初学而言,xml其实是更好的方式,xml相对于注解而言是相对繁杂,但是它的信息也更多更明确,注解只是添加了一个注解就完成配置,细节上是更为隐蔽的。再加上xml配置文件和注解配置的原理是相通的,核心思想是一样的,掌握核心就万变不离其宗。所以这系列文章的例子大部分都会采取xml的方式去配置,当然后续可能也会补充一下注解方式的例子和分析文章。
万事开头难,如果实在觉得看不懂但又想学的,可以硬着头皮看下去,等以后回过头来再看的时候,会有豁然开朗的感觉。
源码分析 启动容器示例废话少说,下面开始搞个例子分析一下。所有源码都在我的仓库ioc-sourcecode-analysis-code-demo里找到。
首先弄个实体类User
/**
* @author Codegitz
* @date 2022/4/26 10:58
**/
public class User {
private String id;
private String name;
private String age;
}
创建业务类UserService以及业务实现类UserServiceImpl,这里的逻辑很简单,就是根据传入的name和age返回一个新的user对象。
/**
* @author Codegitz
* @date 2022/4/26 10:59
**/
public interface UserService {
User getUser(String name,String age);
}
public class UserServiceImpl implements UserService {
@Override
public User getUser(String name, String age) {
User user = new User();
user.setId("1");
user.setName(name);
user.setAge(age);
return user;
}
}
业务类的准备工作已经完成了,接下来就是要写个xml配置文件,告诉Spring Ioc我需要一个UserService的bean。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="www.springframework.org/schema/beans"
xmlns:xsi="www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="www.springframework.org/schema/beans www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userService" class="io.codegitz.service.impl.UserServiceImpl"/>
</beans>
这个xml配置文件比较简单,我们来解释一下每一行是什么意思。
<?xml version="1.0" encoding="UTF-8"?>为xml文件的规定头,没啥好说的。
xmlns="www.springframework.org/schema/beans"表明了xml的命名空间,xmlns全称为xml namespace,一个xml里面命名空间可以有多个。
xmlns:xsi和 xsi:schemaLocation是指明了xml文件的验证模型和验证模型文件的位置。可以看到验证模型能通过www.springframework.org/schema/beans"
this.delegate = createDelegate(getReaderContext(), root, parent);
if (this.delegate.isDefaultNamespace(root)) {
//获取这个profile的值,表示剖面,用于设置环境
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;
}
}
}
//解析XML之前做的准备工作,其实什么也没做
preProcessXml(root);
//调用这个方法解析
parseBeanDefinitions(root, this.delegate);
//后续处理
postProcessXml(root);
this.delegate = parent;
}
跟进解析BeanDefinition的方法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;
//Bean定义的document对象使用了spring的默认命名空间,如www.springframework.org/schema/beans
if (delegate.isDefaultNamespace(ele)) {
//若是则按照spring原有的逻辑进行解析
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);
}
//若果是别名元素,则进行别名解析
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
//bean元素解析
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
显然我们的例子只有一个Bean标签,所以会进入到processBeanDefinition()方法里。
/**
* Process the given bean element, parsing the bean definition
* and registering it with the registry.
*/
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
//BeanDefinitionHolder是对BeanDefinition的封装,即bean定义的封装类
//对document对象中的bean标签解析由BeanDefinitionParserDelegate实现
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
//从springIOC容器注册解析得到的BeanDefinition,这是BeanDefinition向IOC容器注册的入口
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()方法真正将BeanDefinition注册进容器里。咋注册呢?其实就是加到BeanFactory的beanDefinitionMap属性里。beanDefinitionMap可以说就是BeanDefinition的容器了。
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// Register bean definition under primary name.
String beanName = definitionHolder.getBeanName();
// 这里真正把BeanDefinition注册到了BeanFactory里
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);
}
}
}
到这里已经完成了BeanDefinition的注册,是不是有点曲折?其实很简单,就是细节比较多。
到这里obtainFreshBeanFactory()方法已经基本结束,已经完成了配置文件的解析并且注册BeanDefinition的过程了。剩下的操作就是把这个BeanFactory返回给上一步。
接下来分析一下prepareBeanFactory()方法,这方法也简单,主要就是对BeanFactory进行一些属性的设置,跟着注释看一下就行。
/**
* Configure the factory's standard context characteristics,
* such as the context's ClassLoader and post-processors.
* @param beanFactory the BeanFactory to configure
*/
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
// 设置 beanFactory的classLoader 为当前 context的classLoader
beanFactory.setBeanClassLoader(getClassLoader());
/**
* 设置 beanFactory的表达式语言处理器,Spring3 增加了表达式语言的支持,
* 默认可以使用#{bean.xxx}的形式来调用相关属性值
* @Qusetion 在注册了这个解析器之后,spring是在什么时候调用这个解析器的呢?
* Spring在bean进行初始化的时候会有属性填充的步骤,而在这一步中
* Spring会调用AbstractAutowireCapableBeanFactory类的applyPropertyValues函数来完成功能。
* 就这个函数中,会通过构造 BeanDefinitionValueResolver类型实例valueResolver来进行属性值的解析。
* 同时,也是在这个步骤中一般通过 AbstractBeanFactory 中的 evaluateBeanDefinitionString
* 方法去完成SpEL解析
*/
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
//为beanFactory增加一个PropertyEditor,这个主要是对bean的属性等设置管理的一个工具
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
//添加beanPostProcessor
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
//设置几个忽略自动装配的接口
// aware都是由invokeAware方法注入,忽略自动Autowire
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 interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
// 设置了几个自动装配的规则,后面三个都是把当前对象注册了进去,只有BeanFactory老老实实得注册了一个BeanFactory
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// Register early post-processor for detecting inner beans as ApplicationListeners.
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
// 添加对AspectJ的支持
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()));
}
// Register default environment beans.添加系统环境默认的bean
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());
}
}
到这里refresh()的前面三个方法已经简单过完了,除了解析配置文件复杂点,其他的都是些属性配置居多。
小结本文先通过一个列子驱动,找到了Ioc容器启动的入口,简单分析了一下前三个方法,最重要的就是加载BeanDefinition的过程了,可以仔细看多几遍。
今天发生了点小插曲,本该写得更详细点的,但是写不了了,只能作罢,将就着看吧。
如果有人看到这里,那在这里老话重提。与君共勉,路漫漫其修远兮,吾将上下而求索。
本文共计2232个文字,预计阅读时间需要9分钟。
《Spring IoC源码解析系列--IoC源码入口分析+本系列文章代码基于Spring Framework 5.2.x+前言+上一篇文章Spring IoC源码解析系列--IoC的基础知识介绍了IoC的基本概念以及Spring IoC体系的组成部分》
Spring Ioc源码分析系列--Ioc源码入口分析前言本系列文章代码基于Spring Framework 5.2.x
上一篇文章Spring Ioc源码分析系列--Ioc的基础知识准备介绍了Ioc的基础概念以及Spring Ioc体系的部分基础知识。那么这一篇就会真正通过一个例子,启动Ioc容器,获取容器里的bean。
首先说明,本文的例子是基于xml配置文件去完成的。
为什么是xml?因为xml是Spring的灵魂,可能我们初学Spring都会有畏难情绪,看到繁杂的xml就会打退堂鼓。但是实际上不然,xml的格式是相当清晰的,一个配置文件可以说没有一行配置是多余的。现在大部分的配置是用注解去完成的,相比xml而言是简洁许多,但是对于我们初学而言,xml其实是更好的方式,xml相对于注解而言是相对繁杂,但是它的信息也更多更明确,注解只是添加了一个注解就完成配置,细节上是更为隐蔽的。再加上xml配置文件和注解配置的原理是相通的,核心思想是一样的,掌握核心就万变不离其宗。所以这系列文章的例子大部分都会采取xml的方式去配置,当然后续可能也会补充一下注解方式的例子和分析文章。
万事开头难,如果实在觉得看不懂但又想学的,可以硬着头皮看下去,等以后回过头来再看的时候,会有豁然开朗的感觉。
源码分析 启动容器示例废话少说,下面开始搞个例子分析一下。所有源码都在我的仓库ioc-sourcecode-analysis-code-demo里找到。
首先弄个实体类User
/**
* @author Codegitz
* @date 2022/4/26 10:58
**/
public class User {
private String id;
private String name;
private String age;
}
创建业务类UserService以及业务实现类UserServiceImpl,这里的逻辑很简单,就是根据传入的name和age返回一个新的user对象。
/**
* @author Codegitz
* @date 2022/4/26 10:59
**/
public interface UserService {
User getUser(String name,String age);
}
public class UserServiceImpl implements UserService {
@Override
public User getUser(String name, String age) {
User user = new User();
user.setId("1");
user.setName(name);
user.setAge(age);
return user;
}
}
业务类的准备工作已经完成了,接下来就是要写个xml配置文件,告诉Spring Ioc我需要一个UserService的bean。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="www.springframework.org/schema/beans"
xmlns:xsi="www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="www.springframework.org/schema/beans www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userService" class="io.codegitz.service.impl.UserServiceImpl"/>
</beans>
这个xml配置文件比较简单,我们来解释一下每一行是什么意思。
<?xml version="1.0" encoding="UTF-8"?>为xml文件的规定头,没啥好说的。
xmlns="www.springframework.org/schema/beans"表明了xml的命名空间,xmlns全称为xml namespace,一个xml里面命名空间可以有多个。
xmlns:xsi和 xsi:schemaLocation是指明了xml文件的验证模型和验证模型文件的位置。可以看到验证模型能通过www.springframework.org/schema/beans"
this.delegate = createDelegate(getReaderContext(), root, parent);
if (this.delegate.isDefaultNamespace(root)) {
//获取这个profile的值,表示剖面,用于设置环境
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;
}
}
}
//解析XML之前做的准备工作,其实什么也没做
preProcessXml(root);
//调用这个方法解析
parseBeanDefinitions(root, this.delegate);
//后续处理
postProcessXml(root);
this.delegate = parent;
}
跟进解析BeanDefinition的方法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;
//Bean定义的document对象使用了spring的默认命名空间,如www.springframework.org/schema/beans
if (delegate.isDefaultNamespace(ele)) {
//若是则按照spring原有的逻辑进行解析
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);
}
//若果是别名元素,则进行别名解析
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
//bean元素解析
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
显然我们的例子只有一个Bean标签,所以会进入到processBeanDefinition()方法里。
/**
* Process the given bean element, parsing the bean definition
* and registering it with the registry.
*/
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
//BeanDefinitionHolder是对BeanDefinition的封装,即bean定义的封装类
//对document对象中的bean标签解析由BeanDefinitionParserDelegate实现
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
//从springIOC容器注册解析得到的BeanDefinition,这是BeanDefinition向IOC容器注册的入口
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()方法真正将BeanDefinition注册进容器里。咋注册呢?其实就是加到BeanFactory的beanDefinitionMap属性里。beanDefinitionMap可以说就是BeanDefinition的容器了。
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// Register bean definition under primary name.
String beanName = definitionHolder.getBeanName();
// 这里真正把BeanDefinition注册到了BeanFactory里
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);
}
}
}
到这里已经完成了BeanDefinition的注册,是不是有点曲折?其实很简单,就是细节比较多。
到这里obtainFreshBeanFactory()方法已经基本结束,已经完成了配置文件的解析并且注册BeanDefinition的过程了。剩下的操作就是把这个BeanFactory返回给上一步。
接下来分析一下prepareBeanFactory()方法,这方法也简单,主要就是对BeanFactory进行一些属性的设置,跟着注释看一下就行。
/**
* Configure the factory's standard context characteristics,
* such as the context's ClassLoader and post-processors.
* @param beanFactory the BeanFactory to configure
*/
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
// 设置 beanFactory的classLoader 为当前 context的classLoader
beanFactory.setBeanClassLoader(getClassLoader());
/**
* 设置 beanFactory的表达式语言处理器,Spring3 增加了表达式语言的支持,
* 默认可以使用#{bean.xxx}的形式来调用相关属性值
* @Qusetion 在注册了这个解析器之后,spring是在什么时候调用这个解析器的呢?
* Spring在bean进行初始化的时候会有属性填充的步骤,而在这一步中
* Spring会调用AbstractAutowireCapableBeanFactory类的applyPropertyValues函数来完成功能。
* 就这个函数中,会通过构造 BeanDefinitionValueResolver类型实例valueResolver来进行属性值的解析。
* 同时,也是在这个步骤中一般通过 AbstractBeanFactory 中的 evaluateBeanDefinitionString
* 方法去完成SpEL解析
*/
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
//为beanFactory增加一个PropertyEditor,这个主要是对bean的属性等设置管理的一个工具
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
//添加beanPostProcessor
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
//设置几个忽略自动装配的接口
// aware都是由invokeAware方法注入,忽略自动Autowire
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 interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
// 设置了几个自动装配的规则,后面三个都是把当前对象注册了进去,只有BeanFactory老老实实得注册了一个BeanFactory
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// Register early post-processor for detecting inner beans as ApplicationListeners.
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
// 添加对AspectJ的支持
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()));
}
// Register default environment beans.添加系统环境默认的bean
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());
}
}
到这里refresh()的前面三个方法已经简单过完了,除了解析配置文件复杂点,其他的都是些属性配置居多。
小结本文先通过一个列子驱动,找到了Ioc容器启动的入口,简单分析了一下前三个方法,最重要的就是加载BeanDefinition的过程了,可以仔细看多几遍。
今天发生了点小插曲,本该写得更详细点的,但是写不了了,只能作罢,将就着看吧。
如果有人看到这里,那在这里老话重提。与君共勉,路漫漫其修远兮,吾将上下而求索。

