服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Java教程 - Java Spring的refresh方法你知道吗

Java Spring的refresh方法你知道吗

2022-10-09 13:53油头怪 Java教程

这篇文章主要为大家详细介绍了Java Spring的refresh方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助

spring的refresh方法

前置知识

方法入口

// org.springframework.context.support.AbstractApplicationContext#refresh

类的结构图

Java Spring的refresh方法你知道吗

BeanDefinition 接口定义

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
 // 我们可以看到,默认只提供 sington 和 prototype 两种,
 // 很多读者可能知道还有 request, session, globalSession, application, websocket 这几种,
 // 不过,它们属于基于 web 的扩展。
 String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
 String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
 // 比较不重要,直接跳过吧
 int ROLE_APPLICATION = 0;
 int ROLE_SUPPORT = 1;
 int ROLE_INFRASTRUCTURE = 2;
 // 设置父 Bean,这里涉及到 bean 继承,不是 java 继承。请参见附录的详细介绍
 // 一句话就是:继承父 Bean 的配置信息而已
 void setParentName(String parentName);
 // 获取父 Bean
 String getParentName();
 // 设置 Bean 的类名称,将来是要通过反射来生成实例的
 void setBeanClassName(String beanClassName);
 // 获取 Bean 的类名称
 String getBeanClassName();

 // 设置 bean 的 scope
 void setScope(String scope);
 String getScope();
 // 设置是否懒加载
 void setLazyInit(boolean lazyInit);
 boolean isLazyInit();
 // 设置该 Bean 依赖的所有的 Bean,注意,这里的依赖不是指属性依赖(如 @Autowire 标记的),
 // 是 depends-on="" 属性设置的值。
 void setDependsOn(String... dependsOn);
 // 返回该 Bean 的所有依赖
 String[] getDependsOn();
 // 设置该 Bean 是否可以注入到其他 Bean 中,只对根据类型注入有效,
 // 如果根据名称注入,即使这边设置了 false,也是可以的
 void setAutowireCandidate(boolean autowireCandidate);
 // 该 Bean 是否可以注入到其他 Bean 中
 boolean isAutowireCandidate();
 // 主要的。同一接口的多个实现,如果不指定名字的话,Spring 会优先选择设置 primary 为 true 的 bean
 void setPrimary(boolean primary);
 // 是否是 primary 的
 boolean isPrimary();
 // 如果该 Bean 采用工厂方法生成,指定工厂名称。对工厂不熟悉的读者,请参加附录
 // 一句话就是:有些实例不是用反射生成的,而是用工厂模式生成的
 void setFactoryBeanName(String factoryBeanName);
 // 获取工厂名称
 String getFactoryBeanName();
 // 指定工厂类中的 工厂方法名称
 void setFactoryMethodName(String factoryMethodName);
 // 获取工厂类中的 工厂方法名称
 String getFactoryMethodName();
 // 构造器参数
 ConstructorArgumentValues getConstructorArgumentValues();
 // Bean 中的属性值,后面给 bean 注入属性值的时候会说到
 MutablePropertyValues getPropertyValues();
 // 是否 singleton
 boolean isSingleton();
 // 是否 prototype
 boolean isPrototype();
 // 如果这个 Bean 是被设置为 abstract,那么不能实例化,
 // 常用于作为 父bean 用于继承,其实也很少用......
 boolean isAbstract();
 int getRole();
 String getDescription();
 String getResourceDescription();
 BeanDefinition getOriginatingBeanDefinition();
}

refresh 这里简单说下为什么是 refresh(),而不是 init() 这种名字的方法。因为 ApplicationContext 建立起来以后,其实我们是可以通过调用 refresh() 这个方法重建的,refresh() 会将原来的 ApplicationContext 销毁,然后再重新执行一次初始化操作。

