Spring 之 factory工廠模式的解耦
在實際開發中我們可以把三層的物件都使用配置檔案配置起來,當啟動伺服器應用載入的時候,讓一個類中的
方法通過讀取配置檔案,把這些物件創建出來並存起來。在接下來的使用的時候,直接拿過來用就好了。
那麼,這個讀取配置檔案,建立和獲取三層物件的類就是工廠。
上一小節解耦的思路有 2 個問題:
1、存哪去?
分析:由於我們是很多物件,肯定要找個集合來存。這時候有 Map 和 List 供選擇。
到底選 Map 還是 List 就看我們有沒有查詢需求。有查詢需求,選 Map。
所以我們的答案就是
在應用載入時,建立一個 Map,用於存放三層物件。
我們把這個 map 稱之為容器。
2、還是沒解釋什麼是工廠?
工廠就是負責給我們從容器中獲取指定物件的類。這時候我們獲取物件的方式發生了改變。
原來:
我們在獲取物件時,都是採用 new 的方式。是主動的。
現在:
我們獲取物件時,同時跟工廠要,有工廠為我們查詢或者建立物件。是被動的
這就是
控制反轉-Inversion Of Contr
![
程式碼的演示:
曾經程式碼中的問題分析-----------------------------》
模擬一下:
建立新的module:-----》 介面
這些都是 之前做過的 實現類 多型new的現象 就是要避免 和 解耦的 可以用的 優化
業務層 在呼叫 持久層 也在 表現層 到 持久層 都會共有的 問題s
我們maven的座標啊 地方就是 jar 的方式 (沒有座標的)沒有瀏覽器與web
在模擬一個表現層 (實際裡這裡就是一個 servlet)
我們呈現 了好多的依賴 這就是我們要解決的
maven的pom 檔案還是 有個 mysql 就行
mysql
mysql-connector-java
5.1.6
----dao裡
package com.fhw.dao;
/* 賬戶持久層介面*/
public interface IAccountDao {
/* 模擬儲存賬戶的操作*/
void saveAccount();
}
package com.fhw.dao.impl;
import com.fhw.dao.IAccountDao;
/* 賬戶持久層實現類*/
public class IAccountDaoImpl implements IAccountDao {
public void saveAccount() { // System.out.println("儲存了賬戶"); }
}
-seervice 裡
package com.fhw.service;
/*賬戶 :業務層的介面
- /
public interface IAcconutService {
/*- 模擬儲存賬戶
*/
void saveAccount();
}
----package com.fhw.service.impl;
- 模擬儲存賬戶
import com.fhw.dao.IAccountDao;
import com.fhw.factory.BeanFactory;
import com.fhw.service.IAcconutService;
public class IAccountServiceImpl implements IAcconutService{
/private IAccountDao accountDao=new IAccountDaoImpl();/
IAccountDao accountDao= (IAccountDao) BeanFactory.getBean("accountDao");
public void saveAccount() {
accountDao.saveAccount();
System.out.println();
}
}
properties配置檔案
accountService =com.fhw.service.impl.IAccountServiceImpl
accountDao=com.fhw.dao.impl.IAccountDaoImpl
-----核心的 ``factory工廠類------------
``package com.fhw.factory;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
/*
-
c建立一個 Bean物件
-
Bean 在計算機英語裡是 可重用元件
-
javaBean: 不同於java實體類 大於實體類 java編寫的可重用元件
-
javabean 來 建立 我們的 Service 與到的物件
-
1: 需要 配置檔案 來 配置Service與 dao
*配置內容 :唯一標示= 全限定類名 就是 key =value 的配置檔案 -
xml 或 propertise 都行
-
2:通過配置檔案的內容來 反射建立物件
-
現在 選用簡單 propertise 應用
-
*/
public class BeanFactory {
//定義一個 properties 物件
private static Properties props;
//優化 改造 定義map容器 用於存放我們要建立的 物件
private static Map<String ,Object> beans;
// static 為物件 賦值
static{
try {
// 例項化物件
props = new Properties();
//還是類載入器 :反射解耦 方便多了
InputStream in=BeanFactory.class.getClassLoader().getResourceAsStream(“bean.properties”);
props.load(in);
//例項化容器
beans=new HashMap<String,Object>();
//取出配置檔案裡所有的 key
Enumeration keys = props.keys();
//遍歷列舉
while (keys.hasMoreElements()){
String key = keys.nextElement().toString();
//根據key 來獲取value
String beanpath = props.getProperty(key);
//反射建立物件
Object value=Class.forName(beanpath).newInstance();
beans.put(key,value);
}} catch (Exception e) {// 這裡若 讀取失敗 //直接throw 指定異常 給資訊即可 throw new ExceptionInInitializerError("初始化properties 失敗!"); }
}
/**
- 根據bean 的名稱獲取 物件 是單例模式
- @param beanName
- @return
/
public static Object getBean(String beanName){
return beans.get(beanName);
}
/ public static Object getBean(String beanName){//寫活 : Object 或 T泛型 get那個 引數指定
Object bean=null;
try {
String beanPath = props.getProperty(beanName);
//反射獲取 到
bean = Class.forName(beanPath).newInstance();
}catch (Exception e){
e.printStackTrace();
}
return bean;
}*/
}
/*當單例放到方法裡
定義方法的時候 呼叫方法 就重新載入 也是初始化 所以也能保證每次初始化-----》 單例也可以----》但是BeanFactory的就是反射的建構函式NewInstance
-----BeanFactory 建立物件是的反射 裡的newInstance()=》這句 話的出場–每次都會呼叫 預設 建構函式 建立物件
所以每次都是 新的 -------》Spring也 不能識別 只能的java GC 機制 來回收
現在就 只能用一次 newInstance()要保留=》存到那=》容器
於是我們就要一個Map 裡的key value ----------*/