SpringBoot源码解读与原理分析(七)BeanFactory

文章目录

  • 3 SpringBoot的IOC容器
    • 3.1 SpringFramework的IOC容器
      • 3.1.1 BeanFactory
        • 3.1.1.1 BeanFactory根接口
        • 3.1.1.2 HierarchicalBeanFactory
        • 3.1.1.3 ListableBeanFactory
        • 3.1.1.4 AutowireCapableBeanFactory
        • 3.1.1.5 ConfigurableBeanFactory
        • 3.1.1.6 AbstractBeanFactory
        • 3.1.1.7 AbstractAutowireCapableBeanFactory
        • 3.1.1.8 DefaultListableBeanFactory
        • 3.1.1.9 总结

3 SpringBoot的IOC容器

第2章梳理的是SpringBoot的自动装配机制,无论是原生的装配,还是自动装配,最终组件都会装配到IOC容器中。
第3章梳理SpringFramework的IOC容器设计,以及SpringBoot对其的利用与拓展。

3.1 SpringFramework的IOC容器

关于SpringFramework的IOC容器,我们首先想到的应该是ApplicationContext或者BeanFactory。在SpringFramework的官方文档中,有一个片段解释了ApplicationContext和BeanFactory的关系。

The org.springframework.beansand org.springframework.contextpackages are the basis for Spring Framework’s IoC container. The BeanFactoryinterface provides an advanced configuration mechanism capable of managing any type of object. ApplicationContextis a sub-interface of BeanFactory. It adds:

  • Easier integration with Spring’s AOP features
  • Message resource handling (for use in internationalization)
  • Event publication
  • Application-layer specific contexts such as the WebApplicationContextfor use in web applications.

意思是,SpringFramework的org.springframework.beans和org.springframework.context包是IOC容器的基础。BeanFactory接口提供了一种高级配置机制,能够管理任何类型的对象。ApplicationContext是BeanFactory的子接口,它增加以下几个特性:

  • 与SpringFramework的AOP功能轻松集成;
  • 消息资源处理(用于国际化);
  • 事件发布;
  • 应用层特定的上下文,例如Web应用程序中使用的WebApplicationContext。

总结:BeanFactory是IOC容器的基础抽象,ApplicationContext包含BeanFactory的所有功能,且扩展了更多实用特性。

3.1.1 BeanFactory

BeanFactory是IOC容器的顶层抽象,它仅定义最基础的bean对象的管理。借助IDEA可以生成BeanFactory及其派生接口的继承结构,如图:

BeanFactory及其子接口

3.1.1.1 BeanFactory根接口

The root interface for accessing a Spring bean container.
This is the basic client view of a bean container; further interfaces such as ListableBeanFactoryand org.springframework.beans.factory.config.ConfigurableBeanFactoryare available for specific purposes.

第一段:描述了BeanFactory是一个根接口。
BeanFactory是一个访问SpringFramework的Bean容器的根接口。这是Bean容器的基本客户端视图;扩展的接口(例如ListableBeanFactory和org.springframework.beans.factory.config.ConfigurableBeanFactory)都是为了实现某些额外的特性。

This interface is implemented by objects that hold a number of bean definitions, each uniquely identified by a String name. Depending on the bean definition, the factory will return either an independent instance of a contained object (the Prototype design pattern), or a single shared instance (a superior alternative to the Singleton design pattern, in which the instance is a singleton in the scope of the factory). Which type of instance will be returned depends on the bean factory configuration: the API is the same. Since Spring 2.0, further scopes are available depending on the concrete application context (e.g. “request” and “session” scopes in a web environment).

第二段:描述了BeanFactory中定义的作用域概念。
BeanFactory接口由多个对象实现,这些对象包含多个bean定义(即BeanDefinition),而每一项定义信息均由字符串类型的name进行唯一标识。根据bean对象的定义信息,SpringFramework的工厂会返回一个包含对象的独立实例(原型设计模式),或者返回一个单个共享示例(单例设计模式的一个更高级的替代方法,其中实例是工厂作用域中的单例)。返回bean对象的实例类型取决于bean对象工厂的配置:API是相同的。自SpringFramework2.0以后,根据具体的ApplicationContext可以使用更多的作用域(例如Web环境中的"request"和"session"作用域)。

从这一段的描述可以发现,Bean容器中的实例要么是单例bean,要么是原型bean。返回的实例类型取决于Bean对象工厂的配置:API是相同的。怎么理解“API是相同的”?