@Override
public void refresh() throws BeansException, IllegalStateException {
 // 来个锁,不然 refresh() 还没结束,你又来个启动或销毁容器的操作,那不就乱套了嘛
 synchronized (this.startupShutdownMonitor) {
    // 准备工作,记录下容器的启动时间、标记“已启动”状态、处理配置文件中的占位符
    prepareRefresh();
    // 这步比较关键,这步完成后,配置文件就会解析成一个个 Bean 定义,注册到 BeanFactory 中,
    // 当然,这里说的 Bean 还没有初始化,只是配置信息都提取出来了,
    // 注册也只是将这些信息都保存到了注册中心(说到底核心是一个 beanName-> beanDefinition 的 map)
    ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    // 设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean
    // 这块待会会展开说
    prepareBeanFactory(beanFactory);
    try {
       // 【这里需要知道 BeanFactoryPostProcessor 这个知识点,Bean 如果实现了此接口,
       // 那么在容器初始化以后,Spring 会负责调用里面的 postProcessBeanFactory 方法。】
       // 这里是提供给子类的扩展点,到这里的时候,所有的 Bean 都加载、注册完成了,但是都还没有初始化
       // 具体的子类可以在这步的时候添加一些特殊的 BeanFactoryPostProcessor 的实现类或做点什么事
       postProcessBeanFactory(beanFactory);
       // 调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 方法
       invokeBeanFactoryPostProcessors(beanFactory);
       // 注册 BeanPostProcessor 的实现类,注意看和 BeanFactoryPostProcessor 的区别
       // 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
       // 两个方法分别在 Bean 初始化之前和初始化之后得到执行。注意,到这里 Bean 还没初始化
       registerBeanPostProcessors(beanFactory);
       // 初始化当前 ApplicationContext 的 MessageSource,国际化这里就不展开说了,不然没完没了了
       initMessageSource();
       // 初始化当前 ApplicationContext 的事件广播器,这里也不展开了
       initApplicationEventMulticaster();
       // 从方法名就可以知道,典型的模板方法(钩子方法),
       // 具体的子类可以在这里初始化一些特殊的 Bean(在初始化 singleton beans 之前)
       onRefresh();
       // 注册事件监听器,监听器需要实现 ApplicationListener 接口。这也不是我们的重点,过
       registerListeners();
       // 重点,重点,重点
       // 初始化所有的 singleton beans
       //(lazy-init 的除外)
       finishBeanFactoryInitialization(beanFactory);
       // 最后,广播事件,ApplicationContext 初始化完成
       finishRefresh();
    }
    catch (BeansException ex) {
       if (logger.isWarnEnabled()) {
          logger.warn("Exception encountered during context initialization - " +
                "cancelling refresh attempt: " + ex);
       }
       // Destroy already created singletons to avoid dangling resources.
       // 销毁已经初始化的 singleton 的 Beans,以免有些 bean 会一直占用资源
       destroyBeans();
       // Reset 'active' flag.
       cancelRefresh(ex);
       // 把异常往外抛
       throw ex;
    }
    finally {
       // Reset common introspection caches in Spring's core, since we
       // might not ever need metadata for singleton beans anymore...
       resetCommonCaches();
    }
 }
}

创建 Bean 容器前的准备工作

// 准备工作
protected void prepareRefresh() {
 // 记录启动时间,
 // 将 active 属性设置为 true,closed 属性设置为 false,它们都是 AtomicBoolean 类型
 this.startupDate = System.currentTimeMillis();
 this.closed.set(false);
 this.active.set(true);
 if (logger.isInfoEnabled()) {
    logger.info("Refreshing " + this);
 }
 // Initialize any placeholder property sources in the context environment 初始化上下文环境中的任何占位符属性源。
 initPropertySources();
 // 校验 xml 配置文件
 getEnvironment().validateRequiredProperties();
 // 初始化事件集合
 this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}

创建 Bean 容器,加载并注册 Bean

