IOC概念
( Inversion of Control,縮寫為 IoC),是面向對象程式設計中的一種設計原則,可以用來降低計算機代碼之間的耦合度。
簡單來說Spring中的IOC控制反轉就是将對象執行個體化對象的控制權,由手動的new,轉為交給Spring架構通過反射機制,進行對象的執行個體化。
在Spring入門中我們已經使用了xml配置來控制對象的建立,實作了控制反轉。
容器的使用
前面說了控制反轉就是将創見對象的控制權由new,轉為交給Spring架構通過反射機制,進行對象的執行個體化,Spring容器進行執行個體化後會将建立的執行個體對象放入Spring容器,那麼Spring容器到底是什麼東西?
概念了解
容器,容器,顧名思義就是用來裝東西的;如我們生活中的水杯,水桶、水盆等等,是以我們的Spring容器也是用來裝東西的;水杯、水桶用來裝水,而我們的Spring容器就是用來裝對象執行個體的。
IOC 容器的體系結構
-
spring容器
Spring的容器有兩個
- BeanFactory
- ApplicationContext
- 兩者的關系
可以看出,他們兩個都是接口,并且ApplicationContext是BeanFactory的子接口。
在BeanFactory中提供了配置架構和基本功能
在ApplicationContext中增加了更多針對企業的功能。
-
兩者的差別
建立對象的時間點不一樣。
:隻要一讀取配置檔案,預設情況下就會建立對象,類似與單例模式中的餓漢式。ApplicationContext
:什麼時候使用,什麼時候建立對象,類似與單例模式中的懶漢式。BeanFactory
IoC 容器執行個體化的方式
上面已經知道 Spring 的容器是通過一個接口
org.springframework.context.ApplicationContext
表示,并負責執行個體化,配置群組裝 Bean 對象。容器通過讀取 xml 檔案中的配置資訊來擷取關于執行個體化對象,配置屬性等指令。
而
ApplicationContext
隻是一個接口,我們通常建立
ClassPathXmlApplicationContext
的執行個體或者
FileSystemXmlApplicationContext
的執行個體。
前者是從類路徑中擷取上下文定義檔案,後者是從檔案系統或 URL 中擷取上下文定義檔案。
- 從類路徑下讀取Spring配置檔案,建立Spring容器
public void userSaveTest() { //建立spring容器,參數指定spring配置檔案的全名 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); //可以使用多态方式也可以 /* ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); */ }
- 從電腦本地讀取配置檔案,建立Spring容器
public void userSaveTest() { //建立spring容器,參數指定spring配置檔案的全名 FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("D:\\applicationContext.xml"); }
bean 标簽中的屬性介紹
我們知道Bean标簽的作用就是在架構啟動加載配置檔案的時候,根據配置的類的全限定名,建立執行個體對象,放入Spring容器進行統一管理,
Bean标簽回顧
以上我們隻用到了id屬性和class屬性,那麼來看一下是否還有其他屬性。
常用屬性介紹
屬性 | 描述 |
---|---|
id | 定義配置的Bean标簽的唯一辨別 |
name | 同id屬性 |
class | 表示要描述的類,也就是當加載spring配置檔案的時候,要根據此屬性指定的類的全限定名建立的執行個體對象。 |
factory-bean | 主要用于工廠模式執行個體化 bean 的時候使用,這個屬性用于引用配置的工廠Bean |
factory-method | 主要用于工廠模式執行個體化 bean 的時候使用,這個屬性表示引用工廠Bean中的指定方法。 在普通工廠模式下factory-bean與factory-method結合使用,靜态工廠時單獨使用factory-method |
init-method | Bean初始化的時候,指定執行的方法。 |
destroy-method | Bean銷毀的時候,指定執行的方法。 |
scope | 指定配置的Bean的作用範圍,一般用多例還是單例來表述它。 |
lazy-init | 懶加載 |
autowire | 依賴注入 |
depends-on | 依賴于某個執行個體 |
id和name屬性
用于定義Bean的唯一辨別,友善我們擷取。
配置檔案代碼
<?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="user" name="user2" class="com.wyan.entity.User" ></bean>
</beans>
測試類代碼
public static void main(String[] args) {
ApplicationContext context =
new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
System.out.println(context.getBean("user"));
System.out.println(context.getBean("user2"));
}
無論是使用id還是使用name,都能從Spring容器中擷取Bean
class 屬性
Spring的底層是通過反射來建立的執行個體對象,但是他不知道建立哪個類的執行個體對象啊;是以通過Class屬性指定要建立的執行個體對象的全限定類名。
factorybean 和 factorymethod 屬性
這兩個屬性主要用于工廠模式執行個體化 bean 的時候使用
-
使用靜态工廠模式擷取Bean
靜态工廠類代碼
applicationContext配置//方法和參數都是靜态的 public class User { private static User user = new User(); private User() {} public static User createInstance() { return user; } }
<!-- 通過factory-method屬性,引用User工廠類中的createInstance方法,該方法傳回值是一個user對象; 是以當我們使用Bean标簽的id擷取Bean的時候,得到的是createInstance方法的傳回值 -> user對象 --> <bean id="user" class="com.wyan.entity.User" factory-method="createUserInstance"/>
-
使用普通工廠擷取Bean
普通工廠類代碼
applicationContext配置public class BeanFactory { private static User1 user1 = new User1(); private static User2 user2 = new User2(); public User1 createUser1() { return user1; } public User2 createUser2() { return user2; } }
先要配置工廠Bean,然後引用工廠Bean的id,使用factory-method屬性,引用工廠Bean中的方法,得到該方法的傳回值,也就得到了User1執行個體對象<!--spring執行個體化工廠對象 用于建立java執行個體 --> <bean id="beanFactory" class="com.wyan.factory.BeanFactory"></bean> <!-- 被工廠建立的對象執行個體 --> <bean id="user1" factory-bean="beanFactory" factory-method="createUser1"/>
init-method 和 destroy-method 屬性的使用
init-method 就是 bean 被初始化後執行的方法,destory-method 就是 bean 被銷毀執行的代碼。
- 測試代碼User類
public class User { public User(){ System.out.println("我被spring執行個體化了"); } public void initMethod(){ System.out.println("user類執行個體化時候執行的代碼"); } public void destoryMethod(){ System.out.println("user類執行個體被銷毀時候執行的代碼"); } }
- applicationContext.xml配置
- 測試代碼
public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); }
- 結果
scope 屬性
常用屬性值
預設為singleton 單例
- singleton:單例建立對象,當建立Spring容器的時候,對象就會建立,銷毀Spring容器的時候,對象也就銷毀;每次從Spring容器中擷取的對象都是同一個。
- prototype:多例建立對象,當擷取對象的時候,才會建立對象,銷毀Spring容器的時候,對象不會銷毀,由其它機制管理銷毀;每次從Spring中擷取的對象都不是同一個。
<!--單例--> <bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl" scope="singleton"/> <!--多例--> <bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl" scope="prototype"/>