程序的耦合:
程序間的依賴關係或者是調用者和被調用者之間的依賴關係
高耦合
低耦合
開發的原則:
編譯時依賴,運行時不依賴。
(團隊開發中的時候不需要等待別人)
解決依賴關係:
使用反射創建類對象 Class.forName(…)
->新問題:若換個驅動就要改源碼,改源碼的話如果是上線的web項目就需要停掉服務器更改
->使用配置文件,通過讀取配置文件來反射創建類對象
先寫一個配置文件:bean.prperties
CUSTOMERSERVICE=com.itheima.service.impl.CustomerServiceImpl
CUSTOMERDAO=com.itheime.dao.impl.CustomerDaoimpl
pubic class BeanFactory{
//1.定義一個Properties對象
private static Properties props=null;
//2.使用靜態代碼塊給對象賦值
static{
try{
//第一種方法使用類加載器來處理
InputStream in =BeanFactory.class.getClassLoader() .getResourceAsStream("bean.properties");
//第二種方法 但是這種方法,在發佈完應用後會出現找不到配置文件的問題、
因爲web工程一旦發佈,就沒有src文件夾了。發佈的時web-inif
InputStream in =new FileInputStream("src/bean.properties");//可通過打印props.get("CUSTOMERDAO");測試
props.load(in);
}catch(Exception e){
throw new ExceptionInInitializerError("讀取配置文件失敗!"+e);
}
}
其他方法:
利用bundle讀取文件,注意:
1.它只能用於讀取properties文件
2.只能用於讀取,不能用於寫入
3.只能用於讀取類路徑下的,不在類路徑下的讀取不了
方法的參數是按照包名.類名的方式寫的,所以請不要寫上擴展名
code:
private static ResourceBundle bundle=ResourceBundle.getBundle("bean");
/**根據bean的名稱創建類對象:
*/
public static Object getBean(String beanName){
try{
//1.讀取配置文件,跟beaName獲取全限定類名
String beanPath=bundle.getString(beanName);
return Class.forName(beanPath).newInstance();
}catch(Exception e){
throw new RuntimeException(e);
}
}
注意
但是上面這種方法存在的一個問題就是我們的線程安全問題,就拿servlet來說,在不同的進程中,每一次調用時,像碰到i++這種每一次調用就會使其值變化。也就是理解爲:即是當我有類成員變量的時候,使用單例模式訪問,其必然會導致變量值的更改,即另一個類成員訪問到的是上一個對象做出了改變的成員值,
-
但在這個方法中使用的是方法成員,方法成員是沒有線程安全問題的,所以在沒有線程安全問題的情況下,使用單例模式更好,不用創建那麼多的對象實例
-
在上面的反射創建類對象的時候,我們生成了太多對象實例了,即在配置文件中有很多值的話,將會創建很多的對象。
所以在這裏我們使用map來存儲返回的類對象,也便於查找。
private static Map<String,Object> beans=new HashMap<String,Object>();
//使用靜態代碼塊初始化map
static{
try{
//1.讀取配置文件中所有的配置:key的部分
Enumeration<String> keys=bundle.getKeys();
//2.遍歷keys
while(keys.hasMoreElements()){
//3.取出一個key
String key=keys.nextElement();
//4.根據key獲取beanPath
String beanPath=bundle.getString(key);
//5.根據beanPath反射創建類對象
Object value=Class.forName(beanPath).newInstance();
//6.把key和value存入map中
beans.put(key,value);
}
}catch(Exception e){
throw new ExceptionInInitializerError("創建容器失敗,程序停止執行");
}
}
//根據Bean的唯一標識符獲取對象
public static Object getBean(String beanName){
return beans.get(beanName);
}