全網瘋傳的Spring學習筆記【IOC、DI和Spring工廠】,看完我也想寫一個了!
四、控制反轉(IOC)和依賴注入(DI)
4.1、控制反轉(IOC)
控制反轉(IoC,Inversion of Control),是一個概念,是一種思想。指將傳統上由程序代碼直接操控的對象調用權交給容器,通過容器來實現對象的裝配和管理。控制反轉就是對對象控制權的轉移,從程序代碼本身反轉到了外部容器。通過容器實現對象的創建,屬性賦值,依賴的管理。
簡單來說控制反轉就是把對于成員變量賦值的控制權,從代碼中反轉(轉移)到spring工廠和配置文件中完成。
IoC 是一個概念,是一種思想,其實現方式多種多樣。spring 框架使用依賴注入(DI)實現 IoC。
4.2、依賴注入(DI)
依賴:classA 類中含有 classB 的實例,在 classA 中調用 classB 的方法完成功能,即 classA對 classB 有依賴。
依賴注入(Dependency Injection):當一個類需要另一個類時,就可以把另一個類作為本類的成員變量,最終通過Spring的配置文件進行注入(賦值)。簡單來說就是指程序運行過程中,若需要調用另一個對象協助時,無須在代碼中創建被調用者,而是依賴于外部容器,由外部容器創建后傳遞給程序。
Spring 的依賴注入對調用者與被調用者幾乎沒有任何要求,完全支持對象之間依賴關系的管理。
4.3、總結
Spring 容器是一個超級大工廠,負責創建、管理所有的 Java 對象,這些 Java 對象被稱為 Bean。Spring 容器管理著容器中 Bean 之間的依賴關系,Spring 使用“依賴注入”的方式來管理 Bean 之間的依賴關系。使用 IoC 實現對象之間的解耦和。
五、Spring工廠
5.1、簡單對象和復雜對象
5.1.1、簡單對象
簡單對象指的就是可以直接通過調用構造方法(new)創建出來的對象。
5.1.2、復雜對象
復雜對象指的就是不可以直接通過調用構造方法(new)創建出來的對象。比如JDBC的Connection對象、Mybatis的SqlSessionFactory對象。
5.2、Spring創建復雜對象的三種方式
5.2.1、FactoryBean
如果在applicationContext.xml配置文件中配置的class屬性是FactoryBean接口的實現類,那么通過id屬性獲得的是這個類所創建的復雜對象(底層會調用重寫的getObject()方法)。
public class MyFactoryBean implements FactoryBean
/** * 用于測試factoryBean */ @Test public void testFactoryBean(){ ClassPathXmlApplicationContext ctr = new ClassPathXmlApplicationContext("/applicationContext.xml"); Connection conn = (Connection) ctr.getBean("factoryBean"); System.out.println(conn); }
如果我不想獲得創建的復雜對象(Connection),想獲得普通的簡單對象(FactoryBean),我們僅僅只需在getBean(id)的前面加一個&即可。
import java.sql.Connection; import java.sql.DriverManager; import org.springframework.beans.factory.FactoryBean; /** * @Description * @Author XiaoLin * @Date 2021/2/24 19:47 */ public class MyFactoryBean implements FactoryBean
import java.sql.Connection; import org.junit.Test; import org.springframework.beans.factory.FactoryBean; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @Description * @Author XiaoLin * @Date 2021/2/24 19:50 */ public class MyFactoryBeanTest { /** * 用于測試復雜類型對象的創建 */ @Test public void testMyFactoryBeanTest(){ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/applicationContext.xml"); MyFactoryBean connection = (MyFactoryBean)applicationContext.getBean("&factoryBean");// 獲取普通的簡單對象FactoryBean,不獲取復雜的Connection對象 System.out.println(connection); } }
isSingleton()方法,如果返回值為true時,他只會創建一個對象,返回false時會創建多個對象,一般根據對象的特點來判斷返回true(SqlSessionFactory)還是false(Connection)。
FactoryBean是Spring中用于創建復雜對象的一種方式 也是Spring原生提供的,后面框架整合會大量運用。
5.2.2、實例工廠
使用FactoryBean的話有Spring的侵入,實現了FactoryBean接口,一旦離開了Spring,整個類都無法使用。
// 實例工廠 public class ConnectionFactory { public Connection getConnection(){ Connection conn = null; try { Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection("jdbc:mysql:///javaweb?characterEncoding=utf-8&useSSL=false","root","1101121833"); } catch (ClassNotFoundException | SQLException e) { e.printStackTrace(); } return conn; } }
5.2.3、靜態工廠
前面我們學了實例工廠,由于實例工廠的getConnection()方法是實例方法,需要由對象來調用,所以需要先創建對象然后再通過對象來調用方法。
而靜態工廠由于getConnection()方法是靜態方法,不需要由對象來調用,直接通過類進行調用。這就是實例工廠與靜態工廠最大的區別。
public class ConnectionStaticBeanFactory { public static Connection getConnection(){ Connection conn = null; try { Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection("jdbc:mysql:///javaweb?characterEncoding=utf-8&useSSL=false","root","1101121833"); } catch (ClassNotFoundException | SQLException e) { e.printStackTrace(); } return conn; } }
5.3、創建對象的細節
5.3.1、控制簡單對象的創建次數
控制簡單對象的創建次數我們只需要配置bean標簽的scope屬性值即可。他常用的有兩個值:
singleton:默認為單例模式,只會創建一個簡單對象。
prototype:每次都會創建一個新的對象。
5.3.2、控制復雜對象的創建次數
FactoryBean接口的isSingleton()方法的返回值來進行控制(如果沒有isSingleton()方法,那么還是通過scope屬性來進行控制):
返回true:只會創建一次。
返回false:每一次都會創建一個新的對象。
5.3.3、控制對象創建次數的原因
可以被大家共享的對象(SqlSessionFactory、各種Dao、Service)可以只創建一次,不可以被大家共享的對象(Connection、SqlSession、Controller)可以創建多次,控制對象創建次數的最大好處是可以節省不必要的內存浪費。
5.4、對象的生命周期
生命周期指的是一個對象的創建、存活、消亡的一個完整過程。由Spring來負責對象的創建、存活、銷毀。了解生命周期,有利于我們使用好Spring為我們創建的對象。
Spring幫我們創建的對象有三個階段:
創建階段
初始化階段
銷毀階段
5.4.1、創建階段
當 scope = “singleton” 時,Spring工廠創建的同時,對象會隨之創建。如果我們不想在Spring工廠創建的同時創建,想在獲取對象的時候創建,只需在配置文件的bean標簽添加一個lazy-init = true即可。
當 scope = “prototype” 時,Spring工廠會在獲取對象的同時創建對象。
5.4.2、初始化階段
Spring工廠在創建完對象后,會調用對象的初始化方法,完成對應的初始化操作。
初始化方法是由程序員根據需求提供初始化方法,由Spring工廠調用,最終完成初始化操作。他有兩種調用的方式:
實現InitializingBean接口(有Spring侵入的問題)。
提供一個普通方法并修改配置文件。
// 這個就是初始化方法,做一些初始化操作,Spring會進行調用 @Override public void afterPropertiesSet() throws Exception { // 初始化操作 }
由于實現InitializingBean接口存在Spring侵入的問題,所以Spring提供了另一個方法給我們進行初始化操作,那就是提供一個普通的方法,然后去配置文件中增加init-method="方法名"熟悉的配置即可。
public void init(){ System.out.println("我是初始化方法"); }
如果一個對象既實現了InitializingBean接口同時又提供了普通的初始化方法,那么兩個初始化方法都會執行,先執行的是InitializingBean接口的方法,再執行普通的初始化方法。
在執行初始化操作之前,會先進行屬性的注入,注入在前,初始化在后。
初始化需要做的操作一般是數據庫、IO、網絡操作。
5.4.3、銷毀階段
在工廠關閉之前,Spring會在銷毀對象前,會調用對象的銷毀方法,完成銷毀操作。
銷毀方法是程序員根據需求定義銷毀方法,由Spring工廠調用銷毀方法,完成銷毀操作。他也有兩種方法:
實現DisposableBean接口。
定義普通的銷毀方法在配置文件中配置。
public class Product implements InitializingBean, DisposableBean { @Override public void destroy() throws Exception { System.out.println("銷毀操作,資源釋放"); } }
public class Product implements InitializingBean, DisposableBean { public void MyDestory(){ System.out.println("自己定義的銷毀方法"); } }
銷毀方法的操作只適用于scope=“singleton”。
銷毀操作主要指的是一些資源的釋放操作。
5.5、Spring整合配置文件
一般來說像數據庫的一些配置信息我們都不會直接寫在代碼里面,會將他們抽取出來成一個配置文件,再利用Spring進行注入。我們只需要加入一個標簽即可完成。
Spring 容器
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。