• Spring - 从官方文档中认识 IoC 容器


    IoC 容器:Spring’s Inversion of Control (IoC) container

    Spring 的核心功能是 IoC 容器spring-beansspring-context 这两个库是 Spring IoC 容器的基础。
    spring-core 是 Spring 的核心库,其他所有的 Spring 家族的库都会依赖 spring-core


    BeanFactory

    什么是 Bean:由 Spring IoC 容器管理的对象叫做 BeanBean 是由 Spring IoC 容器 实例化、组装、管理 的对象;否则的话 Bean 只是应用中的一个普通对象。Bean 及其之间的依赖关系反映在容器使用的配置元数据中。

    Spring 官方文档 中有介绍:BeanFactory 接口提供了一种高级的配置机制,能够管理任何类型的对象。

    ApplicationContext

    ApplicationContextBeanFactory 的子接口,添加了更多功能:

    • Easier integration with Spring’s AOP features(更容易与 Spring AOP 特性集成)
    • Message resource handling (for use in internationalization)(消息资源处理(国际化))
    • Event publication(事件发布)
    • Application-layer specific contexts such as the WebApplicationContext for use in web applications.(应用层特定的上下文,例如用于 web 应用的 WebApplicationContext)
    public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
    		MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
    }
    
    • 1
    • 2
    • 3

    BeanFactory 提供了配置框架和基本功能,ApplicationContext 添加了更多企业级的功能,是前者的超集。

    在这里插入图片描述

    配置 IoC 容器 的元数据

    一个类是如何加入到 IoC 容器 中的呢,换句话说:IoC 容器 是怎么识别一个类是普通类还是 Bean 呢?

    传统的方式是使用 xml 配置文件(还可以使用 Java 注解 或 Java 代码)来声明各种 元数据(声明为 Bean 及其之间的依赖关系),之后在 IoC 容器创建并初始化的时候,会读取配置的 元数据 来 初始化、配置、装配 这些 Bean

    在 web 应用程序中,我们通常会 在 web.xml 中配置 IoC 容器的加载器(org.springframework.web.context.ContextLoaderListener)来实例化 ApplicationContext

    初始化 IoC 容器

    Spring 提供了几种 ApplicationContext 的几种实现:

    ConfigurableApplicationContext

    public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable {}
    
    • 1

    ConfigurableApplicationContext 作为 ApplicationContext 的派生接口,定义了一些非通用的方法。符合面向对象的7大设计原则之一的接口隔离原则。

    注意:这里定义的 refresh 方法,不支持多次调用。实现类中的这个方法自然也不支持多次调用,但是 AbstractRefreshableApplicationContext 中提供了多次调用的方法。

    在这里插入图片描述

    AbstractApplicationContext

    public abstract class AbstractApplicationContext extends DefaultResourceLoader
    		implements ConfigurableApplicationContext {}
    
    • 1
    • 2

    ConfigurableApplicationContext 接口的抽象实现类。

    其中的 refresh 方法,是 IoC 容器启动的骨架实现,使用了 模板设计模式。提供对 ConfigurableApplicationContext 接口的 refresh 方法的模板实现,即:定义了 ApplicationContext 的启动步骤,但是不提供具体每一步的实现,由子类实现。

    在这里插入图片描述
    比如其中的 postProcessBeanFactory 方法:

    protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    	}
    
    • 1
    • 2

    AbstractRefreshableApplicationContext

    public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {
    	@Nullable
    	// 允许重复Bean定义覆盖
    	private Boolean allowBeanDefinitionOverriding;
    
    	@Nullable
    	// 允许循环引用
    	private Boolean allowCircularReferences;
    	
    	...
    	@Override
    	protected final void refreshBeanFactory() throws BeansException {
    		if (hasBeanFactory()) {
    			destroyBeans();
    			closeBeanFactory();
    		}
    		try {
    			DefaultListableBeanFactory beanFactory = createBeanFactory();
    			beanFactory.setSerializationId(getId());
    			customizeBeanFactory(beanFactory);
    			loadBeanDefinitions(beanFactory);
    			this.beanFactory = beanFactory;
    		}
    		catch (IOException ex) {
    			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    		}
    	}
    	...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    继承 AbstractApplicationContext 抽象类,主要提供可多次重复调用 refresh 方法,刷新容器,销毁之前的 BeanFactoryBeans,重新创建。ConfigurableApplicationContext 接口的定义,默认是不支持多次调用 refresh 方法的,多次调用则抛 IllegalStateException 异常。

    AbstractRefreshableConfigApplicationContext

    public abstract class AbstractRefreshableConfigApplicationContext extends AbstractRefreshableApplicationContext
    		implements BeanNameAware, InitializingBean {
    
    	@Nullable
    	private String[] configLocations;
    	...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    继承 AbstractRefreshableApplicationContext 抽象类,主要作用是定义数组类型的 configLocations 变量,用于加载多个 xml 文件来配置 IoC 容器。

    AbstractXmlApplicationContext

    public abstract class AbstractXmlApplicationContext extends AbstractRefreshableConfigApplicationContext {}
    
    • 1

    继承 AbstractRefreshableConfigApplicationContext,指定使用 xml 文件保存配置,有两个实现类:

    • ClassPathXmlApplicationContext:指定从类路径下加载 xml 配置文件
    • FileSystemXmlApplicationContext:指定从文件系统加载 xml 配置文件
    // 通过加载类路径下的 xml 配置文件创建并初始化 IoC 容器
    ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("services.xml");
    // 获取 IoC 容器中定义的 Beans 的 name
    String[] beanNames = applicationContext.getBeanDefinitionNames();
    for (String beanName : beanNames) {
        System.out.println(beanName);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    GenericApplicationContext

    public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {}
    
    • 1

    继承 AbstractApplicationContext,故不具备上面的 Config,Refreshable 功能。而 Bean 的注册,是通过实现 BeanDefinitionRegistry 接口来提供往内部的 beanFactory 注入 beanDefinitions,而 beanDefinitions 的来源则是通过 BeanDefinitionParser 解析,如 xml 文件来获取的。不支持重复调用 refresh

    GenericXmlApplicationContext:继承于 GenericApplicationContext,比 ClassPathXmlApplicationContextFileSystemXmlApplicationContext 更加通用的基于 xml 配置文件的 ApplicationContext。即可以在构造函数中指定配置数来源,使用的 Resource 类型的数组参数。而前两者都是使用String 类型的 configLocations 数组,即路径数组。

    AnnotationConfigApplicationContext

    public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {}
    
    • 1

    这个也是用来处理我们项目中使用的注解的类,即将标注了 @Controller, @Component 等注解的类注册成 bean。继承于 GenericApplicationContext,并实现 AnnotationConfigRegistry 接口(AnnotationConfigRegistry 接口主要实现将给定的 beanDefinition 注册到绑定的 beanFactory 中)。

  • 相关阅读:
    Apache APISIX Ingress v1.5-rc1 发布
    LINUX基础知识和命令 二
    node.js环境安装和VUE-cli脚手架搭建
    掌控安全学院SQL注入靶场
    Linux实验操作之使用LAMP系统架设一个Discuz论坛
    2023 年您需要了解哪些类型的数据泄露?
    可以作为艺术作品欣赏的CT三维重建技术。
    C语言每日一题(10) 回形矩阵
    【操作系统】内存管理(一)—— 内存管理的概述与总结
    接口隔离原则~
  • 原文地址:https://blog.csdn.net/qiaohao0206/article/details/125537380