为了加深理解Spring 今天自己写了一个模拟的Spring....

步骤:

1.利用jdom解析bean.xml(pull,sax也能够,我这里用了jdom)

2.先解析全部的<bean/>,再解析全部的<property/>.假设边解析<bean/>,边解析<property/>,会导致property的ref找不到相应的bean.

3.利用反射,依据解析到的类路径,new出一个实例,实现Ioc.

文件夹结构:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

这里仅仅给出核心代码,其余的bean,dao,service,并不重要,就不给出了.有兴趣的同志能够点击~这里下载源代码.~

ClassPathXmlApplicationContext:

package glut.spring;

import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry; import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder; public class ClassPathXMLApplicationContext {
/**
* 用于存放<bean/>
*/
private Map<String, Object> beans = new HashMap<>();
/**
* 用于存放<property/>
*/
private Map<String, List<Element>> properties = new HashMap<>(); /**
* 将xml文件转为输入流,作为參数传入.
* @param is
* @throws Exception
*/
public ClassPathXMLApplicationContext(InputStream is) throws Exception {
// TODO Auto-generated constructor stub
autoWired(is);
} /**
* 模拟DI
* @param is
* @throws Exception
*/
private void autoWired(InputStream is) throws Exception {
SAXBuilder sb = new SAXBuilder(); Document doc = sb.build(is); Element rootElement = doc.getRootElement(); List<Element> elementOfBeans = rootElement.getChildren("bean"); //遍历xml中全部的<bean/>
for (Element e : elementOfBeans) { String beanId = e.getAttributeValue("id");
String beanClz = e.getAttributeValue("class"); Object beanInstance = Class.forName(beanClz).newInstance();
//将beanId和bean的实例存入map
beans.put(beanId, beanInstance);
//把全部的property先存着,等bean初始化完成再初始化property,否则可能会导致某些property无法初始化
properties.put(beanId, e.getChildren("property")); } //Dependency Injection Simulation
for (Entry<String, List<Element>> entry : properties.entrySet()) {
for (Element e : entry.getValue()) {
String propertyName = e.getAttributeValue("name");
String propertyRef = e.getAttributeValue("ref"); //通过set方法注入
String methodName = "set"
+ propertyName.substring(0, 1).toUpperCase()
+ propertyName.substring(1); //通过beanId获得相应的bean
Object beanInstance = beans.get(entry.getKey()); //通过ref的值去寻找相应的bean,假设没有相应的bean,在以下用到getClass的时候会抛出异常.
Object refBeanInstance = beans.get(propertyRef); Method setterMethod = beanInstance.getClass().getMethod(
methodName,//呵呵,功能有点简陋,默认仅仅支持refBean实现的第一个接口.
refBeanInstance.getClass().getInterfaces()[0]); //调用相应的setter方法,将ref的bean注入到指定的bean中.
setterMethod.invoke(beanInstance, refBeanInstance); }
}
} /**
* 依据beanName获得bean
*/
public Object getBean(String beanName) {
// TODO Auto-generated method stub
return beans.get(beanName);
} }

測试代码:

package glut.test;

import glut.bean.User;
import glut.service.UserService;
import glut.spring.ClassPathXMLApplicationContext; import org.junit.Test; public class SpringTest {
@Test
public void test() throws Exception {
ClassPathXMLApplicationContext ctx = new ClassPathXMLApplicationContext(
this.getClass().getClassLoader()
.getResourceAsStream("beans.xml")); UserService userService = (UserService) ctx.getBean("userService"); User user = new User("user", "123"); userService.add(user);
}
}

打印的结果为User的toString:

User [uid=user, pwd=123]

