有点时间,正好看了spring的教程,就试着写点东西模拟了下spring的这个简单过程!
强力推荐传智播客,里面的视频资源很nice!
搭建spring环境,通过junit测试效果!
service包下的几个类,都比较简单 ,
PersonServiceDaoImpl:
package com.silence.service.bean;
import com.silence.service.PersonServiceDao;
public class PersonServiceDaoImpl implements PersonServiceDao {
public void add() {
System.out.println("dao 方法");
}
}
PersonServiceImpl:
package com.silence.service.bean;
import com.silence.service.PersonService;
import com.silence.service.PersonServiceDao;
public class PersonServiceImpl implements PersonService {
/* (non-Javadoc)
* @see com.silence.service.bean.PersonService#save()
*/
private PersonServiceDao personDao;
private String name;
public PersonServiceImpl(){
// System.out.println("shilihua !");
}
public void save(){
System.out.println("name="+name);
personDao.add();
}
public void setPersonDao(PersonServiceDao personDao) {
this.personDao = personDao;
}
public PersonServiceDao getPersonDao() {
return personDao;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
PersonService和PersonServiceDao:
package com.silence.service;
public interface PersonService {
public void save();
}
package com.silence.service;
public interface PersonServiceDao {
public void add();
}
Bean:
package com.silence.util;
import java.util.List;
/**
* 装载Beans.xml文件下的Bean的描述
* @author silence
*
*/
public class Bean {
private String id;
private String className;
private List<Property> propertys;
public Bean(String id, String className ,List<Property> propertys) {
this.setId(id);
this.setClassName(className);
this.setPropertys(propertys);
}
public void setClassName(String className) {
this.className = className;
}
public String getClassName() {
return className;
}
public void setId(String id) {
this.id = id;
}
public String getId() {
return id;
}
public void setPropertys(List<Property> propertys) {
this.propertys = propertys;
}
public List<Property> getPropertys() {
return propertys;
}
}
Property:
package com.silence.util;
/**
* 用来装载Beans.xml下的property描述
* @author silence
*
*/
public class Property {
private String name;
private String ref;
private String value ;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setRef(String ref) {
this.ref = ref;
}
public String getRef() {
return ref;
}
public Property(String name, String ref , String value) {
this.name = name;
this.ref = ref;
this.value = value;
}
public void setValue(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
MyClassPathXmlApplicationContext:
package com.silence.util;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.File;
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.apache.commons.beanutils.ConvertUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;
/**
* 模拟一个微量的spring容器
* @author silence
*
*/
public class MyClassPathXmlApplicationContext {
private List<Bean> beans;
private List<Property> propertys;
private Map<String,Object> singleton; //默认情况的下的单例模式!
public MyClassPathXmlApplicationContext(String fileName){
beans = new ArrayList<Bean>();
singleton = new HashMap<String, Object>();
// propertys = new ArrayList<Property>();
this.readXML(fileName);
this.instanceBean();
this.injection();
}
/**
* setter注入
* 实现bean的注入
*/
private void injection() {
for(Bean bean : beans){
Object temp = singleton.get(bean.getId());
if(temp != null && bean.getPropertys() != null){ //对象为null或者属性个数为0的时候不进行注入操作
try{
//获取对象的属性描述,返回一个属性描述的数组
PropertyDescriptor[] ps = Introspector.getBeanInfo(temp.getClass()).getPropertyDescriptors();
for(Property property:bean.getPropertys()){
for(PropertyDescriptor p: ps){
if(property.getName().equals(p.getName())){
Method setter = p.getWriteMethod();
if(setter != null){
Object value = null;
if(property.getRef() != null && !"".equals(property.getRef())){
value = singleton.get(property.getRef());
}else{
//apache的提供的工具类,可以将String转化成已知的基本类型
value = ConvertUtils.convert(property.getValue(), p.getPropertyType());
}
setter.setAccessible(true);
setter.invoke(temp, value);
}
break;
}
}
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
/**
* 对beans里面的对象进行实例化
* 并将初始化后的bean对象装入Map
* @throws Exception
*/
private void instanceBean(){
for(Bean bean:beans){
if(bean.getClassName()!=null&&!"".equals(bean.getClassName().trim())){
try {
singleton.put(bean.getId(), Class.forName(bean.getClassName()).newInstance());
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
/**
* 解析XML
* 使用的是dom4j
* 将配置文件下的所有的bean节点的信息装入beans
* @param fileName
*/
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> elemBeans = xsub.selectNodes(document); //查询document下的所有bean
for(Element e: elemBeans){
String id = e.attributeValue("id"); //获取bean的id和class属性
String className = e.attributeValue("class");
XPath propertyXpath = document.createXPath("ns:property");
propertyXpath.setNamespaceURIs(nsMap);
List<Element> elemProp = propertyXpath.selectNodes(e);
System.out.println(elemProp.size());
if(elemProp.size() > 0 || elemProp != null){
propertys = new ArrayList<Property>();
for(Element e1:elemProp){
String name = e1.attributeValue("name");
String ref = e1.attributeValue("ref");
String value = e1.attributeValue("value");
System.out.println("property="+name +","+ref);
propertys.add(new Property(name, ref ,value));
}
}else{
propertys = null;
}
//这个propertys只有两种情况:里面有内容或者=null
beans.add(new Bean(id, className,propertys));
// System.out.println(id+","+className+","+propertys.size());
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public Object getBean(String beanName){
return this.singleton.get(beanName);
}
}
JUnit测试,记得导入junit的jar包!
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.silence.service.PersonService;
import com.silence.util.MyClassPathXmlApplicationContext;
public class SpringTestCase {
@BeforeClass
public static void setUpBeforeClass()throws Exception{
}
@Test public void instanceSpring(){
// ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
MyClassPathXmlApplicationContext ctx = new MyClassPathXmlApplicationContext("beans.xml");
PersonService ps = (PersonService) ctx.getBean("personService");
ps.save();
}
}
Beans.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="personService" class="com.silence.service.bean.PersonServiceImpl" >
<!-- id不能接受特殊字符 ,name可以接受特殊字符 -->
<property name="personDao" ref="personDao"></property>
<property name="name" value="silence"></property>
</bean>
<bean id="personDao" class = "com.silence.service.bean.PersonServiceDaoImpl"></bean>
</beans>
结果在我这里是正确通过的!
正在学习spring,目前还没发现有什么比较有意思的地方,功力还有得提高!欢迎探讨!