模拟实现Spring IoC功能

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

步骤:

1.利用jdom解析bean.xml

2.创建ClassPathXmlApplicaitonContext用于模拟IoC

3.先解析所有的<bean/>,再解析所有的<property/>.如果边解析<bean/>,边解析<property/>,会导致property的ref找不到对应的bean.

4.利用简单的反射实现Ioc.

目录结构:

这里只给出核心代码,其余的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]

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-25 18:23:44

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

模拟实现Spring IOC

通过在类上标注@Registration 注册进容器,@Injection从容器注入对象 容器类: public class SpringContainer { public SpringContainer(String packageToScan){ Set<Class<?>> classes = getClasses(packageToScan); for(Class c : classes){ if(!c.isAnnotationPresent(Registration.cl

自己模拟实现spring IOC原理

1.1.IoC是什么 Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想.在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制.如何理解好Ioc呢?理解好Ioc的关键是要明确“谁控制谁,控制什么,为何是反转(有反转就应该有正转了),哪些方面反转了”,那我们来深入分析一下: ●谁控制谁,控制什么:传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象:而IoC是有专门一个

使用 Spring 2.5 注释驱动的 IoC 功能

使用 Spring 2.5 注释驱动的 IoC 功能 原文链接 :http://www.ibm.com/developerworks/cn/java/j-lo-spring25-ioc/ 文中对Spring 2.5新引入的注解配置做了详细的讲解以及实例,包括 @Autowired  @Qualifier @Resource @PostConstruct 和 @PreDestroy <context:annotation-config/> <context:component-scan/&

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

基于注释(Annotation)的配置有越来越流行的趋势,Spring 2.5 顺应这种趋势,提供了完全基于注释配置 Bean.装配 Bean 的功能,您可以使用基于注释的 Spring IoC 替换原来基于 XML 的配置.本文通过实例详细讲述了 Spring 2.5 基于注释 IoC 功能的使用. 陈 雄华 ([email protected]), 技术总监, 宝宝淘网络科技有限公司 2008 年 2 月 28 日 内容 概述 注释配置相对于 XML 配置具有很多的优势: 它可以充分利用 J

[Spring系列01]Spring IOC/DI模拟

本文以一个简单的实例大致模拟Spring IOC/DI的运行原理,代码简单分dao,model,service三层.即:dao 与数据库的操作,增删改查等方法model 一般都是javabean对象,例如与数据库的某个表相关联.service 供外部调用,等于对dao,model等进行了包装. 程序结构图如下: 先粘贴部分代码,再进行解释: UserDAO.java package com.ctsh.dao; import com.ctsh.model.User; public interfac

spring ioc aop 原理

spring ioc aop 原理 spring ioc aop 的原理 spring的IoC容器是spring的核心,spring AOP是spring框架的重要组成部分. 在传统的程序设计中,当调用者需要被调用者的协助时,通常由调用者来创建被调用者的实例.但在spring里创建被调用者的工作不再由调用者来完成,因此控制反转(IoC):创建被调用者实例的工作通常由spring容器来完成,然后注入调用者,因此也被称为依赖注入(DI),依赖注入和控制反转是同一个概念. 面向方面编程(AOP)是以另

介绍 Spring IoC 容器和 bean

简介 本章涵盖了 Spring Framework实现控制翻转 (IoC) 的原则. IoC 有时也被称为依赖注入 (DI).这是一个对象定义他们依赖的过程,其中对象之间的相关性,也就是说,它们一起工作,只能通过构造函数参数,参数工厂方法或设置在其构造后的对象实例或者是从一个工厂方法返回的对象实例的属性上.容器在创建的 bean 注入这些依赖.这个过程是根本的反转,因此称为控制反转(IoC),bean 本身通过直接构造类,或作为 Service Locator(服务定位器)模式的机制,来控制其依

Spring IoC的概念

大部分的企业架构都基于Spring框架.它的成功来自于理念,而不是技术,它最为核心的理念是IoC(控制反转)和AOP(面向切面编程),其中IoC是Spring的基础,而AOP则是其重要的功能,最为典型的当属数据库事务的使用. Spring的概述 Spring提供了以下策略: •对于POJO的潜力开发,提供轻量级和低侵入的编程,可以通过配置(XML.注解等)来扩展POJO的功能,通过依赖注入的理念去扩展功能,建议通过接口编程,强调OOD的开发模式理念,降低系统耦合度,提高系统可读性和可扩展性. •

Spring IoC/DI

前言 假设项目层次划分包括logic层和dao层,logic层调用dao层完成业务逻辑,dao层一般与数据库交互.定义两个组件,TestLogic和TestDao,分别操作接口ILogic和IDao,这样程序开发时需要考虑怎样管理这两个组件. 传统方式 这种方式中,当TestLogic组件需要调用TestDao组件时,直接使用关键字new IDao testDao = new TestDao(); 这种方式简单直观,但造成了对外部组件的严重依赖,程序高度耦合,效率低下.当项目需要更换组件时需要修