【Spring 源码】Spring IoC 容器的基本介绍
文章目录
一、Spring Bean和容器的概念
Spring 的基本单位是 Bean,和 OOP(面向对象编程)类似,是以对象为基本单位来管理,而管理 Bean 的对象则称之为容器。其中容器需要实现顶级接口 BeanFactory,里面定义了管理 Bean 的基本方法。
1. BeanFactory 容器
【1】BeanFactory 容器的介绍
BeanFactory 作为一个容器的顶级接口,其中定义了许多关于 Bean 内容的最基本的方法规范,是 Spring 中最简单最基本的一个容器。当然,BeanFactory 只是一个基础接口,还有三个继承此接口的扩展接口 ListableBeanFactory、AutowireCapableBeanFactory 和 HierarchicalBeanFactory,三个接口分别定义了不同容器该实现的方法。比如实现 ListableBeanFactory 接口的容器主要用来将 Bean 进行枚举化,实现 HierarchicalBeanFactory 接口的容器可以设置 BeanFactory 是否可以进行继承,也就是可以设置父级 BeanFactory,而实现 AutowireCapableBeanFactory 接口的容器可以将 Bean 进行自动注入。
通过 BeanFactory 的子类实现一层层查找,可以找到 Spring 提供的默认的 BeanFactory 容器 DefaultListableBeanFactory,默认容器实现了三个基本接口。其中 DefaultListableBeanFactory 上层还有两个抽象类 AbstractBeanFactory 和 AbstractAutowireCapableBeanFactory,这两个抽象类都是对 BeanFactory 的一些方法进行了默认实现,而 AbstractAutowireCapableBeanFactory 还会对 AutowireCapableBeanFactory 接口方法进行扩展实现。
根据接口文档的介绍,BeanFactory 主要用来作为 Spring 组件的注册中心,然后使用 DI(Denpendency Injection,依赖注入)来将注册过的类推送到想使用的地方,而不是用户自己通过查找来获取想要的类。
【2】BeanFactory 容器的使用
在上面介绍到 BeanFactory 默认的实现类是 DefaultListableBeanFactory,并且 DefaultListableBeanFactory 下面还提供了一个子类 XmlBeanFactory,XmlBeanFactory 主要是对 xml 文件注册的 Bean 进行读取以及注册。其实从这边可以看出来,xml 文件就是 Spring 中默认且常用的一种文件内容管理格式,Spring MVC 会对 xml 格式的配置文件进行更强大的扩展。
在下面 BeanFactory 为容器的例子中,新建了一个类名为 MyBean 的 Bean,并且在 MyBean.xml 进行注册,然后 XmlBeanFactory 会从 xml 中获取相对应的 Bean 并打印出相对应的信息内容。
- 目录结构:
|-- src
|-- com.test
|-- Main.java
|-- MyBean.java
|-- MyBean.xml
- MyBean.java:
public class MyBean {
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
- MyBean.xml:
<?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 id="myBean" class="com.test.MyBean">
<property name="message" value="Hello World!" />
</bean>
</beans>
- Main.java:
public class Main {
public static void main(String[] args) {
XmlBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("MyBean.xml"));
MyBean bean = (MyBean) beanFactory.getBean("myBean");
System.out.println(bean.getMessage());
}
}
2. ApplicationContext 容器
【1】ApplicationContext 容器的介绍
ApplicationContext 是 BeanFactory 的一个扩展接口,是一个常用的重量级的接口,相比于 BeanFactory,ApplicationContext 设置了更多的企业功能,比如 ApplicationEventPublisher 接口提供的事件分发机制以及 MessageSource 提供的 Spring 国际化等。
XmlBeanFactory 因为被标记为 @Deprecated
,所以平常使用的时候都是使用 ApplicationContext 接口定义的容器。除非是在某些需要轻量级框架的时候,可以使用 XmlBeanFactory,否则一般不建议使用。
ApplicationContext 容器有三种容器实现:
- FileSystemXmlApplicationContext:从 XML 中获取定义的 Bean,需要提供 xml 文件的完整路径。
- ClassPathXmlApplicationContext:从 XML 中获取定义的 Bean,不需要提供 xml 文件的完整路径,只需要正确配置 CLASSPATH 环境变量,配置以后,容器会从环境变量中搜索 xml 文件。
- XmlWebApplicationContext:容器会从 web 程序范围内加载 XML 文件中的 Bean,此容器就是 Spring MVC 中默认使用的一种容器。
【2】ApplicationContext 容器的使用
- 目录结构:
|-- src
|-- com.test
|-- Main.java
|-- MyBean.java
|-- MyBean.xml
- MyBean.java:
public class MyBean {
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
- MyBean.xml:
<?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 id="myBean" class="com.test.MyBean">
<property name="message" value="Hello World!" />
</bean>
</beans>
- Main.java:
// FileSystemXmlApplicationContext
public class Main {
public static void main(String[] args) {
FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("F:\\myProfiles\\SpringTest\\src\\MyBean.xml");
MyBean bean = (MyBean) beanFactory.getBean("myBean");
System.out.println(bean.getMessage());
}
}
// ClassPathXmlApplicationContext
public class Main {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("MyBean.xml");
MyBean bean = (MyBean) beanFactory.getBean("myBean");
System.out.println(bean.getMessage());
}
}
二、IoC 的概念
其实看到上面的例子,就能大概才出来 IoC 大概是什么意思,其实就是 Bean 的实例操作是反转给容器来做,并且获取 Bean 也是通过容器获取,而不是平常一样使用 new 操作生成 Bean 实例。
在上面的例子实现 Bean 的控制反转一共有四步操作。
- 新建 Bean,以及在 xml 文件中注册 Bean。
- 使用 new 新建容器,并且获取 xml 文件。
- 容器通过一系列操作生成 Bean。
- 使用者通过
getBean()
获得的 Bean 来使用 Bean。