Spring -- IoC

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

Spring 提供 BeanFactory 和 ApplicationContext 这两种容器,类图如下:
class relations

BeanFactory 容器

它是最简单的容器,给 DI 提供了基本的支持,它用 org.springframework.beans.factory.BeanFactory 接口来定义。BeanFactory 或者相关的接口,如 BeanFactoryAware,InitializingBean,DisposableBean,在 Spring 中仍然存在具有大量的与 Spring 整合的第三方框架的反向兼容性的目的。

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.

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).

Normally a BeanFactory will load bean definitions stored in a configuration source (such as an XML document), and use the {@code org.springframework.beans} package 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).

ApplicationContext 容器

该容器添加了更多的企业特定的功能,例如从一个属性文件中解析文本信息的能力,发布应用程序事件给感兴趣的事件监听器的能力。该容器是由 org.springframework.context.ApplicationContext 接口定义。

Central interface to provide configuration for an application. This is read-only while the application is running, but may be reloaded if the implementation supports this.

An ApplicationContext provides:

  • Bean factory methods for accessing application components.
  • The ability to load file resources in a generic fashion.
  • The ability to publish events to registered listeners.
  • The ability to resolve messages, supporting internationalization.
  • Inheritance from a parent context. Definitions in a descendant context will always take priority. This means, for example, that a single parent context can be used by an entire web application, while each servlet has its own child context that is independent of that of any other servlet.
  • In addition to standard BeanFactory lifecycle capabilities, ApplicationContext implementations detect and invoke ApplicationContextAware beans as well as ResourceLoaderAware, ApplicationEventPublisherAware and MessageSourceAware beans.

Comparison

1
2
3
4
5
6
7
8
9
10
11
12
13
public class MainApp {
public static void main(String[] args) {
// BeansFactory
XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("Beans.xml"));
HelloWorld obj = (HelloWorld) factory.getBean("helloWorld");

// ApplicationContext
ApplicationContext context = new FileSystemXmlApplicationContext("Beans.xml");
HelloWorld obj = (HelloWorld) context.getBean("helloWorld");

obj.getMessage();
}
}

Spring Bean 定义

配置文件 Beans.xml

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
30
<?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">

<!-- A simple bean definition -->
<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>

<!-- A bean definition with lazy init set on 当第一次请求这个bean时再创建-->
<bean id="..." class="..." lazy-init="true">
<!-- collaborators and configuration for this bean go here -->
</bean>

<!-- A bean definition with initialization method -->
<bean id="..." class="..." init-method="...">
<!-- collaborators and configuration for this bean go here -->
</bean>

<!-- A bean definition with destruction method -->
<bean id="..." class="..." destroy-method="...">
<!-- collaborators and configuration for this bean go here -->
</bean>

<!-- more bean definitions go here -->

</beans>

  • 通过配置bean标签来完成对象的管理

    • id: 对象名
    • class: 对象的模板类,所有交给IoC容器来管理的类必须有无参构造函数,因为Spring底层是通过反射机制来创建对象的,而反射机制调用的是无参构造
  • 对象的成员变量通过property这个标签来完成赋值

    • name: 成员变量名
    • value: 成员变量值(基本数据类型,String可以直接赋值,如果是其它引用类型,不能通过value赋值)
    • ref: 将IoC中的另外一个bean赋值给当前成员变量(依赖注入DI
    • 内部bean:
    • 集合: 内可以配置
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      <bean id="address_1" class=".....Address">
      <property name="id" value="1"></property>
      <property name="name" value = "上海路"></property>
      </bean>

      <bean id = "student_1" class = ".....Student">
      <property name = "student_name" value="张三"></property>
      <property name = "age" value="15"></property>
      <property name = "address" ref="address_1"></property>
      </bean>

IoC底层原理

  • 读取配置文件,解析XML (可以用 SAXReader 对 XML 文件解析,转换成 Document 对象)
  • 通过反射机制实例化配置文件中所配置的所有的bean

Relation Between Beans and Spring