// 最重要的方法之一,这里将会初始化 BeanFactory、加载 Bean、注册 Bean 等等。
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
 // 关闭旧的 BeanFactory (如果有),创建新的 BeanFactory,加载 Bean 定义、注册 Bean 等等
 refreshBeanFactory();
 // 返回刚刚创建的 BeanFactory
 ConfigurableListableBeanFactory beanFactory = getBeanFactory();
 if (logger.isDebugEnabled()) {
    logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
 }
 return beanFactory;
}
// refreshBeanFactory
@Override
protected final void refreshBeanFactory() throws BeansException {
 // 如果 ApplicationContext 中已经加载过 BeanFactory 了,销毁所有 Bean,关闭 BeanFactory
 // 注意,应用中 BeanFactory 本来就是可以多个的,这里可不是说应用全局是否有 BeanFactory,而是当前
 // ApplicationContext 是否有 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);
 }
}
// customizeBeanFactory 配置是否允许 BeanDefinition 覆盖、是否允许循环引用。
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
 if (this.allowBeanDefinitionOverriding != null) {
    // 是否允许 Bean 定义覆盖  在配置文件中定义 bean 时使用了相同的 id 或 name,默认情况下,allowBeanDefinitionOverriding 属性为 null,如果在同一配置文件中重复了,会抛错,但是如果不是同一配置文件中,会发生覆盖。
    beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
 }
 if (this.allowCircularReferences != null) {
    // 是否允许 Bean 间的循环依赖  如:A 依赖 B,而 B 依赖 A。或 A 依赖 B,B 依赖 C,而 C 依赖 A。
    beanFactory.setAllowCircularReferences(this.allowCircularReferences);
 }
}
// loadBeanDefinitions 加载bean,放入 BeanFactory 中 org.springframework.context.support.AbstractXmlApplicationContext#loadBeanDefinitions(org.springframework.beans.factory.support.DefaultListableBeanFactory)
/** 我们可以看到,此方法将通过一个 XmlBeanDefinitionReader 实例来加载各个 Bean。*/
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
 // 给这个 BeanFactory 实例化一个 XmlBeanDefinitionReader
 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));
 // 初始化 BeanDefinitionReader,其实这个是提供给子类覆写的,
 // 我看了一下,没有类覆写这个方法,我们姑且当做不重要吧
 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) {
    // 2
    reader.loadBeanDefinitions(configLocations);
 }
}
// 上面虽然有两个分支,不过第二个分支很快通过解析路径转换为 Resource 以后也会进到这里
@Override
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
 Assert.notNull(resources, "Resource array must not be null");
 int counter = 0;
 // 注意这里是个 for 循环,也就是每个文件是一个 resource
 for (Resource resource : resources) {
    // 继续往下看
    counter += loadBeanDefinitions(resource);
 }
 // 最后返回 counter,表示总共加载了多少的 BeanDefinition
 return counter;
}
// XmlBeanDefinitionReader 303
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
 return loadBeanDefinitions(new EncodedResource(resource));
}
// XmlBeanDefinitionReader 314
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();
    }
 }
}
// 还在这个文件中,第 388 行
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
    throws BeanDefinitionStoreException {
 try {
    // 这里就不看了,将 xml 文件转换为 Document 对象
    Document doc = doLoadDocument(inputSource, resource);
    // 继续
    return registerBeanDefinitions(doc, resource);
 }
 catch (...
}
// 还在这个文件中,第 505 行
// 返回值:返回从当前配置文件加载了多少数量的 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 90
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
 this.readerContext = readerContext;
 logger.debug("Loading bean definitions");
 Element root = doc.getDocumentElement();
 // 从 xml 根节点开始解析文件
 doRegisterBeanDefinitions(root);
}     
// doRegisterBeanDefinitions 经过漫长的链路,一个配置文件终于转换为一颗 DOM 树了,注意,这里指的是其中一个配置文件,不是所有的,读者可以看到上面有个 for 循环的。下面开始从根节点开始解析:
// DefaultBeanDefinitionDocumentReader 116
protected void doRegisterBeanDefinitions(Element root) {
 // 我们看名字就知道,BeanDefinitionParserDelegate 必定是一个重要的类,它负责解析 Bean 定义,
 // 这里为什么要定义一个 parent? 看到后面就知道了,是递归问题,
 // 因为 <beans /> 内部是可以定义 <beans /> 的,所以这个方法的 root 其实不一定就是 xml 的根节点,也可以是嵌套在里面的 <beans /> 节点,从源码分析的角度,我们当做根节点就好了
 BeanDefinitionParserDelegate parent = this.delegate;
 this.delegate = createDelegate(getReaderContext(), root, parent);
 if (this.delegate.isDefaultNamespace(root)) {
    // 这块说的是根节点 <beans ... profile="dev" /> 中的 profile 是否是当前环境需要的,
    // 如果当前环境配置的 profile 不包含此 profile,那就直接 return 了,不对此 <beans /> 解析
    // 不熟悉 profile 为何物,不熟悉怎么配置 profile 读者的请移步附录区
    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); // 钩子 preProcessXml(root) 和 postProcessXml(root) 是给子类用的钩子方法,鉴于没有被使用到,也不是我们的重点,我们直接跳过。
 // 往下看
 parseBeanDefinitions(root, this.delegate);
 postProcessXml(root); // 钩子
 this.delegate = parent;
}
// default namespace 涉及到的就四个标签 <import />、<alias />、<bean /> 和 <beans />,
// 其他的属于 custom 的
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)) {
             // 解析 default namespace 下面的几个元素
             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);
 }
}          
// DefaultBeanDefinitionDocumentReader 298
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
 // 将 <bean /> 节点中的信息提取出来,然后封装到一个 BeanDefinitionHolder 中,细节往下看
 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 428
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
  return parseBeanDefinitionElement(ele, null);
}
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;
}          

看到这里的时候,我觉得读者就应该站在高处看 ApplicationContext 了,ApplicationContext 继承自 BeanFactory,但是它不应该被理解为 BeanFactory 的实现类,而是说其内部持有一个实例化的 BeanFactory(DefaultListableBeanFactory)。以后所有的 BeanFactory 相关的操作其实是委托给这个实例来处理的。

我们说说为什么选择实例化DefaultListableBeanFactory?前面我们说了有个很重要的接口 ConfigurableListableBeanFactory,它实现了 BeanFactory 下面一层的所有三个接口,我把之前的继承图再拿过来大家再仔细看一下:

Java Spring的refresh方法你知道吗

我们可以看到 ConfigurableListableBeanFactory 只有一个实现类DefaultListableBeanFactory,而且实现类 DefaultListableBeanFactory 还通过实现右边的 AbstractAutowireCapableBeanFactory 通吃了右路。所以结论就是,最底下这个家伙 DefaultListableBeanFactory 基本上是最牛的 BeanFactory 了,这也是为什么这边会使用这个类来实例化的原因。

循环依赖

Java Spring的refresh方法你知道吗

 

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注服务器之家的更多内容!   

原文链接:https://blog.csdn.net/weixin_41010294/article/details/123556466

延伸 · 阅读

精彩推荐