在定义Bean的时候,使用@Scope注解来定义作用域:

@Component
@Scope("prototype") // 或者 singleton
public class Person {
    @Bean
    @Scope("singleton")
    public Person a() {
        return new Person();
    }
}

上面两种方式注入Bean,显式声明作用域,都是用@Scope。意思就是,产生单例Bean和原型Bean所用的API是相同的,都是用@Scope注解来声明,然后由BeanFactory来创建。

The point of this approach is that the BeanFactory is a central registry of application components, and centralizes configuration of application components (no more do individual objects need to read properties files, for example). See chapters 4 and 11 of “Expert One-on-One J2EE Design and Development” for a discussion of the benefits of this approach.

第三段:描述了BeanFactory与环境配置的继承。
这种方法的要点在于,BeanFactory是应用程序组件的注册中心,并集中应用程序组件的配置(例如,单个对象不再需要读取属性文件)。

Note that it is generally better to rely on Dependency Injection (“push” configuration) to configure application objects through setters or constructors, rather than use any form of “pull” configuration like a BeanFactory lookup. Spring’s Dependency Injection functionality is implemented using this BeanFactory interface and its subinterfaces.

第四段:描述了SpringFramework在IOC的两种实现上的权衡:推荐使用依赖注入(DI),尽可能避免依赖查找(DL)。
通常最好使用依赖注入(“推”的配置),通过setter方法或构造方法注入的方式配置应用程序对象,而不是用任何形式的“拉”的配置,例如借助BeanFactory进行依赖查找。SpringFramework的依赖注入特性是使用BeanFactory接口及其子接口实现的。

依赖注入的思想是“推”,主张把组件所需的依赖“推”到组件的成员上;
依赖查找的思想是“拉”,组件需要哪些依赖需要组件自己去IOC容器中“拉取”。

Normally a BeanFactory will load bean definitions stored in a configuration source (such as an XML document), and use the org.springframework.beanspackage to configure the beans. However, an implementation could simply return Java objects it creates as necessary directly in Java code. There are no constraints on how the definitions could be stored: LDAP, RDBMS, XML, properties file, etc. Implementations are encouraged to support references amongst beans (Dependency Injection).

第五段:描述了BeanFactory支持多种类型的Bean配置源。
通常,BeanFactory会加载存储在配置源(例如XML配置文件)中的Bean定义,并使用org.springframework.beans包中的API来配置Bean。然而,BeanFactory的实现可以根据需要直接在Java代码中返回它创建的Java对象。Bean定义的存储方式没有任何限制,它可以是LDAP(轻型目录访问协议)、RDBMS(关系型数据库系统)、XML、properties文件等。鼓励的实现方式是支持Bean之间的引用(依赖注入)。

注意,LDAP, RDBMS并不常用,常用的方式包括XML配置文件、注解配置类、模式注解+组件扫描。

In contrast to the methods in ListableBeanFactory, all of the operations in this interface will also check parent factories if this is a HierarchicalBeanFactory. If a bean is not found in this factory instance, the immediate parent factory will be asked. Beans in this factory instance are supposed to override beans of the same name in any parent factory.

第六段:描述了BeanFactory可实现层次性。
与ListableBeanFactory中的方法相比,BeanFactory中的所有操作还将检查父级工厂(BeanFactory本身可以支持父子结构,这个父子结构的概念和实现由HierarchicalBeanFactory完成)。如果在BeanFactory实例中没有找到指定的bean对象,则会在父工厂中搜索查找。BeanFactory实例中的Bean应该覆盖任何父工厂中的同名Bean。

Bean factory implementations should support the standard bean lifecycle interfaces as far as possible. The full set of initialization methods and their standard order is:

  • BeanNameAware’s setBeanName
  • BeanClassLoaderAware’s setBeanClassLoader

    On shutdown of a bean factory, the following lifecycle methods apply:
  • postProcessBeforeDestructionmethods of DestructionAwareBeanPostProcessors
  • DisposableBean’s destroy
  • a custom destroy-method definition

第七段:描述了BeanFactory设有完整的生命周期控制机制。
BeanFactory接口实现了尽可能支持标准Bean的生命周期接口。初始化方法的完整集合及其标准顺序为:

  • BeanNameAware接口的setBeanName方法
  • BeanClassLoaderAware接口的setBeanClassLoader方法

在关闭BeanFactory时,应用以下生命周期方法:

  • DestructionAwareBeanPostProcessors的postProcessBeforeDestruction方法
  • DisposableBean的destroy方法
  • 自定义的destroy方法

