模拟Spring的内部实现

来源:互联网 发布:linux 切换root用户 编辑:程序博客网 时间:2024/06/14 07:39

Spring是一个开源的控制反转(Inversion of Control,IOC)和面向切面(AOP)的容器框架。它的主要目的是简化企业开发。

我们都知道,Spring框架的xml文件中的<bean>很重要,<bean>元素用于配置要交给spring管理的Bean类,id为这个bean取了一个名称,这个名称是唯一的,通过id获取到这个bean;

所以我就在想能不能通过自己的方法得到配置在<bean>元素中的Bean类的对象。完全不需要依赖Spring框架。想了一下还是可以实现的,这里要用到反射的技术。

首先,创建一个BeanDefinition类,它的作用是用来存放id和Bean类的类名;代码如下:

package junit.test;public class BeanDefinition {private String id;private String className;public BeanDefinition(String id, String className) {super();this.id = id;this.className = className;}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getClassName() {return className;}public void setClassName(String className) {this.className = className;}}



xml文件(applicationContext.xml)代码:

<?xml verapplicationContext.xmlsion="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:jdbc="http://www.springframework.org/schema/jdbc"xmlns:jee="http://www.springframework.org/schema/jee"xmlns:tx="http://www.springframework.org/schema/tx"xmlns:jpa="http://www.springframework.org/schema/data/jpa"xmlns:util="http://www.springframework.org/schema/util"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsdhttp://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsdhttp://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsdhttp://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsdhttp://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd"><bean id="personService" class="service.impl.PersonServiceBean"></bean></beans>


接下来就是重点了,如何获取xml文件中的<bean>中的id和class属性,并通过反射的方式得到该class的实例化对象。

代码如下:

package junit.test;import java.net.URL;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import org.dom4j.Document;import org.dom4j.Element;import org.dom4j.XPath;import org.dom4j.io.SAXReader;/** * 自己做的模拟spring容器 * @author YH * */public class ClassPathXMLApplicationContext {private List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>();private Map<String,Object> sigletons = new HashMap<String,Object>();public ClassPathXMLApplicationContext(String filename){this.readXML(filename);this.instanceBeans();}// 完成bean的实例化private void instanceBeans() {for(BeanDefinition beanDefinition:beanDefines){try {if(beanDefinition.getClassName()!=null&&!"".equals(beanDefinition.getClassName())){System.out.println(beanDefinition.getClassName());sigletons.put(beanDefinition.getId(), Class.forName(beanDefinition.getClassName()).newInstance());}} catch (Exception e) {e.printStackTrace();} }}//读取xml配置文件(使用dom4j读取spring配置文件,这里要用到dom4j的jar包)private void readXML(String filename) {SAXReader saxReader = new SAXReader();Document document = null;try{//取得文件URL xmlpath=this.getClass().getClassLoader().getResource(filename);document = saxReader.read(xmlpath);Map<String,String> nsMap = new HashMap<String,String>();nsMap.put("ns","http://www.springframework.org/schema/beans");//加入命名空间XPath xsub = document.createXPath("//ns:beans/ns:bean");//创建beans/bean查询路径xsub.setNamespaceURIs(nsMap);//设置命名空间List<Element> beans = xsub.selectNodes(document);//获取文档下所有bean节点for(Element element:beans){String id = element.attributeValue("id");//获取id属性值String clazz = element.attributeValue("class");BeanDefinition beanDefine = new BeanDefinition(id,clazz);beanDefines.add(beanDefine);}}catch(Exception e){e.printStackTrace();}}//提供了一个getBean方法,获取bean实例public Object getBean(String beanName){return this.sigletons.get(beanName);}}



最后提供了测试代码(这里使用的是单元测试):

@Testpublic void mySpring(){ClassPathXMLApplicationContext ctx = new ClassPathXMLApplicationContext("applicationContext.xml");// id="personService" class="service.impl.PersonServiceBean";通过ClassPathXMLApplicationContext类的getBean方法得到service.impl.PersonServiceBean的实例化对象PersonService personService = (PersonService)ctx.getBean("personService");//调用该对象的save()方法,该方法内容:System.out.println("我是save()方法");personService.save();}



0 0
原创粉丝点击