在一個項目中實現解耦,需要用到工廠模式實現解耦
一個創建Bean對象的工廠,它就是創建Service、Dao對象的工廠
1>需要配置文件來配置Service、Dao(配置的內容:唯一標識=全限定類名)
2>通過讀取配置文件中配置內容,反射創建對象(配置文件可以是xml或者是properties)
使用工廠模式實現解耦(抽取重用方法)
配置文件:
admainDao=tj.ustb.studentFunding.Dao.AdmainDao.java
admainService=tj.ustb.studentFunding.Service.AdmainService.java
創建BeanFactory工廠類,通過傳入的參數BeanName,調用創建的靜態Properties對象來獲取配置文件中的全類名,獲取後通過Class.forName()獲取加載器,調用創建實例方法獲取實例對象。
public class BeanFactory {
//定義一個Properties對象
private static Properties props;
//使用靜態代碼快爲Properties對象賦值
static{
//實例化對象
Properties props = new Properties();
InputStream is = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
try {
props.load(is);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/*
* 根據Bean的名稱獲取Bean對象
* */
public static Object getBean(String BeanName){
Object bean = null;
try {
//通過key值得到對應Bean的全類名
String beanPath = props.getProperty(BeanName);
//通過全類名獲取該類的加載器並且調用創建實例方法獲取Bean
bean = Class.forName(beanPath).newInstance();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return bean;
}
}
因此,在耦合度高的類中調用BeanFactory類中的靜態方法獲取實例,
public class AdmainService {
AdmainDao admainDao = (AdmainDao)BeanFactory.getBean("admainDao");
/*
* 登錄功能
* */
public Admain login(Admain form) throws StudentException{
Admain admain = admainDao.findByAdmainPassword(form);
if(admain == null) throw new StudentException("賬號不存在或密碼錯誤");
return admain;
}
}
此時,通過調用的newInstance方法生成的實例是多實例的,因此需要通過將反射調用newInstance()得到的實例放入Map,讓其成爲單實例對象。在BeanFactory類的靜態代碼塊中,初始化容器beans(beans的本質是一個Map,key爲Bean的類名,value爲Bean實例)。通過配置文件獲取所有key值,遍歷枚舉獲得對應的key,props.getProperty(key)獲取對應的全類名,使用類加載器將全類名作爲參數,然後調用構造實例的方法,得到相應的實例。最後將key值和實例存入beans中。
public class BeanFactory {
//定義一個Properties對象
private static Properties props;
private static Map<String,Object> beans;
//使用靜態代碼快爲Properties對象賦值
static{
//實例化對象
Properties props = new Properties();
InputStream is = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
try {
props.load(is);
//實例化容器
beans = new HashMap<String,Object>();
//通過Properties類對象調用keys方法得到枚舉類集合
Enumeration keys = props.keys();
//遍歷枚舉
while(keys.hasMoreElements()){
String key = keys.nextElement().toString();
String path = props.getProperty(key);
//反射創建對象
Object value = null;
try {
value = Class.forName(path).newInstance();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//將key value存入容器中
beans.put(key, value);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/*
* 根據Bean的名稱獲取Bean對象
* */
public static Object getBean(String BeanName){
return beans.get(BeanName);
}
}
因此出現了IOC容器,IOC:控制反轉,將創建對象的權利交給框架,因此這是框架的重要特徵,其包括依賴注入(DI)和依賴查找(DL)