总结:BeanFactory的基础特性包括:

  • 最基本的根接口容器
  • 定义了作用域的概念;
  • 推荐使用依赖注入,尽可能避免以来查找;
  • 支持多种类型的配置源;
  • 层次性设计;
  • 完成的生命周期控制机制。
3.1.1.2 HierarchicalBeanFactory

HierarchicalBeanFactory是一个体现了层次性的BeanFactory。

Sub-interface implemented by bean factories that can be part of a hierarchy. The corresponding setParentBeanFactorymethod for bean factories that allow setting the parent in a configurable fashion can be found in the ConfigurableBeanFactoryinterface.

HierarchicalBeanFactory是BeanFactory的子接口,实现了这个接口的IOC容器具有层次性。可以在ConfigurableBeanFactory接口中找到允许以可配置方式设置父节点的Bean工厂的相应方法setParentBeanFactory。

当调用BeanFactory的getBean方法时,如果这个BeanFactory是具有层次性的Bean,getBean方法会从当前BeanFactory开始查找是否存在指定的Bean,如果找不到就依次向上查找父级BeanFactory,直到找到为止返回,或者最终找不到而抛出NoSuchBeanDefinitionException。

如果当前BeanFactory有指定的Bean,父级BeanFactory也可能还有Bean。因为即便存在父子关系,它们本质上也是不同的容器。因此有可能找到多个相同的Bean。换言之,@Scope中声明singleton只是在单独某一个容器中是单实例的,但有了层次性结构后,对于整体的多个容器就不是单实例的了。

3.1.1.3 ListableBeanFactory

ListableBeanFactory是一个可列举的BeanFactory。实现了ListableBeanFactory的IOC容器,可以将容器中所有的bean对象都列举出来。

Extension of the BeanFactoryinterface to be implemented by bean factories that can enumerate all their bean instances, rather than attempting bean lookup by name one by one as requested by clients. BeanFactoryimplementations that preload all their bean definitions (such as XML-based factories) may implement this interface.

第一段:ListableBeanFactory是BeanFactory接口的扩展实现,它可以枚举所有的Bean实例,而不是向客户端请求那样逐个按名称进行Bean查找。预加载所有Bean定义(例如基于XML的工厂)的BeanFactory实现类可以实现这个接口。

If this is a HierarchicalBeanFactory, the return values will not take any BeanFactory hierarchy into account, but will relate only to the beans defined in the current factory. Use the BeanFactoryUtilshelper class to consider beans in ancestor factories too.

第二段:如果当前BeanFactory同时也是一个HierarchicalBeanFactory,则返回值将不考虑任何BeanFactory的层次结构,而只与当前工厂中定义的Bean有关。使用BeanFactoryUtils工具类也可以获取祖先工厂中的bean。

也就是说,ListableBeanFactory只会列举当前容器中的bean对象,而不会列举父级容器中的bean对象。如果想要获取,可以使用BeanFactoryUtils工具类。

The methods in this interface will just respect bean definitions of this factory. They will ignore any singleton beans that have been registered by other means like org.springframework.beans.factory.config.ConfigurableBeanFactory’s registerSingleton method, with the exception of getBeanNamesForType and getBeansOfType which will check such manually registered singletons too. Of course, BeanFactory’s getBean does allow transparent access to such special beans as well. However, in typical scenarios, all beans will be defined by external bean definitions anyway, so most applications don’t need to worry about this differentiation.

第三段:ListableBeanFactory接口的方法将仅遵循当前工厂的Bean定义,它们会忽略通过其他方式(例如ConfigurableBeanFactory的registerSingleton方法)注册的任何单实例Bean,但getBeanNamesForType和getBeansOfType除外,它们也会检查这种手动注册的单实例Bean。当然,BeanFactory的getBean也允许对这种特殊bean进行特殊访问。然而,在典型的场景中,所有bean将由外部Bean定义进行定义,因此大多数应用程序不需要担心这种差异。

本段强调了ListableBeanFactory会有选择性地列举容器内的bean,有些bean对象在列举期间会被忽略。为什么要这样设计呢?来看一个例子:

(1)定义两个简单类:猫和狗

public class Cat {}
public class Dog {}

(2)编写XML文件将Cat注册到IOC容器

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean class="com.star.springboot.test02.Cat"/>
</beans>

(3)使用XML配置文件加载ListableBeanFactory

public class ListableBeanFactoryApp {

