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

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

}

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

  1. 控制反转Inversion of Control (IoC) 与 依赖注入Dependency Injection (DI)

    控制反转和依赖注入 控制反转和依赖注入是两个密不可分的方法用来分离你应用程序中的依赖性.控制反转Inversion of Control (IoC) 意味着一个对象不会新创建一个对象并依赖着它来完成工 ...

  2. 控制反转 (inversion of control)

    The inversion of control (IoC) pattern is abstract; it says that one should move dependency creation ...

  3. 设计模式之————依赖注入(Dependency Injection)与控制反转(Inversion of Controller)

    参考链接: 依赖注入(DI) or 控制反转(IoC) laravel 学习笔记 —— 神奇的服务容器 PHP 依赖注入,从此不再考虑加载顺序 名词解释 IoC(Inversion of Contro ...

  4. Spring 控制反转容器(Inversion of Control – IOC)

    系列教程 Spring 框架介绍 Spring 框架模块 Spring开发环境搭建(Eclipse) 创建一个简单的Spring应用 Spring 控制反转容器(Inversion of Contro ...

  5. 深入浅出spring IOC中三种依赖注入方式

    深入浅出spring IOC中三种依赖注入方式 spring的核心思想是IOC和AOP,IOC-控制反转,是一个重要的面向对象编程的法则来消减计算机程序的耦合问题,控制反转一般分为两种类型,依赖注入和 ...

  6. 转:深入浅出spring IOC中四种依赖注入方式

    转:https://blog.csdn.net/u010800201/article/details/72674420 深入浅出spring IOC中四种依赖注入方式 PS:前三种是我转载的,第四种是 ...

  7. Spring IOC(三)依赖注入

    本系列目录: Spring IOC(一)概览 Spring IOC(二)容器初始化 Spring IOC(三)依赖注入 Spring IOC(四)总结 目录 1.AbstractBeanFactory ...

  8. Spring IOC(五)依赖注入

    Spring IOC(五)依赖注入 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) 一.autowire 五种注入方式测试 ...

  9. 个人对【依赖倒置(DIP)】、【控制反转(IOC)】、【依赖注入(DI)】浅显理解

    一.依赖倒置(Dependency Inversion Principle) 依赖倒置是面向对象设计领域的一种软件设计原则.(其他的设计原则还有:单一职责原则.开放封闭原则.里式替换原则.接口分离原则 ...

  10. IOC-控制反转(Inversion of Control),也成依赖倒置(Dependency Inversion Principle)

    基本简介 IoC 亦称为 “依赖倒置原理”("Dependency Inversion Principle").差不多所有框架都使用了“倒置注入(Fowler 2004)技巧,这可 ...

随机推荐

  1. HDU 2824 简单欧拉函数

    1.HDU 2824   The Euler function 2.链接:http://acm.hdu.edu.cn/showproblem.php?pid=2824 3.总结:欧拉函数 题意:求(a ...

  2. man/info

    提示符方面,在linux当中,默认root的提示符为#,而一般身份用户的提示字符为$. 1.重新启动X Window 的快速按钮 一般来说,我们是可以手动来直接修改X Window 的配置文件的,不过 ...

  3. java线程的简单实现及方法

    java线程: 线程是一个程序内部的顺序控制流. cpu实际上在一个时间点上,只执行一个.只不过我们把cpu分成了多个时间片,由于速度很快,我们看起来像是多个线程.. 就像你的时间分成几片,这样 整体 ...

  4. [CareerCup] 17.12 Sum to Specific Value 和为特定数

    17.12 Design an algorithm to find all pairs of integers within an array which sum to a specified val ...

  5. Odoo Many2many 指定默认分组过滤

    在odoo里如果想单击某个菜单打开的页面是自带过滤的,可以在打开菜单的动作中添加默认过滤来实现,今天有同学在群里问,如何在Many2many的添加更多的弹出窗口中添加类似的过滤,其实是非常非常简单的, ...

  6. django基于正则的url匹配

    url.py views.py index.html detail.html 访问:

  7. 关于http协议的理解

    一.状态码 1.200:请求成功. 2.302:浏览器进行重定向. 3.304:资源已使用,即有缓存. 4.404:请求失败,请求的资源未在服务器上发现. 5.500:服务器端发生错误. 二.php获 ...

  8. JAVA生成二维码图片代码

    首先需要导入 QRCode.jar 包 下载地址看这里   http://pan.baidu.com/s/1o6qRFqM import java.awt.Color;import java.awt. ...

  9. 安装redis,执行make test时遇到You need tcl 8.5 or newer in order to run the Redis test

    安装他yum install tcl

  10. vbox下Oracle Enterprise liunx5.4虚拟机安装10G RAC实验(一)

    1.配置第一个虚拟机 1.1 安装后的登录界面 1.2 第1台机器(单数据配置方面) 1.2.1 验证安装包 1.2.2 修改内核参数 1.2.3添加安全限制 1.2.4关闭防火墙 1.2.5添加用户 ...