• 很多小伙伴们看到标题可能就会想到抛开Spring就不会存在IOC思想了,其实不然在接下来的文章中就会讲述到。
  • 很多小伙伴在理解IOC的时候通常会和Spring放到一起去学习,首先呢Spring设计的非常之巧妙而且里面包含了很多除去IOC的其他功能。这样会导致我们在Spring的基础去理解IOC就变得很困难。很难抓住其核心思想。
  • 所以本文的标题的含义就是单纯的去理解IOC思想,然后通过自定义的IOC去加深对IOC的理解。
  • 看完本文之后再去理解Spring中的IOC其实思想是一致的,只是实现上有些出入。毕竟Spring是大神们经过深思熟虑后的成果。

传统的思想(没有IOC容器的情况下)

在没有IOC容器的情况下,如果我们需要某个类具体的操作如下所示:

传统的Bean创建

  1. 程序员对A进行了主动的使用(new)即创建了A类,A类中又依赖B类然后在对B类进行创建
  2. 创建对象的权利现在是程序员手上需要哪个类就会对那个类进行创建
  3. B类是由于程序员调用了A类有对B类的依赖随着而创建
  4. 总之就是自己动手丰衣足食,没有借助任何中间产物。

优点

  • 很直接的一个优点就是简单,我们需要什么就去创建什么,在程序员的角度上也是比较直观容易理解的。

缺点

  • Bean之间的协调关系是由程序内部代码来控制的即通过New关键字与我们的业务代码进行了强耦合。
  • 没有对Bean进行管理。
  • 对Bean没有进行统一的管理和配置。

IOC思想

首先在这里强调一下IOC不是Spring提出来了,在Spring之前就已经有人提出了IOC思想,只不过在Spring之前都是偏理论化没有一个具体的落地方案,Spring在技术层面把IOC思想体现的淋漓尽致。

什么是IOC(Inversion of controller)

  • IOC是一种思想,而不是一个技术的实现。
  • 主要的描述是在软件开发的领域对象的创建和管理的问题。
  • 上述我们了解了传统的开发模式,我们在来看看如果有IOC的思想下程序员是如何使用对象的。

从上图可知:

  • 程序员只需要告诉IOC自己需要那个Bean。就不需要关系该Bean创建的细节已经该Bean的相关依赖。这一切IOC容器已经帮你做好了。
  • 凡事有得必有失: 这个过程中我们失去了创建Bean的权利。
  • 了解了基本的使用后,有人说IOC就是控制反转,讲到这里你还没将控制反转?好!别急接下来就是细讲我们常说的控制反转。

控制反转

在理解控制反转之前我们首先要清楚控制是指什么? 反转又反转了什么?

  • 控制: 指的就是我们上述说的我们失去的权利(创建对象的创建,或者说控制对象的权利)
  • 反转: 指的是控制权的转变。在没有IOC的容器上我们程序员想创建谁就创建谁的权利。在IOC容器下程序员就只能委屈巴巴的向IOC容器索取对象。创建对象的权利由程序员到IOC容器手里了。

IOC解决了什么问题?

  • 其实就是解决了对象之间的耦合问题。
  • 我们不需要在通过New关键字来创建对象,而是从容器中获取达到一种松耦合的目的。
  • 同时IOC容器也方便管理容器内的所有Bean对象。所谓的Bean的生命周期。

IOC和DI的区别

将到IOC肯定会有人想到DI(Dependancy Injection)依赖注入,那这两者有什么不同和相同呢?

相同点

  • IOC和DI描述的都是同一件事情(对象的实例化以及维护对象与对象已经的依赖关系)

不同点

  • 首先IOC是一种思想,而DI是一种具体的技术实现手段。
  • IOC是站着对象的角度上对象的实例化以及管理从程序员的手里交给了IOC容器
  • DI是站着容器的角度的上会把对象的依赖的其他对象注入到容器中,上述案例中的A类依赖B类IOC容器不仅仅将A类放到容器中还需要将其依赖的B类也一并加载到IOC容器中。

如何自定义实现一个IOC容器

  • 小伙伴们看到这里其实对IOC容器已经有了一定的了解。那如果在面试的过程中面试官问你如何实现一个自定义的IOC容器。你可以讲出的具体思路嘛? 可以先想一想在继续往下看,看看是不是和自己的想发不谋而合。
  • 思路大致如下所示:
  • 想必大家都有自己的一定的理解,可能做法比较简单,但是对于理解IOC容器而已其实已经足够了。如果想更加准确或者深入了解其底层实现,可以按照这个思路去看Spring的相关源码实现,相信你一定会得心应手。