    public static void main(String[] args) {
        ClassPathResource resource = new ClassPathResource("listable.xml");
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
        beanDefinitionReader.loadBeanDefinitions(resource);
        System.out.println("加载XML文件后容器中的Bean如下:");
        Stream.of(beanFactory.getBeanDefinitionNames()).forEach(System.out::println);
    }
    
}

输出结果显示,只有一个Cat对象:

加载XML文件后容器中的Bean如下:
com.star.springboot.test02.Cat#0

(4)手动注册一个单实例Dog

public class ListableBeanFactoryApp {

    public static void main(String[] args) {
        ClassPathResource resource = new ClassPathResource("listable.xml");
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
        beanDefinitionReader.loadBeanDefinitions(resource);
        System.out.println("加载XML文件后容器中的Bean如下:");
        Stream.of(beanFactory.getBeanDefinitionNames()).forEach(System.out::println);

        // 手动注册一个单实例Dog
        beanFactory.registerSingleton("doggggg", new Dog());
        // 再次打印
        System.out.println("手动注册单实例Bean后容器中的Bean如下:");
        Stream.of(beanFactory.getBeanDefinitionNames()).forEach(System.out::println);
    }

}

输出结果显示,依旧只有一个Cat对象:

加载XML文件后容器中的Bean如下:
com.star.springboot.test02.Cat#0
手动注册单实例Bean后容器中的Bean如下:
com.star.springboot.test02.Cat#0

(5)分析
这个结果似乎和预期不符,但印证了javadoc中的说明:ListableBeanFactory在获取容器内的所有bean对象时,不会把手动注册(即使用registerSingleton方法)的bean对象取出。

但容器中肯定是有Dog对象的,通过getBean方法就可以获取:

Dog dog = beanFactory.getBean(Dog.class);
System.out.println("通过getBean方法获取Dog结果:" + dog);

输出结果:

通过getBean方法获取Dog结果:com.star.springboot.test02.Dog@1efbd816

那SpringFramework这样设计的目的是什么?查看AbstractApplicationContext中prepareBeanFactory方法,可以发现使用了registerSingleton:

// Register default environment beans.
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());
}

此处使用registerSingleton方法注册了几个仅供SpringFramework内部使用的默认组件。
由此可以看出,这样设计的目的就是为了隐藏这些内部组件,而不希望开发者直接操作它们。
类似于Windows操作系统中的“隐藏受保护的操作系统文件”,这些文件用户默认是看不见的,避免用户误删。

3.1.1.4 AutowireCapableBeanFactory

AutowireCapableBeanFactory直译过来是“具有自动装配能力的BeanFactory”。可见AutowireCapableBeanFactory支持自动注入或依赖注入。

Extension of the org.springframework.beans.factory.BeanFactoryinterface to be implemented by bean factories that are capable of autowiring, provided that they want to expose this functionality for existing bean instances.

第一段:AutowireCapableBeanFactory是BeanFactory接口的扩展,由能够进行自动注入的Bean工厂实现,前提是它们希望为现有的bean实例暴露此功能。

This subinterface of BeanFactory is not meant to be used in normal application code: stick to org.springframework.beans.factory.BeanFactoryor org.springframework.beans.factory.ListableBeanFactoryfor typical use cases.

第二段:BeanFactory的这个子接口并不是用在普通的应用程序代码中的,而是在BeanFactory或者ListableBeanFactory中用于典型用例。

Integration code for other frameworks can leverage this interface to wire and populate existing bean instances that Spring does not control the lifecycle of. This is particularly useful for WebWork Actions and Tapestry Page objects, for example.

第三段:其他框架的集成代码可以利用这个接口来连接和填充SpringFramework无法控制生命周期的现有bean实例。例如,这对于WebWork动作和Tapestry页面对象特别有用。

直接阅读上面三段javadoc还是挺费解的,它要表达的意思是:

AutowireCapableBeanFactory支持组件的自动注入,可以为一些现有的、没有被SpringFramework统一管理的Bean提供组件自动注入的支持。一般在正常的项目开发中不会用到AutowireCapableBeanFactory,而是在第三方框架与SpringFramework整合时才可能会用到。如果第三方框架的某些bean实例无法让SpringFramework接管,但又需要注入一些由SpringFramework管理的bean对象,就可以使用AutowireCapableBeanFactory辅助完成注入。

