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

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. Maven with Multi-module

    Well, A project made of multi modules. For example, the hongten-security project, the structure of t ...

  2. 在配置IIS负载均衡时,引起的一系列问题

    问题一: IIS中要上传文件的路径是另一台服务器的地址(如:本机IP是192.168.0.100,文件保存的路径在://192.168.0.101/images/folder),在上传时抛出异常: A ...

  3. (转)如何将数据库从SQL Server迁移到MySQL

    一.迁移Database Schema. 首 先使用Sybase Powerdesigner的逆向工程功能,逆向出SQL Server数据库的物理模型.具体操作是在Powerdesigner中选择“F ...

  4. 李洪强iOS经典面试题129

    1. 怎么解决缓存池满的问题(cell) ios中不存在缓存池满的情况,因为通常我们ios中开发,对象都是在需要的时候才会创建,有种常用的说话叫做懒加载,还有在UITableView中一般只会创建刚开 ...

  5. 关于GreenOdoo的一个Bug

    动态创建字段的时候,虽然字段已经创建,但是显示的时候会报没有新创建的字段错误: 但是原版是没有任何问题的,记录一下.

  6. javascript阻止事件冒泡的兼容写法及其相关示例

    //阻止事件冒泡的兼容写法 function stopBubble(e){ //如果提供了事件对象,则是一个非IE浏览器 if(e && e.stopPropagation) //因此 ...

  7. 火狐插件 Http请求利器 Httprequester

    搜索并且下载Httprequester

  8. js控制只允许输入数字

    avascript 只允许输入数字有很多方法,总结如下 1,只允许输入数字和小数点. <input onKeypress="return (/[\d.]/.test(String.fr ...

  9. original.txt和提交的页面输出的文字的混合文件

    如果从准确的角度来说,那PHP文档是最准确的,因为它很简练的列出了实现文本类文件触发下载所需要的三条语句,以PDF为例就是: 代码如下:// We'll be outputting a PDF hea ...

  10. IOS第15天(3,事件处理,手势处理)

    7> 手势识别    使用UIImageView原因:之前既能看见图片,又能监听点击的只有UIButton,学了手势,我们的UIImageView也可以.    * tap(代理:左边不能点,右 ...