Spring IOC容器解析及实现原理
最近一段时间,“容器”两个字一直萦绕在我的耳边,甚至是吃饭、睡觉的时候都在我脑子里蹦来蹦去的。随着这些天一次次的交流、讨论,对于容器的理解也逐渐加深。理论上的东西终归要落实到实践,今天就借助spring容器实现原理,简单说说吧。
简单的说,Spring就是通过工厂+反射将我们的bean放到它的容器中的,当我们想用某个bean的时候,只需要调用getBean("beanID")方法。
原理简单介绍:
Spring容器的原理,其实就是通过解析xml文件,或取到用户配置的bean,然后通过反射将这些bean挨个放到集合中,然后对外提供一个getBean()方法,以便我们获得这些bean。下面是一段简单的模拟代码:
- package com.tgb.spring.factory;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import org.jdom.Document;
- import org.jdom.Element;
- import org.jdom.input.SAXBuilder;
- import org.jdom.xpath.XPath;
- public class ClassPathXmlApplicationContext implements BeanFactory {
- //容器的核心,用来存放注入的Bean
- private Map<String, Object> container = new HashMap<String, Object>();
- //解析xml文件,通过反射将配置的bean放到container中
- public ClassPathXmlApplicationContext(String fileName) throws Exception{
- SAXBuilder sb = new SAXBuilder();
- Document doc = sb.build(this.getClass().getClassLoader().getResourceAsStream(fileName));
- Element root = doc.getRootElement();
- List list = XPath.selectNodes(root, "/beans/bean");
- //扫描配置文件中的bean
- for (int i = 0; i < list.size(); i++) {
- Element bean = (Element) list.get(i);
- String id = bean.getAttributeValue("id");
- String clazz = bean.getAttributeValue("class");
- Object o = Class.forName(clazz).newInstance();
- container.put(id, o);
- }
- }
- @Override
- public Object getBean(String id) {
- return container.get(id);
- }
- }
首先声明一个存放bean的Map,然后通过jdom解析配置文件,循环遍历所有的<bean>节点,并通过反射将它们放到我们之前声明的Map中。然后提供一个getBean()的方法,让我们可以通过bean的Id来找到我们想要的bean。
下面是一个简单的xml配置文件:
- <?xml version="1.0" encoding="UTF-8"?>
- <beans>
- <bean id="E" class="com.tgb.spring.factory.England" />
- <bean id="S" class="com.tgb.spring.factory.Spain" />
- <bean id="P" class="com.tgb.spring.factory.Portugal" />
- </beans>
客户端通过调用前面的ClassPathXmlApplicationContext,来加载上面的配置文件,然后就可以通过Id来获得我们需要的bean了:
- package com.tgb.spring.factory;
- public class Test {
- public static void main(String[] args) throws Exception {
- //加载配置文件
- BeanFactory f = new ClassPathXmlApplicationContext("applicationContext.xml");
- //英格兰
- Object oe = f.getBean("E");
- Team e = (Team)oe;
- e.say();
- //西班牙
- Object os = f.getBean("S");
- Team s = (Team)os;
- s.say();
- //葡萄牙
- Object op = f.getBean("P");
- Team p = (Team)op;
- p.say();
- }
- }
输出结果:
- England :我们是欧洲的中国队,不在乎这次小组没出线...
- Spain :我们是两届欧洲杯冠军、一届世界杯冠军!
- Portugal:我们的C罗一个顶十个!
其他代码:
- //工厂接口
- package com.tgb.spring.factory;
- public interface BeanFactory {
- Object getBean(String id);
- }
- //Team接口
- package com.tgb.spring.factory;
- public interface Team {
- void say();
- }
- //英格兰
- package com.tgb.spring.factory;
- public class England implements Team{
- public void say() {
- System.out.println("England:我们是欧洲的中国队,不在乎这次小组没出线...");
- }
- }
- //西班牙
- package com.tgb.spring.factory;
- public class Spain implements Team{
- @Override
- public void say() {
- System.out.println("Spain:我们是两届欧洲杯冠军、一届世界杯冠军!");
- }
- }
- //葡萄牙
- package com.tgb.spring.factory;
- public class Portugal implements Team {
- @Override
- public void say() {
- System.out.println("Portugal:我们的C罗一个顶十个!");
- }
- }
以上内容是对Spring的一个简单模拟,当然Spring远比这个要复杂的多,也强大的多,而且获取bean的方式也不止通过工厂这一种。这里只是做一个粗略的Demo说说自己对容器的简单理解,向Spring致敬。例子简陋,表达粗糙,欢迎拍砖交流。
Spring IOC容器解析及实现原理的更多相关文章
- 【转】Spring学习---Spring IoC容器的核心原理
[原文] Spring的两个核心概念:IoC和AOP的雏形,Spring的历史变迁和如今的生态帝国. IoC和DI的基本概念 IoC(控制反转,英文含义:Inverse of Control)是Spr ...
- Spring IOC容器启动流程源码解析(四)——初始化单实例bean阶段
目录 1. 引言 2. 初始化bean的入口 3 尝试从当前容器及其父容器的缓存中获取bean 3.1 获取真正的beanName 3.2 尝试从当前容器的缓存中获取bean 3.3 从父容器中查找b ...
- Spring IOC容器启动流程源码解析(一)——容器概念详解及源码初探
目录 1. 前言 1.1 IOC容器到底是什么 1.2 BeanFactory和ApplicationContext的联系以及区别 1.3 解读IOC容器启动流程的意义 1.4 如何有效的阅读源码 2 ...
- Spring IOC容器的初始化-(二)BeanDefinition的载入和解析
前言 1.在讲BeanDefinition的载入和解析之前,我们先来看看什么是BeanDefinition. Bean对象在Spring中是以BeanDefinition来描述的,也就是说在Sprin ...
- Spring源码阅读-IoC容器解析
目录 Spring IoC容器 ApplicationContext设计解析 BeanFactory ListableBeanFactory HierarchicalBeanFactory Messa ...
- Spring IOC容器的实现原理
1 概述 1.1 依赖反转模式 在Java中,一个复杂的功能一般都需要由两个或者两个以上的类通过彼此合作来实现业务逻辑的,这使得每个对象都需要与其合作的对象的引用.如果这个获取依赖对象的过程需要自己去 ...
- spring-framework-中文文档一:IoC容器、介绍Spring IoC容器和bean
5. IoC容器 5.1介绍Spring IoC容器和bean 5.2容器概述 本章介绍Spring Framework实现控制反转(IoC)[1]原理.IoC也被称为依赖注入(DI).它是一个过程, ...
- Spring IOC 容器源码分析 - 填充属性到 bean 原始对象
1. 简介 本篇文章,我们来一起了解一下 Spring 是如何将配置文件中的属性值填充到 bean 对象中的.我在前面几篇文章中介绍过 Spring 创建 bean 的流程,即 Spring 先通过反 ...
- Spring IOC 容器源码分析 - 循环依赖的解决办法
1. 简介 本文,我们来看一下 Spring 是如何解决循环依赖问题的.在本篇文章中,我会首先向大家介绍一下什么是循环依赖.然后,进入源码分析阶段.为了更好的说明 Spring 解决循环依赖的办法,我 ...
随机推荐
- 使用ES6的Promise 解决回调函数。
//创建一个Promise实例,获取数据.并把数据传递给处理函数resolve和reject.需要注意的是Promise在声明的时候就执行了. var getUserInfo=new Promise( ...
- canvas基础学习(一)
一.概述 canvas它和其它的HTML5标签的使用基本一致,但是它相当于在浏览器中建立一个画布,可以再这个画布上画图.创建动画甚至是3D游戏.由于canvas要适配不同终端的分辨率,所以尽可能的在标 ...
- 11462 Age Sort(计数排序)
内存不够用,用计数排序可以解决问题. #include<iostream> #include<cstdio> #include<cstdlib> #include& ...
- Codeforces Round #277.5 (Div. 2)D Unbearable Controversy of Being (暴力)
这道题我临场想到了枚举菱形的起点和终点,然后每次枚举起点指向的点,每个指向的点再枚举它指向的点看有没有能到终点的,有一条就把起点到终点的路径个数加1,最后ans+=C(路径总数,2).每两个点都这么弄 ...
- php代码性能分析
最近在项目中嵌入wordpress,发现wordpress效率非常低,针对此问题进行了部分优化. 1.首先增加redis缓存,通过index.php入口处进行全页面缓存(数据量不大,数据更新频率低,因 ...
- [leetcode]_Flatten Binary Tree to Linked List
题目:将一棵二叉树履平成一个类似Linked-list的东西. 思路:该过程类似于二叉树的前序遍历,但是遍历代码,我处理不来参数的变化.没AC. -------->写的很好的解题博客 参考上述博 ...
- 快速构建一个 Springboot
快速构建一个 Springboot 官网:http://projects.spring.io/spring-boot/ Spring Boot可以轻松创建可以“运行”的独立的,生产级的基于Spring ...
- HUST 1010 The Minimum Length
There is a string A. The length of A is less than 1,000,000. I rewrite it again and again. Then I go ...
- Linux下系统监控工具nmon使用
Mongodb安装在Centos7或以上的版本,对于系统的监控方法如下: 1.从\\10.10.10.1\ShareDoc\User\Zchen\linux系统监控下下载2个工具 nmon16e_mp ...
- jacksi(比较实用的工具批处理)
批处理类别: 国产软件 批处理语言: 简体中文 授权方式: 免费软件 运行环境: Windows平台 警告:运行BAT源码是一种危险的动作,如果你不熟悉,请不要尝试! 这里分享的是用bat写的比较实用 ...