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);
}
}
Sring控制反转(Inversion of Control,Ioc)也被称为依赖注入(Dependency Injection,DI)原理用反射和代理实现的更多相关文章
- 控制反转Inversion of Control (IoC) 与 依赖注入Dependency Injection (DI)
控制反转和依赖注入 控制反转和依赖注入是两个密不可分的方法用来分离你应用程序中的依赖性.控制反转Inversion of Control (IoC) 意味着一个对象不会新创建一个对象并依赖着它来完成工 ...
- 控制反转 (inversion of control)
The inversion of control (IoC) pattern is abstract; it says that one should move dependency creation ...
- 设计模式之————依赖注入(Dependency Injection)与控制反转(Inversion of Controller)
参考链接: 依赖注入(DI) or 控制反转(IoC) laravel 学习笔记 —— 神奇的服务容器 PHP 依赖注入,从此不再考虑加载顺序 名词解释 IoC(Inversion of Contro ...
- Spring 控制反转容器(Inversion of Control – IOC)
系列教程 Spring 框架介绍 Spring 框架模块 Spring开发环境搭建(Eclipse) 创建一个简单的Spring应用 Spring 控制反转容器(Inversion of Contro ...
- 深入浅出spring IOC中三种依赖注入方式
深入浅出spring IOC中三种依赖注入方式 spring的核心思想是IOC和AOP,IOC-控制反转,是一个重要的面向对象编程的法则来消减计算机程序的耦合问题,控制反转一般分为两种类型,依赖注入和 ...
- 转:深入浅出spring IOC中四种依赖注入方式
转:https://blog.csdn.net/u010800201/article/details/72674420 深入浅出spring IOC中四种依赖注入方式 PS:前三种是我转载的,第四种是 ...
- Spring IOC(三)依赖注入
本系列目录: Spring IOC(一)概览 Spring IOC(二)容器初始化 Spring IOC(三)依赖注入 Spring IOC(四)总结 目录 1.AbstractBeanFactory ...
- Spring IOC(五)依赖注入
Spring IOC(五)依赖注入 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) 一.autowire 五种注入方式测试 ...
- 个人对【依赖倒置(DIP)】、【控制反转(IOC)】、【依赖注入(DI)】浅显理解
一.依赖倒置(Dependency Inversion Principle) 依赖倒置是面向对象设计领域的一种软件设计原则.(其他的设计原则还有:单一职责原则.开放封闭原则.里式替换原则.接口分离原则 ...
- IOC-控制反转(Inversion of Control),也成依赖倒置(Dependency Inversion Principle)
基本简介 IoC 亦称为 “依赖倒置原理”("Dependency Inversion Principle").差不多所有框架都使用了“倒置注入(Fowler 2004)技巧,这可 ...
随机推荐
- IOS 蓝牙相关-BabyBluetooth蓝牙库介绍(4)
BabyBluetooth 是一个最简单易用的蓝牙库,基于CoreBluetooth的封装,并兼容ios和mac osx. 特色: 基于原生CoreBluetooth框架封装的轻量级的开源库,可以帮你 ...
- GO语言练习:struct基础练习
1.代码 2.运行 1.代码 package main import "fmt" type Rect struct { x, y float64 width, height flo ...
- Android基于XMPP的即时通讯2-文件传输
本文是在上一篇博文Android基于XMPP的即时通讯1-基本对话的基础上,添加新的功能,文件传输 1.初始化文件传输管理类 public static FileTransferManager get ...
- linux pidof
转载:http://blog.51osos.com/linux/linux-pidof-command/ 什么是pidof命令? #man pidof中的解释: pidof — find the pr ...
- android api汇集
参考文章: 知乎-想写个 App 练手,有什么有趣的 API 接口推荐吗? 使用 Espresso 和 Dagger 测试网络服务 http://developer.simsimi.com/apps# ...
- django基于正则的url匹配
url.py views.py index.html detail.html 访问:
- java程序实现删除本地文件
import java.io.File; public class Test { public static void main(String args[]) { Test t = new Te ...
- iOS 状态栏黑色背景白色字体
一. 状态栏背景(黑色)的设置 1.在有导航栏的情况下,给导航栏设置一个像素为44的背景图片即可 [[UINavigationBar appearance] setBackgroundImage:[U ...
- 【iCore3 双核心板】例程九:ADC实验——电源监控
实验指导书及代码包下载: http://pan.baidu.com/s/1o7wSEO6 iCore3 购买链接: https://item.taobao.com/item.htm?id=524229 ...
- CentOS 6.6 安装 PHP Memcached 扩展
PHP 的 Memcached扩展使用了 libmemcached 库提供的 api 与 memcached 服务端进行交互.它同样提供了一个 session 处理器(memcached). PHP ...