`
8366
  • 浏览: 813390 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

第8讲 --编码剖析Spring装配基本属性的原理

阅读更多

 

    下面我们使用模拟spring容器,来完成Spring容器基本类型的注入,还是使用 ItcastClassPathXMLApplicationContext.java  来模拟spring 容器 注入String类型,int类型.等基本类型,以前我们都是注入的ref引用的 依赖对象

 

 

步骤:首先给PersionServiceBean.java 增加string 类型的变量 name,和int类型的变量 age

package cn.com.xinli.service.impl;

import org.apache.log4j.Logger;

import cn.com.xinli.dao.PersionDao;
import cn.com.xinli.service.PersionSevice;
										   
public class PersionServiceBean implements PersionSevice 
{
	Logger log=Logger.getLogger(PersionServiceBean.class);
	private PersionDao persionDao;
	private String name;
	private int age;
	public int getAge()
	{
		return age;
	}
	public void setAge(int age)
	{
		this.age = age;
	}
	public String getName()
	{
		return name;
	}
	public void setName(String name)
	{
		this.name = name;
	}
	public PersionDao getPersionDao()
	{
		return persionDao;
	}
	public void setPersionDao(PersionDao persionDao)
	{
		this.persionDao = persionDao;
	}
	public void init()
	{
		log.info("初始化资源");
	}
	public PersionServiceBean() 
	{
		log.info("我被实例化了");
	}

	public void save()
	{
		log.info("name:"+name);
		log.info("age:"+age);
		 this.persionDao.add();
	}
	public void destory()
	{
		log.info("释放资源");
	}
}	

 

(2) 修改 ItcastClassPathXMLApplicationContext 容器代码,主要是修改在容器读beans.xml配置文件的时候读到属性的值,和在注入时候完成对基本类型的注入.还需要修改 PropertyDefinition.java 加上一个value属性,和get,set方法 .

 

 

package junit.test;

import java.beans.Introspector;
import java.beans.PropertyDescriptor;
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.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;
import org.springframework.core.Conventions;

/**
 * 实现的spring容器一样的功能
 *
 */
public class ItcastClassPathXMLApplicationContext 
{	
	Logger log=Logger.getLogger(ItcastClassPathXMLApplicationContext.class);
	private List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>();
	private Map<String, Object> sigletons = new HashMap<String, Object>();
	
	public ItcastClassPathXMLApplicationContext(String filename){
		this.readXML(filename);
		this.instanceBeans();
		this.injectObject();
	}
	
	/**
	 * 为属性注入值
	 */
	private void injectObject() 
	{
		for(BeanDefinition beanDefinition : beanDefines){
			Object bean = sigletons.get(beanDefinition.getId());
			if(bean!=null)
			{
				try
				{
					//得到bean对象所有的属性声明,返回的是一个数组
					PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
					for(PropertyDefinition propertyDefinition : beanDefinition.getPropertys())
					{
						for(PropertyDescriptor properdesc : ps)
						{
							//如果xml中读取的属性名字是bean对象属性的名字
							if(propertyDefinition.getName().equals(properdesc.getName()))
							{
								//setter方法是写方法
								Method setter = properdesc.getWriteMethod();
								//获取属性的setter方法 ,如果方法是private需要调用
								if(setter!=null)
								{
									if(propertyDefinition.getRef()!=null && !"".equals(propertyDefinition.getRef()))
									{
										Object value = sigletons.get(propertyDefinition.getRef());
										setter.setAccessible(true);
										setter.invoke(bean, value);//把引用对象注入到属性
										
									}
									else
									{
										
										Object value = ConvertUtils.convert(propertyDefinition.getValue(), properdesc.getPropertyType());
										setter.setAccessible(true);
										setter.invoke(bean, value);//把引用对象注入到属性
									}
									
								}
								break;
							}
						}
					}
				} 
				catch (Exception e) 
				{
				}
			}
		}
	}
	/**
	 * 完成bean的实例化
	 */
	private void instanceBeans() {
		for(BeanDefinition beanDefinition : beanDefines){
			try {
				if(beanDefinition.getClassName()!=null && !"".equals(beanDefinition.getClassName().trim()))
					sigletons.put(beanDefinition.getId(), Class.forName(beanDefinition.getClassName()).newInstance());
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
	}
	/**
	 * 读取xml配置文件
	 * @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> beans = xsub.selectNodes(document);//获取文档下所有bean节点 
	         for(Element element: beans){
	            String id = element.attributeValue("id");//获取id属性值
	            String clazz = element.attributeValue("class"); //获取class属性值        
	            BeanDefinition beanDefine = new BeanDefinition(id, clazz);
	            XPath propertysub =  element.createXPath("ns:property");
	            propertysub.setNamespaceURIs(nsMap);//设置命名空间
	            List<Element> propertys = propertysub.selectNodes(element);
	            for(Element property : propertys){	            	
	            	String propertyName = property.attributeValue("name");
	            	String propertyref = property.attributeValue("ref");
	            	String propertyValue = property.attributeValue("value");
	            	log.info(propertyValue);
	            	PropertyDefinition propertyDefinition = new PropertyDefinition(propertyName, propertyref,propertyValue);
	            	beanDefine.getPropertys().add(propertyDefinition);
	            }
	            beanDefines.add(beanDefine);
	         } 
	        }catch(Exception e){   
	            e.printStackTrace();
	        }
	}
	/**
	 * 获取bean实例
	 * @param beanName
	 * @return
	 */
	public Object getBean(String beanName){
		return this.sigletons.get(beanName);
	}
}

 

注意:

a.红色加粗的 的代码 我们使用了 commons-beanutils.jar 提供的方法,它能根据属性的类型完成转换,可以把String->int 等,因为我们在配置文件一般都是这样写的 <property name="age" value="26"/> 这个工具方法就可以帮助我们把26 这个string类型转换为 int类型.

b.蓝色的代码 表示 当ref不为空的情况下 我们为属性注入引用对象,否则直接注入配置文件中属性所代表的值.

c. 咖啡色 代码 标识我们构造属性bean的使用在加一个类型.

 

(3) 在 PersionServiceBean.java 中我们使用bean.xml中的name和age属性, 看看自己的 ItcastClassPathXMLApplicationContext  使用完成了属性的注入

 

package cn.com.xinli.service.impl;

import org.apache.log4j.Logger;

import cn.com.xinli.dao.PersionDao;
import cn.com.xinli.service.PersionSevice;
										   
public class PersionServiceBean implements PersionSevice 
{
	Logger log=Logger.getLogger(PersionServiceBean.class);
	private PersionDao persionDao;
	private String name;
	private int age;
	public int getAge()
	{
		return age;
	}
	public void setAge(int age)
	{
		this.age = age;
	}
	public String getName()
	{
		return name;
	}
	public void setName(String name)
	{
		this.name = name;
	}
	public PersionDao getPersionDao()
	{
		return persionDao;
	}
	public void setPersionDao(PersionDao persionDao)
	{
		this.persionDao = persionDao;
	}
	public void init()
	{
		log.info("初始化资源");
	}
	public PersionServiceBean() 
	{
		log.info("我被实例化了");
	}

	public void save()
	{
		log.info("name:"+name);
		log.info("age:"+age);
		 this.persionDao.add();
	}
	public void destory()
	{
		log.info("释放资源");
	}
}	

 

(4)测试

 

ItcastClassPathXMLApplicationContext ctx = new ItcastClassPathXMLApplicationContext("beans.xml");
  PersionSevice ps=(PersionSevice)ctx.getBean("persionServiceBean");
        
  ps.save();

 

(5) 结果

2009-05-30 11:08:46,203  INFO (PersionServiceBean.java:44) - 我被实例化了
2009-05-30 11:08:47,187  INFO (PersionServiceBean.java:49) - name:huxl
2009-05-30 11:08:47,187  INFO (PersionServiceBean.java:50) - age:26
2009-05-30 11:08:47,187  INFO (PersionDaoBean.java:15) - 执行了PersionDaoBean中的add()方法

 

分享到:
评论

相关推荐

    深入解析SPRING架构与设计原理(第2版) 带标签 高清版,深入剖析spring运行机制

    《深入解析SPRING架构与设计原理(第2版)》是一部深入探讨Spring框架核心机制和技术细节的著作。这本书旨在帮助读者全面理解Spring的工作原理,掌握其设计思想,并能灵活运用到实际开发中。标签"Spring"表明了主要...

    spring攻略(第一版)源码

    8. **Spring Boot**:虽然《Spring攻略(第一版)》可能不包含Spring Boot的内容,但理解Spring的基本原理对于学习Spring Boot至关重要,因为Spring Boot是基于Spring框架的快速开发工具。 通过仔细研读这份源码,...

    SPRING技术内幕:深入解析SPRING架构与设计原理第2版

    《SPRING技术内幕:深入解析SPRING架构与设计原理第2版》这本书是Spring框架学习者和开发者的重要参考资料。Spring作为Java生态系统中的核心组件,它以其模块化、易用性和强大的功能深受广大开发者喜爱。本篇文章将...

    [Pro.Spring.3(2012)].Clarence.Ho.文字版

    ### 第8章:Spring JDBC支持 该章节聚焦于Spring框架提供的JDBC支持,包括如何利用Spring JDBC模板来简化数据库操作,提高代码的异常处理能力和资源管理效率。读者将学会如何在Spring中执行数据库查询、更新、批量...

    java web技术开发大全(最全最新)

    第8章 Struts 2进阶 第9章 Struts 2的* 第10章 Struts 2的类型转换 第11章 Struts 2的输入校验 第12章 文件的上传和下载 第13章 国际化 第14章 Struts 2的标签库 第15章 Struts 2对AJAX的支持 第16章 用...

    spring入门小例子

    - `Spring_8_AOP_1` 可能是系列教程的第一部分,讲解了AOP的基本概念和使用场景。 通过这个简单的入门例子,你可以逐步掌握Spring的基本用法,包括依赖注入和面向切面编程的实践。同时,结合提供的文件,你可以...

    java web开发技术大全

    第8章 Struts 2进阶 第9章 Struts 2的* 第10章 Struts 2的类型转换 第11章 Struts 2的输入校验 第12章 文件的上传和下载 第13章 国际化 第14章 Struts 2的标签库 第15章 Struts 2对AJAX的支持 第16...

    spring源码可导入eclipse版本 第三部分

    Spring框架是Java开发中不可或缺的重要组成部分,其源码解析对于深入理解其工作原理和技术细节至关重要。本资源提供了可以直接导入Eclipse的Spring 4.3.18版本源码,简化了开发者研究源码的前期准备步骤。在这一部分...

    基于ssm网上服装销售系统.zip

    【SSM网上服装销售系统】是一个综合性的项目,它结合了Spring、SpringMVC和MyBatis三个核心组件,构建了一个高效、灵活的Java Web应用。这个系统旨在为用户提供便捷的在线购物体验,特别是针对服装商品。以下是这个...

    javaweb仿百度云网盘项目源码

    它在Windows环境下部署,采用UTF-8编码,确保跨平台的兼容性和多语言支持。使用的JDK版本为1.8,这是Java SE 8,引入了许多重要的新特性,如Lambda表达式、Stream API和日期时间API,提高了代码的简洁性和性能。 1....

    基于ssm+mysql的团员管理系统源码数据库论文.docx

    需求分析是系统开发的第一步,包括需求概述、功能需求和非功能需求。例如,系统可能需要管理团员的基本信息、活动记录、团费缴纳情况等功能,并且要保证系统的安全性、稳定性、易用性等非功能需求。 9. **系统设计...

    【ssm项目源码】停车场管理系统.zip

    【ssm项目源码】停车场管理系统是一个基于Java技术的Web应用程序,主要...通过学习和实践此类项目,开发者不仅可以提升Java Web开发技能,还能了解到完整的项目开发流程,包括需求分析、设计、编码、测试和运维等环节。

    基于ssm+jsp网上服装销售系统源码数据库.zip

    通过对这些知识点的深入理解和实践,开发者可以掌握一套完整的Web应用程序开发流程,从需求分析、设计、编码到测试和部署。这个基于SSM+JSP的网上服装销售系统源码数据库为学习者提供了一个很好的实践平台,有助于...

    webx3框架指南PDF教程附学习Demo

    2.2. SpringExt原理 ......................................................................................... 16 2.2.1. XML Schema中的秘密 ...............................................................

Global site tag (gtag.js) - Google Analytics