IOC
将模块(对象)之间的依赖关系交由IOC容器管理,让应用开发对接口编程,而不是对类编程。
依赖反转:每个对象都需要与其合作的对象(也就是依赖的对象)的引用。未使用依赖反转的特性之前,是需要先创建一个具体的对象,然后才能引用。而依赖反转是等要调用这个依赖对象时去创建这个依赖实例。这个实现由IOC容器去实现,将具体对象的创建交给IoC容器提高代码的解耦,更加注重业务逻辑的处理。但这又需要依赖注入的实现。【调用这个依赖对象时创建这个依赖的实例,那么是根据什么样的原理来实现的呢?】
依赖注入:将依赖的对象注入到调用的实例中。
public class A{
private B b;
}
-----------
IOC容器系列的设计:BeanFactory和ApplicationContext
Spring通过定义BeanDefinition来管理基于spring的应用中的各种对象以及它们之间的相互依赖关系。BeanDefinition就是对依赖反转模式中管理的对象依赖关系的数据抽象,也是容器实现依赖反转功能的核心数据结构。BeanDefinition中定义了那些注入到IOC容器中类的信息,只是以spring中定义的数据结构呈现。
注:有点跟Class文件结构类似。
BeanDefinition是一个接口,定义了一些规范。
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
}
----------
从接口BeanFacotry到HierarchicalBeanFactory,再到ConfigurableBeanFactory,是一条主要的BeanFactory设计路径。BeanFacotry接口定义了基本的IOC容器的规范。
public interface BeanFactory {
String FACTORY_BEAN_PREFIX = "&";
Object getBean(String var1) throws BeansException;
<T> T getBean(String var1, Class<T> var2) throws BeansException;
<T> T getBean(Class<T> var1) throws BeansException;
....省略
}
HierarchicalBeanFactory 增加了getParentBeanFactory()接口功能,使BeanFactory 具备了双亲管理功能。
public interface HierarchicalBeanFactory extends BeanFactory {
BeanFactory getParentBeanFactory();
boolean containsLocalBean(String var1);
}
----
第二条主线:是以ApplicationContext应用上下接口为核心的接口设计,这个主要是从BeanFactory接口到ListableBeanFactory接口,再到ApplicationContext接口最后到WebApplicationContext或者ConfiurableApplicationContext;
ApplicationContext context = new ClassPathXmlApplicationContext("classPath:applicaitonContext.xml");
ClassPathXmlApplicationContext基础父类是ConfiurableApplicationContext接口,ConfiurableApplicationContext实现了ApplicationContext接口。
注:用户使用容器时,可以使用转义符"&"来得到FactoryBean本身,用来区分通过容器获取FactoryBean产生的对象和获取FactoryBean本身。
BeanFactory中String[] getAliases(String var1);可以查询指定了名字的Bean的所有别名。
---------------
分析ApplicationContext context = new ClassPathXmlApplicationContext("classPath:applicaitonContext.xml");
public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext { private Resource[] configResources; public ClassPathXmlApplicationContext(String configLocation) throws BeansException { this(new String[]{configLocation}, true, (ApplicationContext)null); } public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException { super(parent); this.setConfigLocations(configLocations); if (refresh) { this.refresh();//核心方法 } } }
启动spring容器将spring配置文件加载到IOC容器中,当调用ClassPathXmlApplicationContext的构造器时,会调用 this(new String[]{configLocation}, true, (ApplicationContext)null);方法。然后会调用父类的setConfigLocations方法,将配置文件路径传入:
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] = this.resolvePath(locations[i]).trim(); } } else { this.configLocations = null; } }
refresh()方法:它是IoC的核心方法,由它把类加载到spring容器中,
public void refresh() throws BeansException, IllegalStateException { Object var1 = this.startupShutdownMonitor; // 来个锁,不然 refresh() 还没结束,你又来个启动或销毁容器的操作 synchronized(this.startupShutdownMonitor) { //准备工作,记录下容器的启动时间、标记“已启动”状态、处理配置文件中的占位符 this.prepareRefresh(); // 这步比较关键,这步完成后,配置文件就会被解析成一个个 Bean 定义,注册到 BeanFactory 中, // 当然,这里说的 Bean 还没有初始化,只是配置信息都提取出来了, // 注册也只是将这些信息都保存到了注册中心(说到底核心是一个 beanName-> beanDefinition 的 map) ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory(); // 设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean this.prepareBeanFactory(beanFactory); try { // 【这里需要知道 BeanFactoryPostProcessor 这个知识点,Bean 如果实现了此接口, // 那么在容器初始化以后,Spring 会负责调用里面的 postProcessBeanFactory 方法。】 // 这里是提供给子类的扩展点,到这里的时候,所有的 Bean 都加载、注册完成了,但是都还没有初始化 // 具体的子类可以在这步的时候添加一些特殊的 BeanFactoryPostProcessor 的实现类或做点什么事 this.postProcessBeanFactory(beanFactory); // 调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 方法 this.invokeBeanFactoryPostProcessors(beanFactory); // 注册 BeanPostProcessor 的实现类,注意看和 BeanFactoryPostProcessor 的区别 // 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization // 两个方法分别在 Bean 初始化之前和初始化之后得到执行。注意,到这里 Bean 还没初始化 this.registerBeanPostProcessors(beanFactory); // 初始化当前 ApplicationContext 的 MessageSource,国际化 this.initMessageSource(); // 初始化当前 ApplicationContext 的事件广播器 this.initApplicationEventMulticaster(); // 具体的子类可以在这里初始化一些特殊的 Bean(在初始化 singleton beans 之前) this.onRefresh(); // 注册事件监听器,监听器需要实现 ApplicationListener 接口 this.registerListeners(); / 重点,重点,重点 // 初始化所有的 singleton beans //(lazy-init 的除外) this.finishBeanFactoryInitialization(beanFactory); // 最后,广播事件,ApplicationContext 初始化完成 this.finishRefresh(); } catch (BeansException var9) { if (this.logger.isWarnEnabled()) { this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9); } // 销毁已经初始化的 singleton 的 Beans,以免有些 bean 会一直占用资源 this.destroyBeans(); this.cancelRefresh(var9); throw var9; } finally { this.resetCommonCaches(); } } }
本节主要分析refresh类中的ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();方法
//AbstractApplicationContext类 protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { //更新BeanFactory; refreshBeanFactory(); ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (logger.isDebugEnabled()) { logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory); } return beanFactory; } //refreshBeanFactory();AbstractRefreshableApplicationContext类 protected final void refreshBeanFactory() throws BeansException { //如果有BeanFactory则,关闭这个BeanFactory if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { //初始化一个DefaultListableBeanFactory对象 DefaultListableBeanFactory beanFactory = createBeanFactory(); //BeanFactory序列化 beanFactory.setSerializationId(getId()); // 设置 BeanFactory 的两个配置属性:是否允许 Bean 覆盖、是否允许循环引用 customizeBeanFactory(beanFactory); // 加载 Bean 到 BeanFactory 中, loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } }
//loadBeanDefinitions(beanFactory)在AbstractXmlApplicationContext类中 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); } } //reader.loadBeanDefinitions(configResources);方法在 XmlBeanDefinitionReader类中 public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException { return loadBeanDefinitions(new EncodedResource(resource)); } public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException { Assert.notNull(encodedResource, "EncodedResource must not be null"); if (logger.isInfoEnabled()) { logger.info("Loading XML bean definitions from " + encodedResource.getResource()); } // 用一个 ThreadLocal 来存放配置文件资源 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(); } } } ----
//将xml文档中对象解析;方法在 XmlBeanDefinitionReader类中
//将xml文档中对象解析;方法在 XmlBeanDefinitionReader类中 protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException { try { //创建一个文档对象 Document doc = doLoadDocument(inputSource, resource); //将xml中的bean信息注册到BeanDefinition中 return registerBeanDefinitions(doc, resource); } catch (BeanDefinitionStoreException ex) { throw ex; } ....... } --- // 返回值:返回从当前配置文件加载了多少数量的 Bean public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); int countBefore = getRegistry().getBeanDefinitionCount(); documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); return getRegistry().getBeanDefinitionCount() - countBefore; } --- //方法在DefaultBeanDefinitionDocumentReader //加载bean的相关信息,使用XML文档对象获取定义在xml文件中bean的信息 public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) { this.readerContext = readerContext; logger.debug("Loading bean definitions"); Element root = doc.getDocumentElement(); //从root开始解析xml文档 doRegisterBeanDefinitions(root); } protected void doRegisterBeanDefinitions(Element root) { this.delegate = createDelegate(getReaderContext(), root, parent); if (this.delegate.isDefaultNamespace(root)) { String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE); if (StringUtils.hasText(profileSpec)) { String[] specifiedProfiles = StringUtils.tokenizeToStringArray( profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS); if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) { return; } } } preProcessXml(root); //开始解析XML文档 parseBeanDefinitions(root, this.delegate); postProcessXml(root); this.delegate = parent; } // default namespace 涉及到的就四个标签 <import />、<alias />、<bean /> 和 <beans />, // 其他的属于 custom 的 //这里的四个标签之所以是 default 的,是因为它们是处于这个 namespace 下定义的: //http://www.springframework.org/schema/beans 而对于其他的标签,将进入到 delegate.parseCustomElement(element) 这个分支。如我们经常会使用到的 <mvc />、<task />、<context />、<aop />等。 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 { // 解析其他 namespace 的元素 delegate.parseCustomElement(ele); } } } } else { delegate.parseCustomElement(root); } } -- private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) { if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) { // 处理 <import /> 标签 importBeanDefinitionResource(ele); } else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) { // 处理 <alias /> 标签定义 // <alias name="fromName" alias="toName"/> processAliasRegistration(ele); } else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) { // 处理 <bean /> 标签定义,这也算是我们的重点吧 processBeanDefinition(ele, delegate); } else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) { // 如果碰到的是嵌套的 <beans /> 标签,需要递归 doRegisterBeanDefinitions(ele); } } /** * Process the given bean element, parsing the bean definition * and registering it with the registry. */ protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { // 将 <bean /> 节点中的信息提取出来,然后封装到一个 BeanDefinitionHolder 中 BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); if (bdHolder != null) { bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try { // 注册 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)); } } public class BeanDefinitionHolder implements BeanMetadataElement { private final BeanDefinition beanDefinition; private final String beanName; private final String[] aliases; } public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) { return parseBeanDefinitionElement(ele, null); } ---- //产生BeanDefinition实例,将xml定义的bean信息封装到BeanDefinition实例中, //并将BeanDefinition放入到BeanDefinitionHolder对象中,返回该对象 public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) { String id = ele.getAttribute(ID_ATTRIBUTE); String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); List<String> aliases = new ArrayList<String>(); // 将 name 属性的定义按照 “逗号、分号、空格” 切分,形成一个 别名列表数组, // 当然,如果你不定义 name 属性的话,就是空的了 // 我在附录中简单介绍了一下 id 和 name 的配置,大家可以看一眼,有个20秒就可以了 if (StringUtils.hasLength(nameAttr)) { String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS); aliases.addAll(Arrays.asList(nameArr)); } String beanName = id; // 如果没有指定id, 那么用别名列表的第一个名字作为beanName 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"); } } if (containingBean == null) { checkNameUniqueness(beanName, aliases, ele); } // 根据 <bean ...>...</bean> 中的配置创建 BeanDefinition,然后把配置中的信息都设置到实例中, // 细节后面细说,先知道下面这行结束后,一个 BeanDefinition 实例就出来了。 AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean); // 到这里,整个 <bean /> 标签就算解析结束了,一个 BeanDefinition 就形成了。 if (beanDefinition != null) { // 如果都没有设置 id 和 name,那么此时的 beanName 就会为 null,进入下面这块代码产生 // 如果读者不感兴趣的话,我觉得不需要关心这块代码,对本文源码分析来说,这些东西不重要 if (!StringUtils.hasText(beanName)) { try { if (containingBean != null) {// 按照我们的思路,这里 containingBean 是 null 的 beanName = BeanDefinitionReaderUtils.generateBeanName( beanDefinition, this.readerContext.getRegistry(), true); } else { // 如果我们不定义 id 和 name,那么我们引言里的那个例子: // 1. beanName 为:com.javadoop.example.MessageServiceImpl#0 // 2. beanClassName 为:com.javadoop.example.MessageServiceImpl beanName = this.readerContext.generateBeanName(beanDefinition); String beanClassName = beanDefinition.getBeanClassName(); if (beanClassName != null && beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() && !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) { // 把 beanClassName 设置为 Bean 的别名 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); // 返回 BeanDefinitionHolder return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); } return null; } --- //将获取的xml信息放入到BeanDefinition中 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); } AbstractBeanDefinition bd = createBeanDefinition(className, parent); 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; } ---------- //回到processBeanDefinition()方法中的registerBeanDefinition步骤 public static void registerBeanDefinition( BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException { // 将bean注册到BeanDefinition String beanName = definitionHolder.getBeanName(); registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); // Register aliases for bean name, if any. String[] aliases = definitionHolder.getAliases(); if (aliases != null) { for (String alias : aliases) { registry.registerAlias(beanName, alias); } } } --------- @Override public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { Assert.hasText(beanName, "Bean name must not be empty"); Assert.notNull(beanDefinition, "BeanDefinition must not be null"); if (beanDefinition instanceof AbstractBeanDefinition) { try { ((AbstractBeanDefinition) beanDefinition).validate(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(...); } } // old? 还记得 “允许 bean 覆盖” 这个配置吗?allowBeanDefinitionOverriding BeanDefinition oldBeanDefinition; // 之后会看到,所有的 Bean 注册后会放入这个 beanDefinitionMap 中 oldBeanDefinition = this.beanDefinitionMap.get(beanName); // 处理重复名称的 Bean 定义的情况 if (oldBeanDefinition != null) { if (!isAllowBeanDefinitionOverriding()) { // 如果不允许覆盖的话,抛异常 throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription()... } else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) { // log...用框架定义的 Bean 覆盖用户自定义的 Bean } else if (!beanDefinition.equals(oldBeanDefinition)) { // log...用新的 Bean 覆盖旧的 Bean } else { // log...用同等的 Bean 覆盖旧的 Bean,这里指的是 equals 方法返回 true 的 Bean } // 覆盖 this.beanDefinitionMap.put(beanName, beanDefinition); } else { // 判断是否已经有其他的 Bean 开始初始化了. // 注意,"注册Bean" 这个动作结束,Bean 依然还没有初始化,我们后面会有大篇幅说初始化过程, // 在 Spring 容器启动的最后,会 预初始化 所有的 singleton beans 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 { // 最正常的应该是进到这个分支。 // 将 BeanDefinition 放到这个 map 中,这个 map 保存了所有的 BeanDefinition this.beanDefinitionMap.put(beanName, beanDefinition); // 这是个 ArrayList,所以会按照 bean 配置的顺序保存每一个注册的 Bean 的名字 this.beanDefinitionNames.add(beanName); // 这是个 LinkedHashSet,代表的是手动注册的 singleton bean, // 注意这里是 remove 方法,到这里的 Bean 当然不是手动注册的 // 手动指的是通过调用以下方法注册的 bean : // registerSingleton(String beanName, Object singletonObject) // 这不是重点,解释只是为了不让大家疑惑。Spring 会在后面"手动"注册一些 Bean, // 如 "environment"、"systemProperties" 等 bean,我们自己也可以在运行时注册 Bean 到容器中的 this.manualSingletonNames.remove(beanName); } // 这个不重要,在预初始化的时候会用到,不必管它。 this.frozenBeanDefinitionNames = null; } if (oldBeanDefinition != null || containsSingleton(beanName)) { resetBeanDefinition(beanName); } } ----------------- 上面这些步骤就是将refresh()方法中的前两步完成,也就是将xml配置文件中信息读取到spring的BeanDefinition类中,还未对bean进行初始化。