首先我有一个数据访问层接口:
public interface StudentDao {
void save(Student stu);
}
和实现类:
1.mysql实现类
public class StudentDaoImplByMySql implements StudentDao{
public void save(Student stu){
System.out.println(stu.getName()+"被Orcacle保存了!");
}
}
2.oracle实现类
public class StudentDaoImplByOrcacle implements StudentDao{
public void save(Student stu){
System.out.println(stu.getName()+"被MySql保存了!");
}
}
然后我的业务逻辑层接口:
public interface StudentService {
public void add(Student stu);
}
我的业务逻辑层实现类(里面有一个数据访问层的接口):
public class StudentServiceImpl implements StudentService {
private StudentDao dao;
public void add(Student stu) {
dao.save(stu);
}
public StudentDao getDao() { return dao; }
public void setDao(StudentDao dao) { this.dao = dao; }
}
然后主要的是我的工具类Application:
public class Application {
private Map<String, Object> map = null;
public Application() throws IOException, InstantiationException, IllegalAccessException, ClassNotFoundException, DocumentException, IntrospectionException, IllegalArgumentException, InvocationTargetException {
map = new HashMap<String, Object>();
// 使用dom4J读取XML文件
SAXReader read = new SAXReader();
// 读取文件
Document document = read.read(Application.class.getClassLoader().getResourceAsStream("app.xml"));
// 获取根节点
Element rootElement = document.getRootElement();
// 获取根节点下的子节点集合
List<Element> elements = rootElement.elements();
for (Element element : elements) {
// id为标识名(随意起),class为类型,根据id值找到class
String id = element.attribute("id").getValue();
String clas = element.attribute("class").getValue();
// 得到Class类名后得到这个类的实例对象
Object object = Class.forName(clas).newInstance();
// 继续循环子节点下的子节点
for (Element element2 : (List<Element>) element.elements()) {
// studentServiceImpl实现类里有一个属性是studentDao层的接口
// 这个name的值必须和studentServiceImpl的属性名一致
String name = element2.attribute("name").getValue();
// ref指向dao的一个实现类StudentDaoImpl的标识名(也就是id)
String ref = element2.attribute("ref").getValue();
// 属性描述符 参数一个是接口的别名:StudentDao dao
// 一个是实现类的实例cn.jnti.dao.StudentDaoImplByMySql
PropertyDescriptor pd = new PropertyDescriptor(name,object.getClass());
// WriteMethod就是public void setDao(StudentDao dao)的方法,注入就是这样来的
Method writeMethod = pd.getWriteMethod();
// 由于我的map集合里key值为id,value值为对象,此时的ref为StudentDaoImplByMySql
// StudentDaoImplByMySql正是集合里cn.jnti.dao.StudentDaoImplByMySql对象的key
// object是对象,map.get(ref)拿到此对象的实例
writeMethod.invoke(object, map.get(ref));
}
//map集合里放的全部是代理对象
Handle han = new Handle(object);
//返回一个代理对象
object = Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces(), han);
//把代理对象放入集合
map.put(id, object);
}
}
public Object getBean(String name) {
//返回的是一个代理对象
return map.get(name);
}
}
*************
我的handle类:
*************
public class Handle implements InvocationHandler{
private Object obj;
public Handle(Object obj) {
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//过滤掉service层的执行前和执行后方法
if(method.toString().contains("Service")){
return method.invoke(obj, args);
}
//只在dao层添加执行前和执行后方法
doBefor();
Object object=method.invoke(obj, args);
doAfter();
return object;
}
private void doBefor() { System.out.println("执行之前!"); }
private void doAfter() { System.out.println("执行之后"); }
}
***************
我的app.xml
****************
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="StudentDaoImplByMySql" class="cn.jnti.dao.StudentDaoImplByMySql"></bean>
<bean id="StudentDaoImplByOrcacle" class="cn.jnti.dao.StudentDaoImplByOrcacle"></bean>
<bean id="StudentServiceImpl" class="cn.jnti.service.StudentServiceImpl">
<property name="dao" ref="StudentDaoImplByMySql"></property>
</bean>
</beans>
****************
我的测试类:
public class TestStudent {
StudentService service=null;
@Test
public void studentAdd() throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, DocumentException, IntrospectionException, InvocationTargetException{
Application app=new Application();
service = (StudentService) app.getBean("StudentServiceImpl");
Student stu=new Student("小明",18);
//返回的是一个代理对象,调用代理对象的方法时里面会走doBefor,和doAfter
service.add(stu);
}
}