Note that this interface is not implemented by org.springframework.context.ApplicationContextfacades, as it is hardly ever used by application code. That said, it is available from an application context too, accessible through ApplicationContext’s org.springframework.context.ApplicationContext#getAutowireCapableBeanFactory()method.

注意,ApplicationContext没有实现AutowireCapableBeanFactory接口,因为它几乎不被应用程序代码所使用。也就是说,它可以从应用程序上下文中获取到,通过ApplicationContext的getAutowireCapableBeanFactory方法访问。

总结:AutowireCapableBeanFactory在正常的项目开发中一般不会使用,不需要我们去操作。但如果需要获取AutowireCapableBeanFactory,可以通过ApplicationContext间接获取。

3.1.1.5 ConfigurableBeanFactory

SpringFramework对于核心API的命名有非常强的规律性。当类名中带有 Configurable 前缀时,意味着这个接口的行为有“写”的动作,而去掉 Configurable 前缀的接口只有“读”的动作。

  • 可读:一个类的属性设置为private后,提供get方法
  • 可写:一个类的属性设置为private后,提供set方法

SpringFramework中,普通的BeanFactory只有get相关操作,而 Configurable 前缀的BeanFactory或者ApplicationContext具有set相关操作。

Configuration interface to be implemented by most bean factories. Provides facilities to configure a bean factory, in addition to the bean factory client methods in the org.springframework.beans.factory.BeanFactoryinterface.

第一段:这是大多数BeanFactory都要实现的配置接口。它提供配置BeanFactory的工具,以及BeanFactory接口中的客户端方法。

This bean factory interface is not meant to be used in normal application code: Stick to org.springframework.beans.factory.BeanFactoryor org.springframework.beans.factory.ListableBeanFactoryfor typical needs. This extended interface is just meant to allow for framework-internal plug’n’play and for special access to bean factory configuration methods.

第二段:这个接口并不是用在普通的应用程序代码中的,而是在BeanFactory或者ListableBeanFactory中用于典型用例。这个扩展的接口只是为了支持内部的即插即用,以及对BeanFactory配置方法的特殊访问。

总结:ConfigurableBeanFactory提供了配置功能,可以对BeanFactory进行修改、扩展。但官方不希望开发者使用这个接口,因为原则上程序在运行期间不应该对BeanFactory再进行频繁的变动,只应该有读的动作(除非确定要写且有把握,才写)。

3.1.1.6 AbstractBeanFactory

AbstractBeanFactory是BeanFactory最基础的抽象实现,只具有部分功能。

Abstract base class for org.springframework.beans.factory.BeanFactoryimplementations, providing the full capabilities of the org.springframework.beans.factory.config.ConfigurableBeanFactorySPI. Does not assume a listable bean factory: can therefore also be used as base class for bean factory implementations which obtain bean definitions from some backend resource (where bean definition access is an expensive operation).

第一段:AbstractBeanFactory是BeanFactory接口的抽象基类,提供了ConfigurableBeanFactory类SPI的全部能力。可以被用作从某些后端资源获取Bean定义的基类。

This class provides a singleton cache (through its base class org.springframework.beans.factory.support.DefaultSingletonBeanRegistry), singleton/prototype determination, org.springframework.beans.factory.FactoryBeanhandling, aliases, bean definition merging for child bean definitions, and bean destruction (org.springframework.beans.factory.DisposableBeaninterface, custom destroy methods). Furthermore, it can manage a bean factory hierarchy (delegating to the parent in case of an unknown bean), through implementing the org.springframework.beans.factory.HierarchicalBeanFactoryinterface.

第二段:AbstractBeanFactory可以提供一个单实例缓存(通过它的父类DefaultSingletonBeanRegistry)、单例/原型Bean的裁定、FactoryBean处理、别名存储、用于子Bean定义的Bean定义合并,以及Bean销毁(用DisposableBean接口或自定义的destroy方法)。此外,AbstractBeanFactory可以通过实现HierarchicalBeanFactory接口来管理BeanFactory的层次性结构(在未知Bean的情况下委托给父级工厂)。

The main template methods to be implemented by subclasses are getBeanDefinitionand createBean, retrieving a bean definition for a given bean name and creating a bean instance for a given bean definition, respectively. Default implementations of those operations can be found in DefaultListableBeanFactoryand AbstractAutowireCapableBeanFactory.

第三段:由子类实现的主要模板方法是getBeanDefinition和createBean,分别代表根据给定的Bean名称获取Bean定义,和根据给定的Bean定义创建Bean对象。这些操作的默认实现可以在DefaultListableBeanFactory和AbstractAutowireCapableBeanFactory中找到。