小案例

  • 我们通过一个小案例来写我们的IOC容器
  • 我们经常购物,我们可以把购物简单的理解成下单和减库存两个操作。
  • 有同学会问为什么要写这个案例啊,不仅为了我们能够理解IOC容器也为了我们后续的文章将AOP和AOP的经典实现事务控制铺垫的。

Coding

  • 首先整体的代码结构很简单,在这里也说明一下
  • Bean的配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!--跟标签beans,里面配置一个又一个的bean子标签,每一个bean子标签都代表一个类的配置-->
<beans><!--id标识对象,class是类的全限定类名--><bean id="orderDao" class="com.customize.spring.dao.impl.OrderDaoImpl"></bean><bean id="stockDao" class="com.customize.spring.dao.impl.StockDaoImpl"></bean><bean id="orderService" class="com.customize.spring.service.impl.OrderServiceImpl"><!--通过set方法注入--><property name="setOrderDao" ref="orderDao"></property><property name="setStockDao" ref="stockDao"></property></bean>
</beans>

  • 创建Bean对象”工厂“进行创建
  • 主要就是读取xml,通过set方法传值。
public class BeanFactory {/*** 存放对象*/private static Map<String, Object> map = new ConcurrentHashMap<>();/*** 对外提供的接口* @param id* @return*/public static  Object getBean(String id) {return map.get(id);}static {// 只加载一次就是在BeanFactory初始化的时候去加载类// 任务一:读取解析xml,通过反射技术实例化对象并且存储待用(map集合)System.out.println("开始加载Bean对象");// 加载xmlInputStream resourceAsStream = BeanFactory.class.getClassLoader().getResourceAsStream("beans.xml");// 解析xmlSAXReader saxReader = new SAXReader();try {Document document = saxReader.read(resourceAsStream);Element rootElement = document.getRootElement();List<Element> beanList = rootElement.selectNodes("//bean");for (int i = 0; i < beanList.size(); i++) {Element element =  beanList.get(i);// 处理每个bean元素,获取到该元素的id 和 class 属性String id = element.attributeValue("id");String clazz = element.attributeValue("class");// 通过反射技术实例化对象Class<?> aClass = Class.forName(clazz);Object o = aClass.newInstance();// 存储到map中待用map.put(id,o);}// 实例化完成之后维护对象的依赖关系,检查哪些对象需要传值进入,根据它的配置,我们传入相应的值// 有property子元素的bean就有传值需求List<Element> propertyList = rootElement.selectNodes("//property");// 解析property,获取父元素for (int i = 0; i < propertyList.size(); i++) {Element element =  propertyList.get(i);String name = element.attributeValue("name");String ref = element.attributeValue("ref");// 找到当前需要被处理依赖关系的beanElement parent = element.getParent();// 调用父元素对象的反射功能String parentId = parent.attributeValue("id");Object parentObject = map.get(parentId);// 遍历父对象中的所有方法,找到"set" + nameMethod[] methods = parentObject.getClass().getMethods();for (int j = 0; j < methods.length; j++) {Method method = methods[j];// 该方法就是 setAccountDao(AccountDao accountDao)if(method.getName().equalsIgnoreCase(name)) {method.invoke(parentObject,map.get(ref));}}// 把处理之后的parentObject重新放到map中map.put(parentId,parentObject);}System.out.println("加载完毕,Map中的Bean对象个数为:" + map.size());} catch (Exception e) {e.printStackTrace();}}
}

  • 业务代码
public class OrderServiceImpl implements OrderService {private OrderDao orderDao;private StockDao stockDao;public void setOrderDao(OrderDao orderDao) {this.orderDao = orderDao;}public void setStockDao(StockDao stockDao) {this.stockDao = stockDao;}@Overridepublic void order(Order order) {
//        没有IOC容器的情况下
//        OrderDao orderDao = new OrderDaoImpl();
//        // 保存订单
//        orderDao.save(order);
//
//        //扣除库存
//        StockDao stockDao = new StockDaoImpl();
//        stockDao.subStock(order.getName());// 有IOC容器的基础上orderDao.save(order);//扣除库存stockDao.subStock(order.getName());System.out.println("下单成功");}
}

  • 启动
  • 测试

    • 地址: http://localhost:9080/order?userId=857&name=ipone
    • 配图:

项目地址

  • 项目地址
  • 有帮忙到你记得点个小星星哦。

总结

  • 本人水平有限有什么不正确的地方,欢迎大家留言区讨论。

ioc spring 上机案例_抛开Spring去理解IOC思想 - 原来IOC容器这么简单相关推荐

  1. ioc spring 上机案例_通过实例解析Spring Ioc项目实现过程

    0. Ioc 主要是实现一个控制反转,耦合性大大降低. 1. 建maven项目 建立一个空的maven项目,然后pom.xml添加spring-context的依赖: org.springframew ...

  2. spring mysql 注解_【Spring】SpringMVC之基于注解的实现SpringMVC+MySQL

    目录结构: contents structure [-] SpringMVC是什么 MVC的全称是Model View Controller,通过实现MVC框架可以很好的数据.视图.业务逻辑进行分离. ...

  3. spring boot测试_测试Spring Boot有条件的合理方式

    spring boot测试 如果您或多或少有经验的Spring Boot用户,那么很幸运,在某些时候您可能需要遇到必须有条件地注入特定bean或配置的情况 . 它的机制是很好理解的 ,但有时这样的测试 ...

  4. spring 事务 会话_测试Spring的“会话”范围

    spring 事务 会话 在基于Spring的Web应用程序中,bean的作用域可以是用户"会话". 从本质上讲,这意味着对会话范围Bean的状态更改仅在用户会话范围内可见. 本条 ...

  5. java spring 条件注解_【Spring】Spring高级话题-条件注解-@Condition

    进行本示例的演示,需要先配置好Maven和Spring哦. 见: [Spring]基于IntelliJ IDEA搭建Maven 分析 通过profile,我们可以获得不同的profile,我们可以获得 ...

  6. ioc spring 上机案例_IOC(控制反转)—最后的爱,是放手

    [摘要]Spring框架的一个重要理念之一,就是IOC,英文全拼为Inversion of Control, 中文翻译为控制反转,这是一个非常伟大的理念,不应该只是在程序中被提及. 某些教程,因为缺乏 ...

  7. ioc spring 上机案例_Spring的IoC入门案例

    1.创建工程,导入坐标 1.1 创建工程 1.2 导入坐标 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:sc ...

  8. spring 扫描所有_从Spring的几个阶段理解其工作过程

    首发于博客园,https://www.cnblogs.com/ibigboy/p/11150237.html Spring框架非常强大,想要彻底弄懂Spring是非常困难的. 为了便于初学者了解Spr ...

  9. spring 开发环境_设置Spring 3开发环境

    spring 开发环境 本教程简要说明了如何设置典型的环境来开发基于Spring的应用程序. 除了可以正常工作的Windows XP客户端具有足够的CPU能力和内存外,本教程没有其他先决条件. 在教程 ...

最新文章

  1. 使用docker安装mysql服务
  2. STM32应用实例六:与MS5837压力传感器的I2C通讯
  3. Python多任务(1.多进程的概念和用法 )
  4. 解决安装SQL Server 2005开发版时,出现“SQL Server 服务无法启动 ”点击重试或取消的解决方法
  5. et200sp模块接线手册_格力变频空调模块常见故障处理。
  6. (项目)生鲜超市(六)
  7. .NET异步编程总结----四种实现模式
  8. 基于Cocos2d-x开发guardCarrot--5 《保卫萝卜2》主页面音频
  9. 动态修改php的配置项
  10. Spring boot 开发 GA/T1400 协议之注册、保活、注销、校时功能
  11. 工具说明书 - 搜索引擎推荐
  12. codeforces EDU suffix array
  13. 数据分析师认证考试形式发布,如何掌握考试重难点?
  14. UI自动化执行遇到的问题汇总
  15. 河北省 建筑标准规范 合集
  16. Linux socket设置mark的必要性
  17. python 脚本式编程
  18. 什么是Lambda架构?
  19. 在HTML代码中要如何插入空格?
  20. 使用了代理服务器之后突然浏览器不能打开网页的解决方法

热门文章

  1. 通俗的讲,这就是容器CPU隔离的底层实现机制
  2. 如何让 Mac在运行 Windows时享受极致体验?Parallels Desktop 16给你答案!
  3. 从安全到镜像流水线,Docker 最佳实践与反模式一览
  4. 医疗保健、零售、金融、制造业……一文带你看懂大数据对工业领域的影响!...
  5. 戴尔科技:以技术突破创新边界!
  6. mysql基础和高级整理_mysql基础整理01
  7. 用c语言绘制自定义图形,Android使用自定义View绘图
  8. c语言程序停止正常工作,C语言 由于出现问题,程序停止正常工作。如果帮我解决这个问题即可获得悬赏...
  9. Maven 操作手册
  10. Syntax Error: TypeError: this.getOptions is not a function