业务场景: 客户使用的是 oracle,但是我们开发用的是 mysql,或者程序需要兼容不同的数据库时,因为底层数据库的操作命令不同,所以我们需要对我们的程序的DAO层的实现层进行解耦,来适配不同的数据库。
原理解析
- 在src下面新建一个
application.xml
的配置文件(该文件配置使用哪中数据库的Dao层实现)
示例: - 然后在DAO实现层中实现不同版本数据库的操作命令,示例如下:
- 新建一个 BeanFactory.java类 来 接受一个字符串并 返回该类的实例。(通过该类 去创建不同数据库 的具体的 DAO实现层的对象)
示例:public class BeanFactory { public static Object createObject(String name) { return null; } }
- BeanFactory 是根据 application.xml中的类名 用反射来创建相关的对象。
示例demo
加入我们现在需要使用mysql 的 数据库
- application.xml 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="CategoryDao" class="cn.itcast.store.dao.daoImp.CategoryDaoImp"/>
<bean id="UserDao" class="cn.itcast.store.dao.daoImp.UserDaoImp"/>
<bean id="ProductDao" class="cn.itcast.store.dao.daoImp.ProductDaoImp"/>
</beans>
- BeanFactory.java工厂类的实现
package cn.itcast.store.utils;
import java.io.InputStream;
import java.sql.SQLException;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
public class BeanFactory {
//解析XML
public static Object createObject(String name) {
try {
//通过传递过来的name获取application.xml中name对应的class值
//获取到Document对象
SAXReader reader=new SAXReader();
//如果获取application.xml文件的输入流 (application.xml必须位于src下)
InputStream is=BeanFactory.class.getClassLoader().getResourceAsStream("application.xml");
Document doc=reader.read(is);
//通过Document对象获取根节点 beans
Element rootElement = doc.getRootElement();
//通过根节点获取到根节点下所有的子节点 bean,返回集合
List<Element> list = rootElement.elements();
//遍历集合,判断每个元素上的id的值是否和当前的name一致
for (Element ele : list) {
//ele相当于beans节点下的每个bean
//获取到当前节点的id属性值
//如果一致,获取到当前元素上class属性值
String id=ele.attributeValue("id");
if(id.equals(name)){
String str=ele.attributeValue("class");
//通过反射创建对象并且返回
Class clazz=Class.forName(str);
//利用class值通过反射创建对象返回
return clazz.newInstance();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
- 在业务层 CategoryServiceImp.java 使用 该工具类(假如我么你要查询 所有的分类,和 增加分类的功能)
public class CategoryServiceImp implements CategoryService {
CategoryDao CategoryDao=(CategoryDao)BeanFactory.createObject("CategoryDao");
@Override
public List<Category> getAllCats() throws Exception {
return CategoryDao.getAllCats();
}
@Override
public void addCategory(Category c) throws Exception {
//本质是向MYSQL插入一条数据
CategoryDao.addCategory(c);
//更新redis缓存
Jedis jedis = JedisUtils.getJedis();
jedis.del("allCats");
JedisUtils.closeJedis(jedis);
}
}
在 用dom4j解析 application的过程中, 根据传入的 字符串 找到 对应的 id 和 该字符串相等的 dom,在获取该dom的 class属性,得到该类的全名,通过 Class.forName(类名);来创建 类字节码对象,并用newInstance创建相应的实例并返回。