总结:AbstractBeanFactory是BeanFactory接口的抽象基类,具有一些基础功能,使用模板方法模式对getBeanDefinition和createBean方法做了规范定义。

3.1.1.7 AbstractAutowireCapableBeanFactory

Abstract bean factory superclass that implements default bean creation, with the full capabilities specified by the RootBeanDefinitionclass. Implements the org.springframework.beans.factory.config.AutowireCapableBeanFactoryinterface in addition to AbstractBeanFactory’s createBeanmethod.

第一段:AbstractAutowireCapableBeanFactory是实现了默认的bean对象创建逻辑的BeanFactory接口的抽象类,具有RootBeanDefinition类指定的完整功能。它除了实现AbstractBeanFactory的createBean方法,还额外实现了AutowireCapableBeanFactory接口的方法。

也就是说,bean对象的创建动作都在AbstractAutowireCapableBeanFactory中完成

Provides bean creation (with constructor resolution), property population, wiring (including autowiring), and initialization. Handles runtime bean references, resolves managed collections, calls initialization methods, etc. Supports autowiring constructors, properties by name, and properties by type.

第二段:AbstractAutowireCapableBeanFactory的核心功能包括:bean对象的创建(带有构造函数解析)、属性赋值、依赖注入(包括自动注入)、以及初始化。处理运行时Bean引用,解析托管集合,调用初始化方法等。支持自动装配构造函数,按名称设置属性和按类型设置属性。

The main template method to be implemented by subclasses is resolveDependency(DependencyDescriptor, String, Set, TypeConverter), used for autowiring by type. In case of a factory which is capable of searching its bean definitions, matching beans will typically be implemented through such a search. For other factory styles, simplified matching algorithms can be implemented.

第三段:AbstractAutowireCapableBeanFactory实现的主要的模板方法是resolveDependency,用于根据类型进行自动注入。对于能够获取其Bean定义信息的BeanFactory,通常通过这种查询来实现。对于其他样式的BeanFactory,可以实现简化的匹配算法。

Note that this class does not assume or implement bean definition registry capabilities. See DefaultListableBeanFactoryfor an implementation of the org.springframework.beans.factory.ListableBeanFactoryand BeanDefinitionRegistryinterfaces, which represent the API and SPI view of such a factory, respectively.

第四段:注意,AbstractAutowireCapableBeanFactory没有假定或实现Bean定义信息注册的能力。请参阅DefaultListableBeanFactory获取ListableBeanFactory和BeanDefinitionRegistry接口的实现,它们分别代表了这种工厂的API和SPI视图。

总结:AbstractAutowireCapableBeanFactory实现了对Bean的创建、赋值、注入和初始化的逻辑,但对于Bean的定义信息是如何进入BeanFactory的没有涉及。

3.1.1.8 DefaultListableBeanFactory

DefaultListableBeanFactory是唯一目前底层正在使用的BeanFactory的落地实现。

Spring’s default implementation of the ConfigurableListableBeanFactoryand BeanDefinitionRegistryinterfaces: a full-fledged bean factory based on bean definition metadata, extensible through post-processors.

第一段:DefaultListableBeanFactory是ConfigurableListableBeanFactory和BeanDefinitionRegistry接口的默认实现:一个基于Bean定义信息元数据的成熟的BeanFactory,可以通过后处理器进行拓展。

Typical usage is registering all bean definitions first (possibly read from a bean definition file), before accessing beans. Bean lookup by name is therefore an inexpensive operation in a local bean definition table, operating on pre-resolved bean definition metadata objects.

第二段:典型的用法是在访问bean对象之前先注册所有Bean定义信息(可能从Bean定义文件中读取)。因此,在本地Bean定义表中,按名称查找是一个开销不大的操作,它操作在预先解析的Bean定义元数据对象上。

Note that readers for specific bean definition formats are typically implemented separately rather than as bean factory subclasses: see for example org.springframework.beans.factory.xml.XmlBeanDefinitionReader.

第三段:注意,特定的Bean定义信息格式的解析器通常是单独实现的,而不是作为BeanFactory的子类,参见XmlBeanDefinitionReader。

For an alternative implementation of the org.springframework.beans.factory.ListableBeanFactoryinterface, have a look at StaticListableBeanFactory, which manages existing bean instances rather than creating new ones based on bean definitions.

第四段:对于ListableBeanFactory的替代实现,参见StaticListableBeanFactory,这个类管理着现有的bean实例,而不是根据Bean定义信息创建新实例。

