0x00 参考

本笔记直接参考或引自如下链接文章:

https://www.w3cschool.cn/wkspring/

http://c.biancheng.net/spring/

0x01 IoC简介

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

IoC(Inversion of Control,控制反转)是指在程序开发中,实例的创建不再由调用者管理,而是由Spring容器创建。Spring容器会负责控制程序之间的关系,而不是由程序代码直接控制,因此控制权由程序代码转移到了Spring容器中,控制权发生了反转,这就是Spring的IoC思想。

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

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

Spring提供了两种IoC容器,分别为BeanFactory和ApplicationContext。

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

二者的主要区别在于,如果Bean的某一个属性没有注入,则使用BeanFacotry加载后,在第一次调用getBean()方法时会抛出异常,而ApplicationContext则在初始化时自检,这样有利于检查所依赖的属性是否注入。因此,在实际开发中,通常都选择使用ApplicationContext,而只有在系统资源较少时才考虑使用BeanFactory。

0x02 BeanFactory

BeanFactory是基础类型的IoC容器,由org.springframework.beans.facytory.BeanFactory接口定义,主要的功能是为依赖注入(DI)提供支持,并提供了完整的IoC服务支持。简单来说,BeanFactory就是一个管理Bean的工厂,它主要负责初始化各种Bean,并调用它们的生命周期方法。

BeanFactory和相关的接口,比如BeanFactoryAware、DisposableBean、InitializingBean,仍旧保留在Spring中,主要目的是向后兼容已经存在的和那些Spring整合在一起的第三方框架。

BeanFactory接口有多个实现类,最常见的是org.springframework.beans.factory.xml.XmlBeanFactory,它是根据XML配置文件中的定义装配Bean的。

创建BeanFactory实例时,需要提供Spring所管理容器的详细配置信息,这些信息通常采用XML文件形式管理。其加载配置信息的代码具体如下所示:

1
BeanFactory beanFactory = new XmlBeanFactory(new FileSystemResource("D://applicationContext.xml"));

Demo

HelloWorld.java,Bean类:

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.mi1k7ea;

public class HelloWorld {
private String message;

public void setMessage(String message){
this.message = message;
}

public void getMessage(){
System.out.println("Your Message : " + message);
}
}

MainApp.java:

1
2
3
4
5
6
7
8
9
10
11
12
package com.mi1k7ea;

import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;

public class MainApp {
public static void main(String[] args) {
XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("Beans.xml"));
HelloWorld obj = (HelloWorld) factory.getBean("helloWorld");
obj.getMessage();
}
}

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

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

Beans.xml,给HelloWorld类的message属性赋值:

1
2
3
4
5
6
7
8
9
10
11
<?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-3.0.xsd">

<bean id="helloWorld" class="com.mi1k7ea.HelloWorld">
<property name="message" value="BeanFactory Test"/>
</bean>

</beans>

运行,输出如下:

0x03 ApplicationContext

ApplicationContext是BeanFactory的子接口,被称为应用上下文。Application Context是Spring中较高级的容器。和BeanFactory类似,它可以加载配置文件中定义的Bean,将所有的Bean集中在一起,当有请求的时候分配 Bean。它不仅提供了BeanFactory的所有功能,还添加了对i18n(国际化)、资源访问、事件传播等方面的良好支持。该接口的全路径为org.springframework.context.ApplicationContext。

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

  • FileSystemXmlApplicationContext:该容器从XML文件中加载已被定义的Bean。在这里,你需要提供给构造器XML文件的绝对路径;
  • ClassPathXmlApplicationContext:该容器从XML文件中加载已被定义的Bean。无需提供XML文件的完整路径,只需正确配置CLASSPATH环境变量即可,因为容器会从CLASSPATH中搜索Bean配置文件;
  • WebXmlApplicationContext:该容器会在一个Web应用程序的范围内加载在XML文件中已被定义的 bean;

Demo

以前面的例子为例,HelloWorld.java不用修改,Beans.xml的message属性值改为”ApplicationContext Test”。

MainApp.java,将IoC容器从XmlBeanFactory改为ApplicationContext,同时获取XML配置文件的方式改为调用FileSystemXmlApplicationContext,注意要绝对路径:

1
2
3
4
5
6
7
8
9
10
11
12
package com.mi1k7ea;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

public class MainApp {
public static void main(String[] args) {
ApplicationContext context = new FileSystemXmlApplicationContext("E:\xx\\xx\\SpringTest\\src\\Beans.xml");
HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
obj.getMessage();
}
}

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

  • 第一步生成工厂对象。加载完指定路径下 bean 配置文件后,利用框架提供的 FileSystemXmlApplicationContext API 去生成工厂 bean。FileSystemXmlApplicationContext 负责生成和初始化所有的对象,比如,所有在 XML bean 配置文件中的 bean。
  • 第二步利用第一步生成的上下文中的 getBean() 方法得到所需要的 bean。 这个方法通过配置文件中的 bean ID 来返回一个真正的对象。一旦得到这个对象,就可以利用这个对象来调用任何方法。

输出: