Spring IoC容器(一)
一、Spring IoC 容器和 Bean 簡介
IoC也稱為依賴注入(dependency injection, DI)。這是一個過程,在這個過程中,物件僅通過建構函式引數、工廠方法的引數或物件例項構造或從工廠方法返回後在該物件例項上設定的屬性來定義它們的依賴關係(即與它們一起工作的其他物件)。然後容器在建立bean時注入這些依賴項。這個過程本質上與bean本身相反(因此稱為控制反轉),bean本身通過直接構造類或一種機制(如服務定位器模式)來控制依賴項的例項化或位置。
org.springframework.beans
和 org.springframework.context
在Spring中,構成應用程式主幹並由Spring IoC容器管理的物件稱為bean。bean是由Spring IoC容器例項化、組裝和管理的物件。否則,bean只是應用程式中的許多物件之一。bean及其之間的依賴關係反映在容器使用的配置元資料中。
二、容器概述
org.springframework.context.ApplicationContext
介面表示Spring IoC容器,負責例項化、配置和組裝bean。容器通過讀取配置元資料獲取關於要例項化、配置和組裝哪些物件的指令。配置元資料用XML、Java註釋或Java程式碼表示。它允許您表達組成應用程式的物件以及這些物件之間豐富的相互依賴關係。
Spring提供了ApplicationContext介面的幾個實現。在獨立應用程式中,通常建立ClassPathXmlApplicationContext或FileSystemXmlApplicationContext的例項。雖然XML一直是定義配置元資料的傳統格式,但可以通過提供少量XML配置來宣告支援這些額外的元資料格式,從而指示容器使用Java註釋或程式碼作為元資料格式。
下圖顯示了Spring如何工作的高階檢視
1. 配置元資料
傳統上,配置元資料以簡單直觀的XML格式提供,不過基於XML的元資料不是唯一允許的配置元資料形式。Spring IoC容器本身完全與實際編寫此配置元資料的格式分離。現在,許多開發都是基於Java的配置。
- 基於註釋的配置:Spring 2.5引入了對基於註釋的配置元資料的支援
- 基於Java的配置:從Spring 3.0開始,Spring JavaConfig專案提供的許多功能成為核心Spring Framework的一部分。因此,我們可以使用Java而不是XML檔案在應用程式類外部定義bean。要使用這些新功能,請參閱
@Configuration
,@Bean
,@Import
,和@DependsOn
註釋。
Spring配置包含容器必須管理的至少一個且通常不止一個bean定義。基於XML的配置元資料將這些bean配置為<bean/>
頂級元素內的<beans/>
元素。Java配置通常@Bean
在@Configuration
類中使用註釋方法。
這些bean定義對應於組成應用程式的實際物件。通常,定義服務層物件、資料訪問物件(DAOs)、表示物件(如Struts操作例項)、基礎設施物件(如Hibernate SessionFactories)、JMS佇列等等。通常,不會在容器中配置細粒度域物件,因為通常由dao和業務邏輯負責建立和載入域物件。不過,可以使用Spring與AspectJ的整合來配置在IoC容器控制之外建立的物件。
以下示例顯示了基於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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="teacher" class="com.example.spring.beans.Admin">
<!-- collaborators and configuration for this bean go here -->
<property name="name" value="小明"/>
<property name="sex" value="男"/>
<property name="age" value="22"/>
</bean>
<!-- more bean definitions go here -->
</beans>
id
屬性是一個標識單個bean定義的字串。class
屬性定義bean的型別並使用完全限定的類名。
2. 例項化容器
提供給ApplicationContext
建構函式的位置路徑是資源字串,它允許容器從各種外部資源(如本地檔案系統,Java等)載入配置元資料CLASSPATH
。
ApplicationContext context = new ClassPathXmlApplicationContext("user.xml");
簡單示例如下
專案結構:
Admin物件:
package com.example.spring.beans;
import lombok.Data;
/**
* @author
* @version 2019/4/16 上午 10:40
*/
@Data
public class Admin {
private String name;
private String sex;
private Integer age;
}
User物件:
package com.example.spring.beans;
import lombok.Data;
/**
* @author
* @version 2019/4/16 上午 10:40
*/
@Data
public class User {
private Integer type;
private Admin admin;
@Data
public static class Child {
private String name;
}
}
content.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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="admin" class="com.example.spring.beans.Admin">
<!-- collaborators and configuration for this bean go here -->
<property name="name" value="小明"/>
<property name="sex" value="男"/>
<property name="age" value="22"/>
</bean>
<!-- more bean definitions go here -->
</beans>
user.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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="content.xml"/>
<alias name="user2" alias="user3"/>
<bean id="user" name="user2" class="com.example.spring.beans.User">
<!-- collaborators and configuration for this bean go here -->
<property name="type" value="1"/>
<property name="admin" ref="admin"/>
</bean>
<bean id="a" class="com.example.spring.beans.User$Child">
<!-- collaborators and configuration for this bean go here -->
<property name="name" value="123"/>
</bean>
<!-- more bean definitions go here -->
</beans>
main方法:
package com.example.spring;
import com.example.spring.beans.Admin;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author
* @version 2019/4/16 上午 10:47
*/
public class Main {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:/user.xml");
System.out.println(context);
System.out.println(context.getBean("user"));
System.out.println(context.getBean("user2"));
System.out.println(context.getBean("user3"));
System.out.println(context.getBean(Admin.class));
System.out.println(context.getBean("a"));
}
}
執行結果:
18:33:19.614 [main] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@73a28541 18:33:19.738 [main] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 1 bean definitions from class path resource [content.xml] 18:33:19.739 [main] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 3 bean definitions from class path resource [user.xml] 18:33:19.762 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'teacher' 18:33:19.804 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'user' 18:33:19.806 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'a' org.springframework.context.support.ClassPathXmlApplicationContext@73a28541, started on Wed Apr 17 18:33:19 CST 2019 User(type=1, admin=Admin(name=小明, sex=男, age=22)) User(type=1, admin=Admin(name=小明, sex=男, age=22)) User(type=1, admin=Admin(name=小明, sex=男, age=22)) Admin(name=小明, sex=男, age=22) U