总结:DefaultListableBeanFactory的源码中已经没有abstract关键字的标注,说明它是一个成熟的落地实现类,在AbstractAutowireCapableBeanFactory的基础上完成注册Bean定义信息的动作。

3.1.1.9 总结

至此,可以总结一下BeanFactory的功能:

BeanFactory及其子接口
BeanFactory是一个统一管理Bean组件的容器,它的核心工作是控制Bean在创建阶段的声明周期与bean对象的统一管理,而对于Bean从哪里来、如何被创建、有哪些依赖要注入、这些都与BeanFactory无关,而是有专门的组件来处理。

  • HierarchicalBeanFactory :BeanFactory的层次性
  • ListableBeanFactory :可列举Bean
  • AutowireCapableBeanFactory :自动注入一些现有的、没有被SpringFramework统一管理的Bean
  • ConfigurableBeanFactory :对BeanFactory进行修改、扩展
  • AbstractBeanFactory :对getBeanDefinition和createBean方法做了规范定义
  • AbstractAutowireCapableBeanFactory :对Bean的创建、赋值、注入和初始化的逻辑
  • DefaultListableBeanFactory :注册Bean定义信息

本节完,更多内容请查阅分类专栏:SpringBoot源码解读与原理分析

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/381812.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ctfshow-命令执行(web118-web122)

web118 是一个窗口 查看源码 发现是system($code) 命令执行 经过测试禁用了很多东西 很多很多 $IFS可以 思路就是使用系统变量 构造我需要的poc 这些都是系统的环境变量 这是答案${PATH:~A}${PWD:~A}$IFS????.??? 解释一下 PATH变量输出结尾一般都是n 因为网站默认根目…

setState的参数

目录 1、setState的第一个参数 2、setState的第二个参数 3、在 React 底层主要做了那些事呢&#xff1f; 4、类组件如何限制 state 更新视图 React 项目中的 UI 的改变来源于 State 改变&#xff0c;类组件中 setState 是更新组件&#xff0c;渲染视图的 1、setState的第一个参…

中文GPTS,字节中文扣子Coze使用全教程

字节出自己的GPTS了&#xff0c;名字英文名叫coze&#xff0c;中文名叫“扣子”。和OpenAI的GPTS类似。具有可定制性和完成特定任务的强大功能&#xff0c;它提供了一种新的GPT方式&#xff0c;可以让用户根据自己的需求定制化&#xff0c;并与其他用户共享。 国内用的是云雀大…

Python数据可视化库之mplfinance使用详解

概要 Python 是一种强大的编程语言,拥有众多用于数据可视化的库和工具。其中之一是 mplfinance(Matplotlib Finance),它是基于 Matplotlib 的库,专门用于创建金融图表和交互式金融数据可视化。本文将深入介绍 mplfinance,包括其基本概念、功能特性以及如何使用示例代码创…

Java 内存区域介绍

&#xff08;1&#xff09;程序计数器 程序计数器主要有两个作用&#xff1a; 字节码解释器通过改变程序计数器来依次读取指令&#xff0c;从而实现代码的流程控制&#xff0c;如&#xff1a;顺序执行、选择、循环、异常处理。 在多线程的情况下&#xff0c;程序计数器用于记录…

每日一练:LeeCode-106、从中序与后序遍历序列构造⼆叉树、LeeCode-106、从前序与中序遍历序列构造二叉树【二叉树+DFS+分治】

本文是力扣LeeCode-106、从中序与后序遍历序列构造二叉树 LeeCode-105、从前序与中序遍历序列构造二叉树 学习与理解过程&#xff0c;本文仅做学习之用&#xff0c;对本题感兴趣的小伙伴可以出门左拐LeeCode。 106、从中序与后序遍历序列构造⼆叉树 给定两个整数数组 inorder…

【JavaScript 】finally() 方法和Filter() 方法

JavaScript 中的finally() 方法 finally是 JavaScript 构造中使用的方法try-catch。try它在and阻塞之后执行catch&#xff0c;无论 Promise 是已履行还是已拒绝。该函数的主要作用是执行必要的清理任务并向用户传达消息。一个常见的用例可能是通知用户“您的请求已被处理”&am…

C# OpenVino Yolov8 Pose

目录 效果 模型信息 项目 代码 下载 效果 模型信息 Model Properties ------------------------- date&#xff1a;2023-09-07T17:11:43.091306 description&#xff1a;Ultralytics YOLOv8n-pose model trained on /usr/src/app/ultralytics/datasets/coco-pose.yaml a…