模拟实现Spring IoC功能的更多相关文章

  1. 手动模拟实现Spring IOC功能(基于javaConfig风格)

    以下文中spring特指spring frameWork项目,不含其它:如spring cloud等. 作为刚开始研究spring源码的小白,对于spring两大核心功能之一的IOC,虽说大致了解了B ...

  2. 自定义模拟一个Spring IOC容器

    一.模拟一个IOC容器: 介绍:现在,我们准备使用一个java project来模拟一个spring的IOC容器创建对象的方法,也就是不使用spring的jar自动帮助我们创建对象,而是通过自己手动书 ...

  3. 自己模拟实现spring IOC原理

    1.1.IoC是什么 Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想.在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对 ...

  4. Spring IOC 剖析

    模拟实现 Spring Ioc 控制反转功能 使用 => 原理 => 源码 => 模拟实现 使用:了解 原理:熟悉 源码 And 模拟实现: 精通 对照 Spring 功能点 Spr ...

  5. 使用 Spring 2.5 注释驱动的 IoC 功能(转)

    基于注释(Annotation)的配置有越来越流行的趋势,Spring 2.5 顺应这种趋势,提供了完全基于注释配置 Bean.装配 Bean 的功能,您可以使用基于注释的 Spring IoC 替换 ...

  6. spring IOC 模拟实现

    IOC即inverse of control 控制反转 以前对象之间的引用是通过new来调用实现,有了Spring IOC,我们可以把对象之间的引用交给他来管理,这样就把控制权交给了Spring,所以 ...

  7. (反射+内省机制的运用)简单模拟spring IoC容器的操作

    简单模拟spring IoC容器的操作[管理对象的创建.管理对象的依赖关系,例如属性设置] 实体类Hello package com.shan.hello; public class Hello { ...

  8. spring ioc aop 原理

    spring ioc aop 原理 spring ioc aop 的原理 spring的IoC容器是spring的核心,spring AOP是spring框架的重要组成部分. 在传统的程序设计中,当调 ...

  9. J2EE进阶(十四)超详细的Java后台开发面试题之Spring IOC与AOP

    J2EE进阶(十四)超详细的Java后台开发面试题之Spring IOC与AOP 前言   搜狐畅游笔试题中有一道问答题涉及到回答谈谈对Spring IOC与AOP的理解.特将相关内容进行整理.    ...

随机推荐

  1. AS常见的错误

    导入的项目使用的gradle版本和本地的要一致,不然会提示类似"Minimum supported Gradle version is 3.3. Current version is 2.1 ...

  2. Android - 使用JD-GUI反编译Android代码

    使用JD-GUI反编译Android代码 本文地址: http://blog.csdn.net/caroline_wendy Android程序出现Bug时,须要依据Bug寻找问题出错的地方; 须要使 ...

  3. java连接mysql数据库增删改查操作记录

    1. 连接数据库.得到数据库连接变量 注意连接数据库的时候 (1)打开DB Browser 新建一个Database Driver,注意加入Driver JARs的时候加入的包,我的是mysql-co ...

  4. 受 SQLite 多年青睐,C 语言到底好在哪儿?

    SQLite 近日发表了一篇博文,解释了为什么多年来 SQLite 一直坚持用 C 语言来实现,以下是正文内容: C 语言是最佳选择 从2000年5月29日发布至今,SQLite 一直都是用 C 语言 ...

  5. angularjs1-路由

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  6. Redis学习笔记(三) 基本命令:Key操作

    参考:http://doc.redisfans.com/ del key 删除给定的一个或多个Key(多个key用空格隔开),删除成功返回1,当key不存在时,返回0:例:del no-exist-k ...

  7. PHPMailer使用说明

    PHPMailer是一个用来发送电子邮件的函数包,远比PHP提供的mail()方便易用. 邮件格式说明 一封普通的电子邮件,通常是由发件人.收件人.抄送人.邮件标题.邮件内容.附件等内容构成.以下是一 ...

  8. 【译文】采用chrome的DevTool中TimeLine和profile工具提升Web app性能

    ->译文,原文在这里<- 本文地址: http://www.cnblogs.com/blackmanba/p/web-perfomance-with-Chrome-DevTools.htm ...

  9. jmeter的认识——线程组的认识

    名称:可以给线程组设置一个个性化的命名 注释:可以对线程组添加备注以标记 在取样器错误后要执行的动作:就是在错误之后要如何执行,可选继续执行后续的.停止执行等. 线程数:就是需要设置多少线程执行测试. ...

  10. 一个vue的全局提示框组件

    <template> <!-- 全局提示框 --> <div v-show="visible" class="dialog-tips dia ...