Spring的Ioc模拟实现
关于IOC:我们讲个故事吧!
有一个厨师,他在做一道菜的时候需要某种调味料(bean),可是他正好没有那瓶调味料(bean),这个时候他就必须去制作一瓶调味料(bean)出来。(这就像我们平时需要对象的时候一样:UserDao userdao=new UserDaoImpl)这个时候厨师的工作就不得不跟制作调味料联系起来,这就是所谓的“耦合”。(耦合程度高通说来说就是,我没了你我活不了了。);
这个时候IOC里的控制反转出来了,它提出,开辟一个仓库(容器),里面放着各种各样的调味料(bean),当你需要某种调味料(bean)的时候只要给出调味料的名字(beanName)就可以直接去拿取,代码类似这样:(UserDao user=仓库.get("调味料名字"));这样你就可以直接拿到了调味料 (bean)而不用等到你没有的时候再去制作一瓶出来。这就是所谓的将控制权转移出来,它将生产调味料(bean)的工作直接让仓库(容器)来制作(生产);
接下来依赖注入出来了,它就更加地强大的了,它提出厨师只要有一个瓶子(private UserDao userdao),并且将瓶子盖打开(方法:setUserDao( UserDao userdao){this.userdao=userdao}即提供对于的set方法 )再给瓶子贴上一个标签注明要放什么材料(在xml文件中配置一下<property name="userdao",ref="xxbean"),那么这个时候你什么都不用做了,仓库(容器)会自动派人帮你将你所需的调味料(bean)放入到瓶子中 ;当你想换另一种调味料的时候只要将瓶子上的标签改成其他比如胡椒粉(这时要在xml文件中更改一下ref的bean就行了),依赖注入提高了代码的灵活性,你需要替换类的实现的时候,不需要去修改只要在xml配置文件里修改一下就行了;
总结一下我的总结:IOC的主要目的就是实现解耦!解耦!解耦!重要的事情说三遍.由厨师的列子来说就是.我是一个厨师我只做菜,我不做调味料~~我不是一个做调味料的,我不跟制作调味料有那么大的关系. IOC的出现,厨师只要安心做好自己的事情(做菜),需要调味料直接去仓库拿取就行了!那么这样厨师跟调味料的制作之间的关系就分离开来了,这就是解耦!解耦!解耦!使两个东西的关系没那么紧密.
模拟IOC的实现,主要使用的技术是java的反射机制(模拟使用的是架构分为dao层,service层,controller层):
注:欢迎各位大佬的指点,小弟也在学习,说得不好多多包涵~
一.编写dao类,用于测试:
public interface IocDao {
public void sayhello(); //一个用来测试的接口
}
二.编写dao的实现类:
public class IocDaoImpl implements IocDao {
@Override
public void sayhello() {
// TODO Auto-generated method stub
System.out.println("hello word");//实现我们的dao接口里的方法
}
}
三.编写service类:
public interface IocDaoService {
public void sayhello();//业务类接口,这里就跟dao一样
}
四.编写service的实现类:
public class IocDaoServiceImpl implements IocDaoService {
private IocDao iocDao; //创建一个接口.
public IocDao getIocDao() {
return iocDao;
}
//编写IocDao接口对应的set方法用于依赖注入
//依赖注入的方式有三种:接口注入,构造方法注入,set注入;
//此处为set注入
public void setIocDao(IocDao iocDao) {
this.iocDao = iocDao;
}
@Override
public void sayhello() {
// TODO Auto-generated method stub
iocDao.sayhello();//调用接口方法
}
}
五.编写bean.xml配置文件.(这里的i你可以看成是IocDaoImpl类,iocService看成IocDaoServiceImpl,iocDao这是IocDaoServiceImpl里的一个属性,这个属性传入的参数值为“i”);
<beans>
<bean id="i" class="com.hck.dao.impl.IocDaoImpl"/>
<bean id="iocService" class="com.hck.service.impl.IocDaoServiceImpl">
<property name="iocDao" ref="i"></property>
</bean>
</beans>
六.编写工厂接口.
//模拟ClassPathXmlApplicationContext实现的一个接口BeanFactory
public interface BeanFactory {
public Object getBean(String beanName);
}
七.编写ClassPathXmlApplicationContext去读取配置文件,并且根据bean.xml里的配置对象去生成各种bean,完成其中的注入工作.(最重要的部分Ioc的实现原理),一字一句都有注释
//模拟ClassPathXmlApplicationContext去读取配置文件
public class ClassPathXmlApplicationContext implements BeanFactory {
//定义map集合来存放bean.xml里的bean的id跟其对应的实例化对象
//<bean id="i" class="com.hck.dao.impl.IocDaoImpl"/>
//那么类似的存放bean.put("i",new IocDaoImpl());这样子.
Map<String, Object> beans=new HashMap<String,Object>();
public ClassPathXmlApplicationContext(String xmlPath){
try {
//创建SAXBuilder对象解析文档
SAXBuilder saxBuilder = new SAXBuilder();
//解析build里的参数是一个文件路径.
Document document = saxBuilder.build(xmlPath);
//document.getRootElement().getChildren("bean")获取所有<bean>标签内容
List elements = document.getRootElement().getChildren("bean");
//遍历<bean>对象
for (int i = 0; i < elements.size(); i++) {
//获取第一个<bean>标签elements.get(0);
Element element = (Element) elements.get(i);
//获取<bean>标签里的<id>属性,
//<bean id="i" class="com.hck.dao.impl.IocDaoImpl"/>
//即String beanName="i";
String beanName = element.getAttributeValue("id");
//同上String clazz="com.hck.dao.impl.IocDaoImpl";
String clazz = element.getAttributeValue("class");
//加载类对象并且实例化.Object object=new IocDaoImpl();
Object object = Class.forName(clazz).newInstance();//object是IocDaoServiceImpl
//将他们添加在map集合里,后面可以根据beanName直接获取到实例化对象.
beans.put(beanName, object);
//遍历<bean>标签下的<property>字标签.
//第一个标签没有字标签所以直接跳过.已第二个为例子
//<bean id="iocService" class="com.hck.service.impl.IocDaoServiceImpl">
//<property name="iocDao" ref="i"></property></bean>
List elements2 = element.getChildren("property");
for (int j = 0; j < elements2.size(); j++) {
//此处我们将获得<property name="iocDao" ref="i"></property></bean>
Element element2 = (Element) elements2.get(j);
//相当于String propertyName="iocDao";
String propertyName = element2.getAttributeValue("name");
//相当于String refBean="i";
String refBean = element2.getAttributeValue("ref");
//相当于String propertyName="IocDao";
//目的是为了得到一个方法的名字setIocDao,用于反射调用
propertyName = propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
//这里的methodName="setIocDao";
String methodName = "set" + propertyName;
//获取Map集合里Key="i"的值;i对应的是IocDaoImpl的实例化对象
//相当于 Object object2 =IocDaoImpl;
Object object2 = beans.get(refBean);
//获取IocDaoServiceImpl方法里的setIocDao方法.
//第一个方法是方法名,第二个参数是方法的参数类型.
Method method = object.getClass().getDeclaredMethod(methodName,
object2.getClass().getInterfaces());
//调用方法,并传入参数,完成依赖注入.
method.invoke(object, object2);
}
}
// String beanName=document.getElementById(id).attributes().get("class");
// Object object=Class.forName(beanName).newInstance();
// return object;
} catch (Exception e) {
e.printStackTrace();
// TODO: handle exception
}
}
/* (non-Javadoc)
* @see com.hck.ioc.BeanFactory#getBean()
*/
@Override
public Object getBean(String beanName) {
// TODO Auto-generated method stub
return beans.get(beanName);
}
}
八.编写测试类
public class Ioc {
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("src/bean.xml");
IocDaoService ids=(IocDaoService)applicationContext.getBean("iocService");
ids.sayhello();
}
}
九.显示结果:

