程序的耦合:
程序间的依赖关系或者是调用者和被调用者之间的依赖关系
高耦合
低耦合
开发的原则:
编译时依赖,运行时不依赖。
(团队开发中的时候不需要等待别人)
解决依赖关系:
使用反射创建类对象 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);
}