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


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

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

    }

  • 相关阅读:
    面向对象三大特性:封装,继承,多态(三、多态的进一步讲解)
    面向对象三大特性:封装,继承,多态(二、多态)
    面向对象三大特性:封装,继承,多态(一,封装和继承)
    zookeeper+dubbo+demo
    Eclipse常见版本和JDK常用版本对应关系
    Navicat 连接MySQL 8.0.11 出现2059错误
    Neo4j elk Elasticsearch kibana kettle
    jvm垃圾回收机制GC
    jvm 这我就能会了 擦
    spring的4种事务特性,4种隔离级别,7种传播行为
  • 原文地址:https://www.cnblogs.com/345214483-qq/p/4174368.html
Copyright © 2020-2023  润新知