Sring控制反转(Inversion of Control,Ioc)也被称为依赖注入(Dependency Injection,DI)原理用反射和代理实现

时间:2021-01-26 17:07:57

首先我有一个数据访问层接口:

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);
 }

}