IOC 容器

Spring 容器是 Spring 框架的核心。容器将创建对象,把它们连接在一起,配置它们,并管理他们的整个生命周期从创建到销毁。Spring 容器使用依赖注入(DI)来管理组成一个应用程序的组件。这些对象被称为 Spring Beans。

通过阅读配置元数据提供的指令,容器知道对哪些对象进行实例化,配置和组装。配置元数据可以通过 XML,Java 注释或 Java 代码来表示。下图是 Spring 如何工作的高级视图。 Spring IoC 容器利用 Java 的 POJO 类和配置元数据来生成完全配置和可执行的系统或应用程序。
Spring IOC容器 - 图1

IOC 容器 是**具有依赖注入功能的容器,它可以创建对象,IOC 容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。通常new一个实例,控制权由程序员控制,而控制反转()是指new实例工作不由程序员来做而是交给Spring容器来做。在Spring中 BeanFactory 是IOC容器的实际代表者。

Spring 提供了以下两种不同类型的容器:

  • BeanFactory:它是最简单的容器,给 DI 提供了基本的支持,它用 org.springframework.beans.factory.BeanFactory 接口来定义。BeanFactory 或者相关的接口,如 BeanFactoryAwareInitializingBeanDisposableBean,在 Spring 中仍然存在具有大量的与 Spring 整合的第三方框架的反向兼容性的目的。
  • ApplicationContext:该容器添加了更多的企业特定的功能,例如从一个属性文件中解析文本信息的能力,发布应用程序事件给感兴趣的事件监听器的能力。该容器是由 org.springframework.context.ApplicationContext 接口定义;

ApplicationContext 容器包括 BeanFactory 容器的所有功能,所以通常建议使用 ApplicationContextBeanFactory 仍然可以用于轻量级的应用程序,如移动设备或基于 applet 的应用程序,其中它的数据量和速度是显著。

Spring BeanFactory 容器

这是一个最简单的容器,它主要的功能是为依赖注入 (DI) 提供支持,这个容器接口在 org.springframework.beans.factory.BeanFactor 中被定义。 BeanFactory 和相关的接口,比如 BeanFactoryAwareDisposableBeanInitializingBean ,仍旧保留在 Spring 中,主要目的是向后兼容已经存在的和那些 Spring 整合在一起的第三方框架。

在 Spring 中,有大量对 BeanFactory 接口的实现。其中,最常被使用的是**XmlBeanFactory**类。这个容器从一个 XML 文件中读取配置元数据,由这些元数据来生成一个被配置化的系统或者应用。

在资源宝贵的移动设备或者基于 applet 的应用当中, BeanFactory 会被优先选择。否则,一般使用的是 ApplicationContext ,除非你有更好的理由选择 BeanFactory

代码示例

(1)创建HelloWord类

  1. public class HelloWord {
  2. private String message;
  3. public String getMessage() {
  4. return message;
  5. }
  6. public void setMessage(String message) {
  7. this.message = message;
  8. }
  9. public void sayHello(){
  10. System.out.println("hello world!");
  11. }
  12. }

(2)配置文件 bean.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
  5. <bean class="com.haan.HelloWord" id="helloWord"></bean> //
  6. </beans>

(3)main函数测试

  1. /**
  2. * @Desc
  3. * @Created By liukuihan
  4. * @date on 2020/5/23
  5. */
  6. public class Main {
  7. public static void main(String[] args) {
  8. BeanFactory beanFactory =
  9. new XmlBeanFactory(new ClassPathResource("bean.xml"));//<1>
  10. HelloWord helloWord = (HelloWord) beanFactory.getBean("helloWord"); //<2>
  11. helloWord.sayHello(); //<3>
  12. }
  13. }
  • <1>:加载bean.xml配置文件,将在bean.xml中配置的POJO注入到spring容器中去,即生成Spring bean;
  • <2>:从spring容器中读取bean id为hellWord的bean;
  • <3>:调用HelloWordsayHello()方法

在主程序当中,我们需要注意以下两点:

  • 第一步利用框架提供的 **XmlBeanFactory()** API 去生成工厂 bean 以及利用 **ClassPathResource()** API 去加载在路径 CLASSPATH 下可用的 bean 配置文件。**XmlBeanFactory()** API 负责创建并初始化所有的对象,即在配置文件中提到的 bean。
  • 第二步利用第一步生成的 bean 工厂对象的 **getBean()** 方法得到所需要的 bean。 这个方法通过配置文件中的 bean ID 来返回一个真正的对象,该对象最后可以用于实际的对象。一旦得到这个对象,你就可以利用这个对象来调用任何方法。

(4)执行结果

  1. hello world!

Spring ApplicationContext 容器

ApplicationContextBeanFactory的子接口,也被成为 Spring 上下文。

