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.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://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);
}
}
最后提供了测试代码(这里使用的是单元测试):
@Test
public 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();
}