当前位置: 首页 > news >正文

Spring源码学习之:模拟实现BeanFactory,从而说明IOC容器的大致原理

spring的IOC容器能够帮我们自动new对象,对象交给spring管之后我们不用自己手动去new对象了。那么它的原理是什么呢?是怎么实现的呢?下面我来简单的模拟一下spring的机制,相信看完之后就会对spring的原理有一定的了解。

  spring使用BeanFactory来实例化、配置和管理对象,但是它只是一个接口,里面有一个getBean()方法。我们一般都不直接用BeanFactory,而是用它的实现类ApplicationContext,这个类会自动解析我们配置的applicationContext.xml,然后根据我们配置的bean来new对象,将new好的对象放进一个Map中,键就是我们bean的id,值就是new的对象。

  首先我们建立一个BeanFactory接口

1 package com.spring;
2 
3 public interface BeanFactory {
4     Object getBean(String id);
5 }

  然后建立一个BeanFactory的实现类ClassPathXmlApplicationContext.java

复制代码
 1 package com.spring;
 2 
 3 import java.util.HashMap;
 4 import java.util.List;
 5 import java.util.Map;
 6 
 7 import org.dom4j.Document;
 8 import org.dom4j.DocumentException;
 9 import org.dom4j.Element;
10 import org.dom4j.io.SAXReader;
11 
12 
13 public class ClassPathXmlApplicationContext implements BeanFactory {
14     private Map<String, Object> beans = new HashMap<String, Object>();
15     public ClassPathXmlApplicationContext(String fileName) throws Exception{
16         SAXReader reader = new SAXReader();
17         Document document = reader.read(this.getClass().getClassLoader().getResourceAsStream(fileName));
18         List<Element> elements = document.selectNodes("/beans/bean");
19         for (Element e : elements) {
20             String id = e.attributeValue("id");
21             String value = e.attributeValue("class");
22             Object o = Class.forName(value).newInstance();
23             beans.put(id, o);
24         }
25     }
26     
27     public Object getBean(String id) {
28         return beans.get(id);
29     }
30 
31 }
复制代码

  然后配置applicationContext.xml

1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans>
3     <bean id="c" class="com.spring.Car"></bean>
4      <bean id="p" class="com.spring.Plane"></bean>
5 </beans>

创建类的时候顺便演示一下工厂模式,其实BeanFactory它也是一种工厂模式的。

1 package com.spring;
2 
3 public interface Moveable {
4     void run();
5 }
复制代码
1 package com.spring;
2 
3 public class Car implements Moveable{
4     
5     public void run(){
6         System.out.println("拖着四个轮子满街跑car·····");
7     }
8 }
复制代码
复制代码
1 package com.spring;
2 
3 public class Plane implements Moveable{
4 
5     public void run() {
6         System.out.println("拖着翅膀天空飞plane......");
7     }
8     
9 }
复制代码

 

现在来看一看效果吧,写一个类测试一下:

复制代码
 1 package com.spring;
 2 
 3 import org.dom4j.DocumentException;
 4 
 5 public class Test {
 6 
 7     /**
 8      * @param args
 9      * @throws DocumentException 
10      */
11     public static void main(String[] args) throws Exception {
12         BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");
13         Object o = factory.getBean("c");
14         Moveable m = (Moveable)o;
15         m.run();
16     }
17 
18 }
复制代码

由于Map容器里面保存的是Object类型,所以通过getBean()方法取出来的对象要强制类型转换。

相关文章:

  • photoshop之蒙板(又称遮罩)的使用
  • 最新思科考试中心查询
  • 扩展 TreeView 实现选择 CheckBox 自动回发
  • 苏州印象
  • JS实现搜索关键字加亮效果
  • 使用redis做mybaties的二级缓存(2)-Mybatis 二级缓存小心使用
  • [转]SQL中CONVERT转化函数
  • 镜像ISO 小知识
  • Windows安装MySQL绿色版
  • 团队游戏2
  • cisco路由器配置及维护手册
  • Proxy设计模式
  • Lua第三方插件列表
  • Python2 爬虫(一) -- 人生第一条蠕动的爬虫
  • 人生就是这样
  • [LeetCode] Wiggle Sort
  • css选择器
  • exports和module.exports
  • php的插入排序,通过双层for循环
  • Python socket服务器端、客户端传送信息
  • Python_网络编程
  • python学习笔记 - ThreadLocal
  • Redis提升并发能力 | 从0开始构建SpringCloud微服务(2)
  • SpiderData 2019年2月23日 DApp数据排行榜
  • 初识 webpack
  • 分布式事物理论与实践
  • 后端_ThinkPHP5
  • 将回调地狱按在地上摩擦的Promise
  • 数据科学 第 3 章 11 字符串处理
  • 详解移动APP与web APP的区别
  • 【云吞铺子】性能抖动剖析(二)
  • ​七周四次课(5月9日)iptables filter表案例、iptables nat表应用
  • #define
  • #WEB前端(HTML属性)
  • (04)Hive的相关概念——order by 、sort by、distribute by 、cluster by
  • (39)STM32——FLASH闪存
  • (附源码)ssm高校社团管理系统 毕业设计 234162
  • (附源码)计算机毕业设计ssm本地美食推荐平台
  • (机器学习-深度学习快速入门)第一章第一节:Python环境和数据分析
  • (剑指Offer)面试题41:和为s的连续正数序列
  • (论文阅读23/100)Hierarchical Convolutional Features for Visual Tracking
  • (四)Controller接口控制器详解(三)
  • (转)winform之ListView
  • (转)树状数组
  • * CIL library *(* CIL module *) : error LNK2005: _DllMain@12 already defined in mfcs120u.lib(dllmodu
  • .mysql secret在哪_MySQL如何使用索引
  • .NET 指南:抽象化实现的基类
  • .NET/C# 如何获取当前进程的 CPU 和内存占用?如何获取全局 CPU 和内存占用?
  • .NET/C# 在 64 位进程中读取 32 位进程重定向后的注册表
  • .net安装_还在用第三方安装.NET?Win10自带.NET3.5安装
  • .net反编译的九款神器
  • .sh文件怎么运行_创建优化的Go镜像文件以及踩过的坑
  • ?.的用法
  • [ C++ ] STL_stack(栈)queue(队列)使用及其重要接口模拟实现
  • []error LNK2001: unresolved external symbol _m