我们看下接口ApplicationContext的源码:

  1. public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
  2. @Nullable
  3. String getId();
  4. String getApplicationName();
  5. String getDisplayName();
  6. long getStartupDate();
  7. @Nullable
  8. ApplicationContext getParent();
  9. AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;
  10. }

我们可以发现ApplicationContext继承了ListableBeanFactory, HierarchicalBeanFactory接口,而ListableBeanFactoryHierarchicalBeanFactory
接口又都继承了BeanFactory 接口。

ApplicationContext 是 spring 中较高级的容器。和 BeanFactory类似,它可以加载配置文件中定义的 bean,将所有的 bean 集中在一起,当有请求的时候分配 bean。 另外,它增加了企业所需要的功能,比如,从属性文件中解析文本信息和将事件传递给所指定的监听器。这个容器在 org.springframework.context.ApplicationContext interface接口中定义。

ApplicationContext包含 BeanFactory所有的功能,一般情况下,相对于 BeanFactoryApplicationContext会更加优秀。当然,BeanFactory仍可以在轻量级应用中使用,比如移动设备或者基于 applet的应用程序。

最常被使用的 ApplicationContext接口实现:

  • **FileSystemXmlApplicationContext**:该容器从 XML文件中加载已被定义的 bean。在这里,你需要提供给构造器 XML文件的完整路径。

  • **ClassPathXmlApplicationContext**:该容器从 XML文件中加载已被定义的 bean。在这里,你不需要提供 XML文件的完整路径,只需正确配置 CLASSPATH环境变量即可,因为,容器会从 CLASSPATH中搜索 bean配置文件。

  • **WebXmlApplicationContext**:该容器会在一个 web应用程序的范围内加载在 XML文件中已被定义的 bean

    代码示例

修改main函数测试:

  1. public class Main {
  2. public static void main(String[] args) {
  3. // BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("bean.xml")); //<1>
  4. //
  5. // HelloWord helloWord = (HelloWord) beanFactory.getBean("helloWord"); //<2>
  6. // helloWord.sayHello(); //<3>
  7. ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
  8. HelloWord helloWord = (HelloWord) context.getBean("helloWord");
  9. helloWord.sayHello();
  10. }
  11. }

在主程序当中,我们需要注意以下两点:

  • 第一步生成工厂对象。加载完指定路径下 bean配置文件后,利用框架提供的 FileSystemXmlApplicationContextAPI 去生成工厂 beanFileSystemXmlApplicationContext负责生成和初始化所有的对象,比如,所有在 XML ``bean配置文件中的 bean

  • 第二步利用第一步生成的上下文中的 getBean() 方法得到所需要的 bean。 这个方法通过配置文件中的 beanID 来返回一个真正的对象。一旦得到这个对象,就可以利用这个对象来调用任何方法。

Spring Bean定义

Bean 定义

被称作 bean 的对象是构成应用程序的支柱也是由 Spring IoC 容器管理的。bean 是一个被实例化,组装,并通过 Spring IoC 容器所管理的对象。这些 bean 是由用容器提供的配置元数据创建的,例如在 XML 的表单中的定义。
bean 定义包含称为配置元数据的信息,下述容器也需要知道配置元数据:

  • 如何创建一个 bean
  • bean 的生命周期的详细信息
  • bean 的依赖关系

上述所有的配置元数据转换成一组构成每个 bean 定义的下列属性。

Bean定义的属性

属性 描述
class 这个属性是强制性的,并且指定用来创建 bean 的 bean 类。
name 这个属性指定唯一的 bean 标识符。在基于 XML 的配置元数据中,你可以使用 ID 和/或 name 属性来指定 bean 标识符。
scope 这个属性指定由特定的 bean 定义创建的对象的作用域,它将会在 bean 作用域的章节中进行讨论。
constructor-arg 它是用来注入依赖关系的,并会在接下来的章节中进行讨论。
properties 它是用来注入依赖关系的,并会在接下来的章节中进行讨论。
autowiring mode 它是用来注入依赖关系的,并会在接下来的章节中进行讨论。
lazy-initialization mode 延迟初始化的 bean 告诉 IoC 容器在它第一次被请求时,而不是在启动时去创建一个 bean 实例。
initialization 方法 在 bean 的所有必需的属性被容器设置之后,调用回调方法。它将会在 bean 的生命周期章节中进行讨论。
destruction 方法 当包含该 bean 的容器被销毁时,使用回调方法。它将会在 bean 的生命周期章节中进行讨论。

Bean和Spring容器的关系

下图表达了Bean 与 Spring 容器之间的关系:
Spring IOC容器 - 图2
Bean配置信息定义了Bean的实现及依赖关系,Spring容器根据各种形式的Bean配置信息在容器内部建立Bean定义注册表,然后根据注册表加载、实例化Bean,并建立Bean和Bean的依赖关系,最后将这些准备就绪的Bean放到Bean缓存池中,以供外层的应用程序进行调用。