Spring之旅--Spring管理bean的原理

        各位老少爷们,赶紧系紧安全带,菜鸟开车,防止车速过快偷笑。言归正传,本篇文章呢,主要是来探讨一下Spring管理bean的原理。

       

   
     

   
     
    
    
      

   
     

        如上xml文件所示,通常我们在使用Spring管理系统应用的组件时,在Spring的核心配置文件中,配置上需要管理组件的信息就可以了,剩下的就都交于Spring框架了。但是我们不要满足于用,更要知道其中的原理。知己知彼,百战不殆。为了了解Spring框架如何管理bean的,接下来我们简单模仿一下Spring 容器。

       
package com.marswzp.test.beanbase;

/**
 * bean 对象基本定义
 * @author Administrator
 *
 */
public class BeanDefintion {

	private String id;
	
	private String className;

	
	public BeanDefintion(String id, String className) {
		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;
	}
	
	
	
	
}
       
package com.marswzp.test.ioc;

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;

import com.marswzp.test.beanbase.BeanDefintion;

/**
 * 
 * 容器:模拟Spring容器
 * @author Administrator
 *
 */
public class MyTestClassPathXMLApplicationContext {

	//存放BeanDefintion 对象的集合
	private List
    
    
     
      beanDefintions = new ArrayList
     
     
      
      ();
	
	//存放实例化后的bean对象
	private Map
      
      
       
        singletons = new HashMap
       
       
        
        ();
	
	/**
	 * 容器构造方法:用于读取配置文件
	 * @param resource
	 */
	public MyTestClassPathXMLApplicationContext(String resourceName){
		
		//读取配置文件,并将bean的配置信息放入集合中
		this.readXML(resourceName);
		
		//实例化bean
		this.instanceBean();
	}
	
	

	/**
	 * 根据xml资源名称读取xml文件
	 * @param resourceName
	 */
	public void readXML(String resourceName){
		
		//采用dom4j  的SAX方式读取xml配置文件
	    SAXReader saxReader = new SAXReader();
		
	    Document document = null;
	    
	    
	    try {
	    	
	    	URL xmlPath = this.getClass().getClassLoader().getResource(resourceName);//获取资源路径
	    	document = saxReader.read(xmlPath);//读取路径的文件,实例化xml文档对象
	    	
	    	/**
	    	 * 采用xpath 匹配查询xml文档节点
	    	 */
	    	
	    	
	    	//增加XPath的命名空间
	    	Map
        
        
          nsMap = new HashMap 
         
           (); nsMap.put("ns", "http://www.springframework.org/schema/beans"); XPath xsub = document.createXPath("//ns:beans/ns:bean");//创建beans/bean的查询路径 //设置 命名空间 xsub.setNamespaceURIs(nsMap); //匹配解析xml文档对象,返回beans.xml文件中bean配置信息节点 List 
          
            beans = xsub.selectNodes(document); //遍历获取bean配置信息,实例化BeanDefintion对象 for(Element bean : beans){ String id = bean.attributeValue("id");//id属性值 String clazz = bean.attributeValue("class");//class属性值 //创建BeanDefintion 对象 BeanDefintion beanDefintion = new BeanDefintion(id,clazz); //bean配置对象方法集合中 beanDefintions.add(beanDefintion); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 通过 反射集合实例化bean */ private void instanceBean() { for(BeanDefintion beanDefintion : beanDefintions){ try { if(beanDefintion.getClassName() !=null && !"".equals(beanDefintion.getClassName().trim())){ singletons.put(beanDefintion.getId(), Class.forName(beanDefintion.getClassName()).newInstance()); } } catch (Exception e) { e.printStackTrace(); } } } /** * 根据id获取bean对象 * @param id * @return */ public Object getBean(String key){ return singletons.get(key); } } 
           
          
        
       
       
      
      
     
     
    
    
        MyTestClassPathXMLApplicationContext类模仿了Spring 容器,仔细分析其中的代码,可以知道,在这个容器类中,我主要做了以下几个步骤:

        1. 读取xml配置文件, 数据封装到BeanDefinition。

        2. 将BeanDefinition对象存入list。

        3. 遍历list, 通过反射产生对象并存入map。

        4. 调用getBean方法返回一个bean对象, 此bean对象为单例。

        读取xml配置文件时,我采用的是dom4j 的sax方法,并且通过xpath来匹配xml文档中的节点。因此我们需要在项目中引入两个jar包:dom4j-1.6.1.jar、jaxen-1.1-beta-6.jar。将这两个jar扔到项目的lib文件夹下即可。当我们解析完成xml文档,并且将xml文档中<bean>节点所配置的信息封装到BeanDefinition对象中时,接下来容器会通过这些封装的配置信息,通过反射技术,实例化bean对象,并存入一个Map集合。容器提供了一个getBean方法,在容器外部可以获取到实例化后的bean对象。
        容器类已经模仿好了,那么接下来需要进行实例测试了。事先我定义了一个接口,并且编写实现类实现了这个接口,代码如下。
       
/**
 *学生接口
 * @author Administrator
 *
 */
public interface StudentService {

	public void save();
	
	public void say();
	
}




import com.marswzp.service.StudentService;

/**
 * 接口实现类
 * @author Administrator
 *
 */
public class StudentServiceImpl implements StudentService {

	public void save() {

		System.out.println("我是一个保存方法");
		
	}

	public void say() {
        System.out.println("我是一个学生,我要抓住凹凸曼!!!");
	}

}













        编写测试用例,我采用的是单元测试框架junit4进行测试单元测试,测试用例代码如下。
       

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.marswzp.service.PersonService;
import com.marswzp.service.StudentService;
import com.marswzp.test.ioc.MyTestClassPathXMLApplicationContext;



/**
 * 测试类
 * @author Administrator
 *
 */
public class JunitTest {

	@Before
	public void star() {

		System.out.println("开始测试");
		
	}
	
	@After
	public  void end() {
       System.out.println("测试结束");
	}
	
	
	@Test
	public void testMyIoc(){
		
		/**
		 * 模仿IOC
		 */
		MyTestClassPathXMLApplicationContext context  = new MyTestClassPathXMLApplicationContext("beans.xml");
		
		StudentService  studentService = (StudentService)context.getBean("studentService");
		
		studentService.say();
		
	}
	
	
	
}
        以上就是通过模仿Spring容器管理bean的过程,可以让我们可以更深入的理解Spring管理bean对象的机制,当然以上的模仿只是做简单的模仿,Spring 的容器提供了更多的功能和更多的行为,需要你慢慢地去理解和使用。
        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值