Spring Ioc源码解析:从何处切入Ioc源码核心?

2026-05-06 05:311阅读0评论SEO问题
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计2232个文字,预计阅读时间需要9分钟。

Spring Ioc源码解析:从何处切入Ioc源码核心?

《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,这里的逻辑很简单,就是根据传入的nameage返回一个新的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我需要一个UserServicebean

<?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:xsixsi: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注册进容器里。咋注册呢?其实就是加到BeanFactorybeanDefinitionMap属性里。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()方法

接下来分析一下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的过程了,可以仔细看多几遍。

今天发生了点小插曲,本该写得更详细点的,但是写不了了,只能作罢,将就着看吧。

Spring Ioc源码解析:从何处切入Ioc源码核心?

如果有人看到这里,那在这里老话重提。与君共勉,路漫漫其修远兮,吾将上下而求索。

本文共计2232个文字,预计阅读时间需要9分钟。

Spring Ioc源码解析:从何处切入Ioc源码核心?

《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,这里的逻辑很简单,就是根据传入的nameage返回一个新的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我需要一个UserServicebean

<?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:xsixsi: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注册进容器里。咋注册呢?其实就是加到BeanFactorybeanDefinitionMap属性里。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()方法

接下来分析一下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的过程了,可以仔细看多几遍。

今天发生了点小插曲,本该写得更详细点的,但是写不了了,只能作罢,将就着看吧。

Spring Ioc源码解析:从何处切入Ioc源码核心?

如果有人看到这里,那在这里老话重提。与君共勉,路漫漫其修远兮,吾将上下而求索。