Spring学习笔记之自定义ClassPathXmlApplication…
2018-08-05 07:46:41来源:博客园 阅读 ()
在学习Spring的时候,配置完xml文件后,我们在测试类中一般是创建一个ClassPathXmlApplicationContext类的实例对象通过加载xml配置文件的路劲进行Spring的初始化。然后我们可以通过这个实例对象中getBean的方法来得到xml配置文件中定义好的bean的实例化对象。具体操作如下。
package com.hl.action; import org.junit.Test; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.hl.service.GoodsService; public class GoodsAction { @Test public void save(){ AbstractApplicationContext aac = new ClassPathXmlApplicationContext("applicationContext.xml"); GoodsService gs = aac.getBean("goodsService", GoodsService.class); gs.save(); } }
Spring的配置文件如下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:cache="http://www.springframework.org/schema/cache" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.0.xsd"> <bean id="goodsDao" class="com.hl.dao.GoodsDao"></bean> <bean id="goodsService" class="com.hl.service.GoodsService"> <!-- set方式的注入 --> <property name="goodsDao" ref="goodsDao"></property> <!-- set注入的第二种写法 --> <!-- <property name="goodsDao"><bean class="com.hl.dao.GoodsDao"></bean></property> --> </bean> <!-- 使用构造器注入 --> <!-- 一个参数: <bean id="goodsService" class="com.hl.service.GoodsService"> <constructor-arg ref="goodsDao"></constructor-arg> </bean> 多个参数: <bean id="goodsService" class="com.hl.service.GoodsService"> <constructor-arg index="0" ref="goodsDao"></constructor-arg> <constructor-arg index="1" value="小明"></constructor-arg> </bean> --> </beans>
有关xml配置文件中定义的bean的类这里就不给出了。那么Spring是怎么进行初始化的呢?
通过分析xml配置文件我们可以看到beans跟节点下有多个bean子节点,而bean子节点有两个属性:id和class,class属性值对应的是这个bean定义的类的全路径,id为唯一标识符。这时我们不难想到ClassPathXmlApplicationContext可能是通过解析xml中的配置得到bean节点中中的id和class属性值,然后通过反射根据class值创建类的实例对象并将对应的id值和class实例对象存到一个Map集合中,ClassPathXmlApplicationContext类只需要维护Map集合就行了。到此我们的第一步已经完成了,我们创建了bean的实例,但是我们观察到xml文件中bean节点下还有property子节点,我们还要解析到这个节点并且把该节点中的ref值中的bean对象实例注入到这个bean中,这里同样用到反射的原理。
原理大概就是这个样子,现在我们来实现这个自定义的ClassPathXmlApplicationContext类吧。
首先我们定义两个类用来封装bean节点和property节点的信息。代码如下:
BeanDefinition类:
package com.hl.myspring; import java.util.ArrayList; import java.util.List; /** * 本类是封装了Sring配置文件中的bean对象 * * @author admin * */ public class BeanDefinition { private String id; //配置文件中bean节点中的id属性值 private String myclass;//配置文件中bean节点中的class属性值 private List<PropertyDefinition> list = new ArrayList<PropertyDefinition>(0);//bean节点中的property子节点,应为可能有多个,所以使用list集合存储 public List<PropertyDefinition> getList() { return list; } public void setList(List<PropertyDefinition> list) { this.list = list; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getMyclass() { return myclass; } public void setMyclass(String myclass) { this.myclass = myclass; } }
PropertyDefinition类:
package com.hl.myspring; /** * 封装了spring配置文件中bean节点中的property子节点信息 * @author admin * */ public class PropertyDefinition { private String name; private String ref; private String value; public PropertyDefinition() { super(); } public PropertyDefinition(String name, String ref, String value) { super(); this.name = name; this.ref = ref; this.value = value; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getRef() { return ref; } public void setRef(String ref) { this.ref = ref; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } }
自定义的ClassPathXmlApplicationContext类MyClassPathXmlApplicationContext:
package com.hl.myspring; import java.lang.reflect.Method; 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.DocumentException; import org.dom4j.Element; import org.dom4j.XPath; import org.dom4j.io.SAXReader; /** * 实现一个自己的Spring ClassPathXmlApplicationContext类来通过配置文件来配置bean * 比上个实现增添了一个功能,能够解析配置文件,进行bean的set注入。 * @author admin * */ public class MyClassPathXmlApplicationContext { private List<BeanDefinition> list = new ArrayList<BeanDefinition>(0); //存储所有的bean对象 private Map<String ,Object > map = new HashMap<String ,Object >(0); /** * 根据Spring自带的ClassPathXmlApplicationContext来构建自己的构造方法 * @param path 配置文件名 */ public MyClassPathXmlApplicationContext(String xml){ //解析xml文件,将xml中的bean节点存储到list结合中 parser(xml); //通过list结合中的BeanDefinition元素创建bean对象并根据id-class的键值对存到map集合中 instanceBean(); //把bean节点中property配置注入进去 setProperty(); } /** * 解析xml文件 * @param xml */ private void parser(String xml) { //创建解析器 SAXReader sax = new SAXReader(); //创建解析路劲 URL url = this.getClass().getClassLoader().getResource(xml); //System.out.println(url); //获取domcument元素 try { Document document = sax.read(url); //解析有命名空间的xml需要使用XPath XPath xpath = document.createXPath("//ns:bean"); //创建一个map接和用来设置命名空间 Map<String,String> m = new HashMap<String,String>(0); m.put("ns", "http://www.springframework.org/schema/beans"); //设置命名空间 xpath.setNamespaceURIs(m); //获取所有的bean节点 List<Element> l = xpath.selectNodes(document); for (Element element : l) { //得到bean节点中的id属性值 String id = element.attributeValue("id"); String myclass = element.attributeValue("class"); BeanDefinition b = new BeanDefinition(); b.setId(id); b.setMyclass(myclass); //解析每个bean节点下的多个子节点,可能有多个property配置 List<Element> pl = element.elements(); //循环遍历pl ,把property设置到b的properdefinition集合中 for (Element property : pl ) { String name = property.attributeValue("name"); String ref = property.attributeValue("ref"); String value = property.attributeValue("value"); PropertyDefinition p = new PropertyDefinition(name, ref, value); b.getList().add(p); } list.add(b); } } catch (DocumentException e) { e.printStackTrace(); } } /** * 便利list集合 通过放射来创建对象 */ private void instanceBean() { for (BeanDefinition beanDefinition : list) { try { //System.out.println(beanDefinition.getMyclass()); Class clazz = Class.forName(beanDefinition.getMyclass()); map.put(beanDefinition.getId(), clazz.newInstance()); } catch (Exception e) { e.printStackTrace(); } } } /** * * 进行set注入 */ private void setProperty() { //先遍历BeanDefinition集合 for (BeanDefinition beanDefinition : list) { String beanId = beanDefinition.getId();//得到bean节点的id值 String beanClassName = beanDefinition.getMyclass();//的到bean节点的class属性值 Object bean = map.get(beanId);//得到bean的实例对象 List<PropertyDefinition> pl = beanDefinition.getList();//得到bean节点中的property子节点信息 //遍历pl集合进行set设置 for (PropertyDefinition propertyDefinition : pl) { String propertyName = propertyDefinition.getName();//得到property节点name属性的值 String propertyRef = propertyDefinition.getRef();//得到property节点ref属性的值 String methodName = "set"+propertyName.substring(0,1).toUpperCase()+propertyName.substring(1);//拼写set方法的名称 //创建method方法,并执行 try { Method m = bean.getClass().getMethod(methodName, map.get(propertyRef).getClass()); m.invoke(bean, map.get(propertyRef)); } catch (Exception e) { e.printStackTrace(); } } } } public Object getBean(String key ){ return map.get(key); } }
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
上一篇:1.14(java学习笔记)数组
下一篇:Java-集合
- Spring系列.ApplicationContext接口 2020-06-11
- springboot2配置JavaMelody与springMVC配置JavaMelody 2020-06-11
- 学习Java 8 Stream Api (4) - Stream 终端操作之 collect 2020-06-11
- java学习之第一天 2020-06-11
- 给你一份超详细 Spring Boot 知识清单 2020-06-11
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash