spring -3 建立複雜物件及控制物件的建立次數
目錄
什麼是複雜物件?
簡單物件:直接通過new的方式可以直接建立的。Person per = new Person();
複雜物件:不能直接通過new構造方法來建立的。
例如:Connection物件,SqlSessionFactory物件。
spring工廠建立複雜物件的3種方式:
1,實現spring提供的FactoryBean介面。
public class ConnectionFactory implements FactoryBean<Connection> { static { try { Class.forName("com.mysql.cj.jdbc.Driver"); } catch (ClassNotFoundException e) { e.printStackTrace(); } } //獲得物件的程式碼 @Override public Connection getObject() { Connection conn = null; try { conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/demo?serverTimezone=UTC","root","1234"); } catch (SQLException e) { e.printStackTrace(); } return conn; } //獲得物件的class型別 @Override public Class<?> getObjectType() { return Connection.class; } //預設是true,表示獲取的是單例 // 是否是單例物件 @Override public boolean isSingleton() { return false; } }
XML檔案中:
<bean id="conn" class="begin.ConnectionFactory"></bean>
test程式碼:
/** * 測試:建立複雜物件 */ @org.junit.Test public void test4(){ ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml"); Connection conn = (Connection) ctx.getBean("conn"); System.out.println(conn); }
結果:
細節:Connection物件是不可公用的,而SqlSessionFactory是可以公用的。
配置檔案中:如果使用和普通物件一樣的配置方法,返回的就是複雜物件。若想要原來的物件,就要getBean("&conn").就會返回原來的那個類的物件。而不是由那個類建立的物件。
spring如何實現的?(明明我寫的是得到class類的方法,給我的確是這個類建立的物件)。
原因: if(bean instanceof FactoryBean) return bean.getObject();
總結:spring建立複雜物件的一種方式,spring原生提供,spring衍生框架中,大量應用了FactoryBean介面。
2,例項工廠:
避免了spring框架的侵入;整合遺留系統(有class檔案,而原始碼沒有或者不能輕易修改)。
顧名思義:將工廠例項化,建立物件。
例如:
public class ConectionFactory1 {
public Connection getObject() {
Connection conn = null;
try {
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/demo?serverTimezone=UTC","root","1234");
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
}
XML檔案中:
<bean id="connFactory" class="begin.ConectionFactory1"></bean>
<!-- 指定工廠物件,工廠得到物件方法-->
<bean id="conn" factory-bean="connFactory" factory-method="getObject"></bean>
結果:
總結:返回物件類不需要指定class,需要指定factory-bean和factory-method。
3,靜態工廠
建立複雜物件是個靜態工廠類,建立方法是靜態方法。
public class ConectionFactory1 {
public static Connection getObject() throws ClassNotFoundException {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection conn = null;
try {
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/demo?serverTimezone=UTC","root","1234");
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
}
XML檔案中:
<bean id="conn" class="begin.ConectionFactory1" factory-method="getObject"></bean>
結果:
spring控制物件的建立次數:
spring為什麼要控制物件的建立次數呢?
比如所一個UserService只需要一個,一個UserDao也只需要一個(因為實現的功能是一樣的,過多的會產生更大記憶體開銷和冗餘)。
如何控制:
1,實現FactoryBean介面後,之中有一個isSingleton方法。就是制定建立的物件是否是單例(即自始至終得到的物件只有一個)。return true。即可。
2,在XML檔案bean標籤中有一個scope屬性,一個是prototype(原型表示建立多個一樣的),一個是singleton(單例)。
好處:節省不必要的記憶體開銷。
什麼樣的物件只建立一次呢?
各種dao和service。SqlSessionFactory和DispatchServlet(springMVC)的各種重量級資源(肯定都是執行緒安全的)。