到这里Ioc的模拟就结束了.觉得容易有用的朋友可以点击一下推荐或者点击一下关注。么么哒~~
Spring的Ioc模拟实现的更多相关文章
- spring之IOC模拟实现
使用Spring框架已经有很长时间了,一直没有仔细的想过框架的设计思想是什么样的,底层到底是怎么实现的,这几天调试程序看了些源码,写下来做个记录.由于Spring框架博大精深,个人理解的难免有不正确的 ...
- 简单理解Spring之IOC和AOP及代码示例
Spring是一个开源框架,主要实现两件事,IOC(控制反转)和AOP(面向切面编程). IOC 控制反转,也可以称为依赖倒置. 所谓依赖,从程序的角度看,就是比如A要调用B的方法,那么A就依赖于B, ...
- [原]容器学习(一):动手模拟spring的IoC
介绍 学习经典框架的实现原理以及设计模式在其实际中的运用,是非常有必要的,可以让我们更好进行面向对象. 本篇文章就来模拟Spring的IOC功能,明白原理后,可以更好的使用它,进而为进行面向对象提供一 ...
- 容器学习(一):动手模拟spring的IoC
介绍 学习经典框架的实现原理以及设计模式在事实上际中的运用,是很有必要的,能够让我们更好进行面向对象. 本篇文章就来模拟Spring的IOC功能.明确原理后,能够更好的使用它,进而为进行面向对象提供一 ...
- JAVA模拟Spring实现IoC过程(附源码)
前言:本人大四学生,第一次写博客,如果有写得不好的地方,请大家多多指正 一.IoC(Inversion of Control)反转控制 传统开发都是需要对象就new,但这样做有几个问题: 效率低下,创 ...
- 自己动手模拟spring的IOC
我们这里是模拟spring,主要模拟spring中的IOC功能,所以在此我们一样要在service层中定义dao的实例,当然不用new出来,我们就通过spring的IOC把这里的dao层注入进来.不要 ...
- spring IOC 模拟实现
IOC即inverse of control 控制反转 以前对象之间的引用是通过new来调用实现,有了Spring IOC,我们可以把对象之间的引用交给他来管理,这样就把控制权交给了Spring,所以 ...
- Spring中IOC和AOP的详细解释
我们是在使用Spring框架的过程中,其实就是为了使用IOC,依赖注入,和AOP,面向切面编程,这两个是Spring的灵魂. 主要用到的设计模式有工厂模式和代理模式. IOC就是典型的工厂模式,通过s ...
- Spring 实践 -IoC
Spring 实践 标签: Java与设计模式 Spring简介 Spring是分层的JavaSE/EE Full-Stack轻量级开源框架.以IoC(Inverse of Control 控制反转) ...
随机推荐
- WPF 动态模拟CPU 使用率曲线图
原文:WPF 动态模拟CPU 使用率曲线图 在工作中经常会遇到需要将一组数据绘制成曲线图的情况,最简单的方法是将数据导入Excel,然后使用绘图功能手动生成曲线图.但是如果基础数据频繁更改, ...
- Styling a ListView with a Horizontal ItemsPanel and a Header
原文http://eblog.cloudplush.com/2012/05/23/styling-a-listview-with-a-horizontal-itemspanel-and-a-heade ...
- AY写给国人的教程- VS2017 Live Unit Testing[1/2]-C#人爱学不学-aaronyang技术分享
原文:AY写给国人的教程- VS2017 Live Unit Testing[1/2]-C#人爱学不学-aaronyang技术分享 谢谢大家观看-AY的 VS2017推广系列 Live Unit Te ...
- Android各版本对应的SDK和JDK版本
原文:Android各版本对应的SDK和JDK版本 一.Android各版本对应的SDK版本: 平台版本 SDK版本 版本名称 Android 8.0 26 Oreo Android 7.1 25 N ...
- [WPF疑难] 模式窗口被隐藏后重新显示时变成了非模式窗口
原文:[WPF疑难] 模式窗口被隐藏后重新显示时变成了非模式窗口 [WPF疑难] 模式窗口被隐藏后重新显示时变成了非模式窗口 周银辉 现象: 大家可以试试下面这个很有趣但会带来Defect的现象:当我 ...
- WPF 遍历 控件
比较简单的方式是 在设计一个画面时 先添加一个grid 或其他的布局控件 确保要遍历的控件都在这个Grid中时就可以这么写 foreach (UIElement uie in Grid.Childre ...
- Win8 Metro(C#)数字图像处理--2.59 P分位法图像二值化
原文:Win8 Metro(C#)数字图像处理--2.59 P分位法图像二值化 [函数名称] P分位法图像二值化 [算法说明] 所谓P分位法图像分割,就是在知道图像中目标所占的比率Rat ...
- DDD中的值对象如何用NHibernate进行映射
原文:DDD中的值对象如何用NHibernate进行映射 <component/>是NHibernate中一个有趣的特性,即是用来映射DDD(Data-Display-Debuger)概念 ...
- 在Visual Studio2015中使用单元测试
所谓的单元测试(Unit Test),就是对软件的一些模块进行测试以检查其正确性和可靠性,这些模块可以是一个类或者是一个方法等.在Visual studio中,这十分容易实现. 打开Visual st ...
- 用python的curl和lxml来抓取和分析网页内容
Curl是一个强大的URL语法的客户端,支持DICT, FILE, FTP, FTPS, Gopher, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, POP3, PO ...