93 log4j-slf4j-impl 搭配上 log4j-to-slf4j 导致的 StackOverflow

前言 呵呵 最近想要 做一个 mongo 低版本的客户端读取高版本的服务端传递过来的数据造成的一个错误的时候, 出现了这样的问题 引入了 mongo-java-driver 之后, 使用相关 api 的时候会触发 com.mongo.internal.connection.BaseCluser 的初始化, 其依赖的 Loggers 间接的依赖…

MyBatisPlus之分页查询及Service接口运用

一、分页查询 1.1 基本分页查询 配置分页查询拦截器 package com.fox.mp.config;import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; import org.springfra…

分享86个表单按钮JS特效,总有一款适合您

分享86个表单按钮JS特效&#xff0c;总有一款适合您 86个表单按钮JS特效下载链接&#xff1a;https://pan.baidu.com/s/1WwQGFPWv8464JBcuEMJZ_Q?pwd8888 提取码&#xff1a;8888 Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 学习知识费力气&#xff0c;…

SpringBoot3整合Mybatis-Plus,自定义动态数据源starter

文章目录 前言正文一、项目总览二、核心代码展示2.1 自定义AbstractRoutingDataSource2.2 动态数据源DynamicDataSource2.3 动态数据源自动配置2.4 动态数据源上下文DynamicDataSourceContextHolder2.5 动态数据源修改注解定义2.6 修改切面DynamicDataSourceAspect2.7 动态数据…

嵌入式系统的前景:未来智能汽车

&#xff08;本文为简单介绍&#xff0c;个人的观点仅供参考&#xff09; 智能汽车时代已经来临!未来十年,我们的汽车将变得越来越智能化。各大汽车公司在研发自动驾驶技术,目标是实现真正的无人驾驶。要实现这一目标,嵌入式系统将发挥关键作用。 简单来说,嵌入式系统就是在汽…

【Linux】指令提权-sudo

Hello everybody&#xff0c;新年快乐&#xff01;哈哈&#xff01;今天打算给大家讲讲指令提权的相关知识&#xff0c;虽然内容不多&#xff0c;但有时却很有用。在我们学习过权限&#xff0c;vim后就可以学习指令提权啦&#xff0c;没看过的宝子们建议先去看一看我之前的文章…

旅游|基于Springboot的旅游管理系统设计与实现(源码+数据库+文档)

旅游管理系统目录 目录 基于Springboot的旅游管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、用户管理 2、景点分类管理 3、景点信息管理 4、酒店信息管理 5、景点信息 6、游记分享管理 四、数据库设计 1、实体ER图 2、具体的表设计如下所示&#xf…

工业级加固平板丨亿道三防平板电脑丨安卓工业平板丨改善车队管理

在现代物流和运输行业中&#xff0c;车队管理是一个复杂而重要的任务。为了更好地管理车队&#xff0c;提高工作效率和减少成本&#xff0c;许多企业正在采用新技术和工具。其中&#xff0c;三防平板电脑作为一种功能强大且适应恶劣环境的设备&#xff0c;已经在车队管理中得到…

【九章斩题录】Leetcode:判定是否互为字符重排(C/C++)

面试题 01.02. 判定是否互为字符重排 ✅ 模板&#xff1a;C class Solution { public:bool CheckPermutation(string s1, string s2) {} }; 「 法一 」排序 &#x1f4a1; 思路&#xff1a;看到题目中说 "重新排列后能否变成另一个字符串"&#xff0c;等等……重新…

第三百一十七回

文章目录 1. 概念介绍2. 实现方法2.1 hintText2.2 labelText2.3 controller 3. 示例代码4. 内容总结 我们在上一章回中介绍了"如何在输入框中处理光标"相关的内容&#xff0c;本章回中将介绍如何添加输入框默认值.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1.…

[VulnHub靶机渗透] Misdirection: 1

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【python】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收藏…

Linux操作系统基础(八):Linux的vi/vim编辑器

文章目录 Linux的vi/vim编辑器 一、vi/vim编辑器介绍 二、打开文件 三、VIM编辑器的三种模式(重点) 四、命令模式相关命令 五、底行模式相关命令 Linux的vi/vim编辑器 一、vi/vim编辑器介绍 vi是visual interface的简称, 是Linux中最经典的文本编辑器 vi的核心设计思想…
最新文章