Spring笔记——模拟spring的bean管理原理以及依赖注入原理

有点时间,正好看了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,目前还没发现有什么比较有意思的地方,功力还有得提高!欢迎探讨!




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值