`
Luob.
  • 浏览: 1570594 次
  • 来自: 上海
社区版块
存档分类
最新评论

Spring IOC控制反转 依赖注入DI

阅读更多
目录
1.使用IOC控制反转 中的DI依赖注入
   手工注入
      A:使用set 方法 注入 (1.使用 ref  2.使用bean)
      B.使用 构造 注入
   自动注入
      C 注解 (未)
2.自己编写 模仿 spring 的 注入功能
3.依赖 注入各种集合类型  set, map, list, properties

使用DI依赖注入dao( 编写dao---> 在service中使用 set方法注入dao-->配置)
package com.person.dao;

public interface PersonDao {
	public void add();
}

package com.person.dao.impl;

import com.person.dao.PersonDao;


public class PersonDaoBean implements PersonDao {
	public void add(){
		System.out.println("调用personDao中的add方法");
	}
}



import com.person.dao.PersonDao;
import com.person.service.PersonService;

public class PersonServiceBean implements PersonService {
	
	private PersonDao personDao; //注入 object
	
	private String name;  //注入基本类型 
	
	
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}



	//只需要提供 set方法 就可以  让 spring 的反射机制 给我们 注入dao 
	public void setPersonDao(PersonDao personDao) {
		this.personDao = personDao;
	}

	//调用 dao中的方法    
	public void add(){
		personDao.add();
	}

        
}



<!-- 使用 spring 管理 dao -->
	<bean id="personDao" class="com.person.dao.impl.PersonDaoBean">
	</bean>
	
	<!-- 这里配置后 就会有 spring来管理, 注意id 和name 的区别  -->
	<bean id="personService" class="com.person.service.impl.PersonServiceBean" lazy-init="true" >
		<!-- 配置 service 中引用 的dao 对象 为上面的 配置的 dao -->
		<property name="personDao" ref="personDao"/>
		<!-- 也可以使用这种 方式 注入   区别 在于   上面的 personDao就可以不用定义了 ,这样 其他的 service就不能访问 personDao, 根据需求使用  这两种方式
		<property name="personDao">
			<bean class="com.person.dao.impl.PersonDaoBean"/>
		</property> -->
		
		<!-- 为基本上属性注入值 -->
		<property name="name" value="JACK"/>
	</bean>


@Test   //测试  spring的 依赖注入
	public void init7(){
		ApplicationContext ctx=new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
		PersonService personService=(PersonService)ctx.getBean("personService");
		personService.add();
	}


//发现  打印出 "调用personDao中的add方法" 这句话 说明 spring 的 IOC DI 成功.

2.下面我们来  模仿 spring的 注入功能  我想 这样你就更清楚了 (主要在我们昨天 编写的 mini spring 框架上 添加 属性的 注入功能)

在 加入一个 commons-beanutils-1.8.3.jar  帮助我们进行 类型转换

1.首先 定义 spring 配置中的 bean
package junit.test;

import java.util.ArrayList;
import java.util.List;

/**
 * 定义  保存 spring配置文件中的bean对象
 * @author Bin
 */
public class BeanDefinition {
	
	private String id;  //对应 spring配置文件中的id
	private String className;   //对应 spring配置文件中的class 
	
	//定义  bean中  属性的节点  集合 
	private List<PropertyDefinition> propertys= new ArrayList<PropertyDefinition>();
		
	
	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;
	}
	public BeanDefinition() {
	}
	
	public List<PropertyDefinition> getPropertys() {
		return propertys;
	}
	public void setPropertys(List<PropertyDefinition> propertys) {
		this.propertys = propertys;
	}
	public BeanDefinition(String id, String className) {
		this.id = id;
		this.className = className;
	}
	
	
}


2.定义 bean节点中的属性  property
package junit.test;

public class PropertyDefinition {
	private String name;  //对应配置 文件中的name 
	private String ref;   //对应配置 文件中的ref
	private String value;  //为基本属性注入值
	
	
	public String getValue() {
		return value;
	}
	public void setValue(String value) {
		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 PropertyDefinition() {
		super();
		// TODO Auto-generated constructor stub
	}
	public PropertyDefinition(String name, String ref) {
		super();
		this.name = name;
		this.ref = ref;
	}
	public PropertyDefinition(String name, String ref, String value) {
		super();
		this.name = name;
		this.ref = ref;
		this.value = value;
	}
	
	
	
}



3.定义 ClassPathXmlApplicationContext 
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.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;

import com.sun.xml.internal.fastinfoset.stax.events.Util;


/*
 * 编写自己的  mini spring 容器
 * 来模拟spring 的工作
 */
public class MySpringClassPathXmlApplicationContext {
	
	//保存 配置文件中的 bean 的信息  
	private List<BeanDefinition> beandefines=new ArrayList<BeanDefinition>();
	
	//保存初始化 后的对象
	private Map<String,Object> sigletons=new HashMap<String,Object>();
	
	
	//构造方法
	public MySpringClassPathXmlApplicationContext(String fileName) {
		//读取配置文件
		this.readXml(fileName);
		//初始化所有的bean
		this.instanceBean();
		//为所有bean 依赖注入 属性 
		this.injectObject();
	}


	/**==================
	 *   读取xml配置文件
	 * ==================
	 * @author Bin
	 * @param fileName
	 */
	private void readXml(String fileName) {
		SAXReader saxReader=new SAXReader();
		Document doucment=null;
		try {
			URL xmlPath=this.getClass().getClassLoader().getResource(fileName);
			doucment=saxReader.read(xmlPath);
			Map<String,String> nsMap=new HashMap<String,String>();
			//给spring配置文件的命名空间  一个别名 ns
			nsMap.put("ns","http://www.springframework.org/schema/beans"); //加入命名空间  xmlns: spring配置文件中的
			XPath xsub=doucment.createXPath("//ns:beans/ns:bean"); //创建 beans/bean 查询路径
			
			xsub.setNamespaceURIs(nsMap); //设置命名空间
			List<Element> beans=xsub.selectNodes(doucment); //获取文档下的所有bean节点
			
			for (Element element : beans) {
				String id=element.attributeValue("id"); //获取 id的属性值
				String clazz=element.attributeValue("class"); // 获取 class属性

				//类是 spring中的 : org.springframework.beans.factory.config.BeanDefinition;
				BeanDefinition beandefine=new BeanDefinition(id,clazz);
				
				//解析 bean节点中的property 属性节点
				XPath propertysub=element.createXPath("ns:property"); //创建 property的查询路径  //使用相对路径 
				propertysub.setNamespaceURIs(nsMap); //设置命名空间
				List<Element> propertys=propertysub.selectNodes(element); //根据 查询路径 在  这个元素中查找  子元素
				for (Element property : propertys) { //取出查找到 的 property 子节点
					String propertyName=property.attributeValue("name");
					String propertyRef=property.attributeValue("ref");
					String propertyValue=property.attributeValue("value");
					PropertyDefinition propertyDefinition= new PropertyDefinition(propertyName,propertyRef,propertyValue);
					//放入 bean 的property 集合中 
					beandefine.getPropertys().add(propertyDefinition);
				}
				beandefines.add(beandefine);  //将这个bean保存的 集合中
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**===================================
	 *   完成Bean 的实例化
	 * ===================================
	 * @author Bin
	 */
	private void instanceBean() {
		for (BeanDefinition beandefine : beandefines) {
			try {
				if(!Util.isEmptyString(beandefine.getClassName()))
					sigletons.put(beandefine.getId(), Class.forName(beandefine.getClassName().trim()).newInstance());
			}catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	//注入对象  主要是  根据 set 方法  
	private void injectObject() {
		try{
			//遍历 spring配置中的 bean节点信息的集合 (id class)
			for (BeanDefinition beandefine : beandefines) {
				//根据id 到 初试化好了的 对象集合中 查找对象
				Object bean=sigletons.get(beandefine.getId());
				if(bean!=null){
					//如果对象不为空 就获取这个对象的 所有属性信息 
					PropertyDescriptor[] ps=Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
					//遍历  bean节点中  所有的 property 子节点集合 
					for(PropertyDefinition propertyDefinition:beandefine.getPropertys()){
						//遍历 初始化好后的 对象中的 属性 描述
						for(PropertyDescriptor properDesc:ps){
							//如果 两个 属性名相等  就说明找到了这个对象中的属性了
							if(propertyDefinition.getName().equals(properDesc.getName())){
								Method setter=properDesc.getWriteMethod(); //获取属性的setter方法 可  能是 public  ,private 类型
								if(setter!=null){
									Object value=null;
									if(!setter.isAccessible()){ //判断是否是 私有只读的 
										   setter.setAccessible(true);  //强制访问 私有属性的 setter 方法
									}
									if(!Util.isEmptyString(propertyDefinition.getRef())){ //说明是引用类型
										//根据属性节点中的ref 到 sigletons 中取出对象 
										value=sigletons.get(propertyDefinition.getRef());
									}else{//说明 是基本类型  
										value=ConvertUtils.convert(propertyDefinition.getValue(),properDesc.getPropertyType());
									}
									setter.invoke(bean, value);  //给 某个对象某个方法 注入一个值
								}
								break;  //注入 完一个 属性后 就跳出  继续为下一个属性 赋值
							}
						}
					}
				}
			}
		}catch(Exception e){
			e.printStackTrace();
		}
		
	}
	
	
	/**=======================
	 *    获取bean 
	 * =======================
	 * @param beanName
	 * @return
	 */
	public Object getBean(String beanName){
		return this.sigletons.get(beanName);
	}
	
}



4.测试
	@Test  //测试自己  编写的 spring 注入 功能
	public void init8(){
		MySpringClassPathXmlApplicationContext ctx= new MySpringClassPathXmlApplicationContext("applicationContext.xml");
		PersonService personService=(PersonService)ctx.getBean("personService");
		personService.add();
	}


如果上面的 打印出了 "调用personDao中的add方法" 说明我们手动的 编写的 spring注入 成成功实现了 注入对象和 注入基本类型. 我想这样 不会告诉我说你不懂 spring IOC了吧  呵呵

3.依赖 注入各种集合类型  set, map, list, properties
package com.person.service;

import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

public interface PersonService {
	
	//为了能在  前台访问 所以就提供这样的一个方法 用来放回注入后的set 集合
	public Set<String> getSets();
	public List<String> getLists();
	public Properties getProperties();
	public Map<String, String> getMaps();
	
	
	public void save();
	public void add();
}

package com.person.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import com.person.dao.PersonDao;
import com.person.service.PersonService;

public class PersonServiceBean implements PersonService {
	
	//引用对象
	private PersonDao personDao; //注入 object
	//基本类型 
	private String name;  //注入基本类型 
	// Set 集合类型
	private Set<String> sets=new HashSet<String>();
	// list 集合类型
	private List<String> lists=new ArrayList<String>();
	// Properties 集合类型
	private Properties properties=new Properties();
	// Map 集合类型
	private Map<String,String> maps=new HashMap<String,String>();
	
	// get set
}


<?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/context 
    http://www.springframework.org/schema/context/spring-context-3.0.xsd
    http://www.springframework.org/schema/beans   
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd "> 
	
	<!-- 使用 spring 管理 dao -->
	<bean id="personDao" class="com.person.dao.impl.PersonDaoBean">
	</bean>
	
	<!-- 这里配置后 就会有 spring来管理, 注意id 和name 的区别  -->
	<bean id="personService" class="com.person.service.impl.PersonServiceBean" lazy-init="true" >
		<!-- 配置 service 中引用 的dao 对象 为上面的 配置的 dao -->
		<property name="personDao" ref="personDao"/>
		<!-- 也可以使用这种 方式 注入   区别 在于   上面的 personDao就可以不用定义了 ,这样 其他的 service就不能访问 personDao, 根据需求使用  这两种方式
		<property name="personDao">
			<bean class="com.person.dao.impl.PersonDaoBean"/>
		</property> -->
		
		<!-- 为基本上属性注入值 -->
		<property name="name" value="JACK"/>
		
		<property name="sets">
			<set>
				<value>第一个</value>
				<value>第二个</value>
				<value>第三个</value>
				<value>第四个</value>
			</set>
		</property>
		
		<property name="lists">
			<list>
				<value>第一个List元素</value>
				<value>第二个List元素</value>
				<value>第三个List元素</value>
			</list>
		</property>
		
		<property name="properties">
			<props>
				<prop key="key1">value1</prop>
				<prop key="key2">value2</prop>
				<prop key="key3">value3</prop>
			</props>
		</property>
		<property name="maps">
			<map>
				<entry key="key-1" value="value-1"/>
				<entry key="key-2" value="value-2"/>
				<entry key="key-3" value="value-3"/>
			</map>
		</property>
	</bean>
</beans>

	
	@Test   //测试  spring的 依赖注入
	public void init9(){
		ApplicationContext ctx=new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
		PersonService personService=(PersonService)ctx.getBean("personService");
		personService.add();
		System.out.println("============set============");
		for (String name : personService.getSets()) {
			System.out.println(name);
		} 
		System.out.println("============List============");
		for (String desc : personService.getLists()) {
			System.out.println(desc);
		}
		System.out.println("============properties============");
		for (Object key : personService.getProperties().keySet()) {
			System.out.println(key+"="+personService.getProperties().getProperty(key.toString()));
		}
		System.out.println("============maps============");
		for (String key: personService.getMaps().keySet()) {
			System.out.println(key+"="+personService.getMaps().get(key));
		}
	}


5.使用构造注入
package com.person.service.impl;

import com.person.dao.PersonDao;
import com.person.service.PersonService;

public class PersonServiceBean implements PersonService {
	
	//引用对象
	private PersonDao personDao; //注入 object
	//基本类型 
	private String name;  //注入基本类型 
	
	// 使用构造注入
	public PersonServiceBean(PersonDao personDao, String name) {
		this.personDao = personDao;
		this.name = name;
	}
	
}

	<!-- 使用 spring 管理 dao -->
	<bean id="personDao" class="com.person.dao.impl.PersonDaoBean">
	</bean>
	<bean id="personService4" class="com.person.service.impl.PersonServiceBean" >
		<constructor-arg index="0" type="com.person.dao.PersonDao" ref="personDao"/>
		<constructor-arg index="1" type="java.lang.String" value="欢迎踩踩!"/>
	</bean>

@Test
	public void init10(){
		ApplicationContext ctx=new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
		PersonService personService=(PersonService)ctx.getBean("personService4");
		personService.add();
	}


//从上面可以测试出 我们在给构造函数 给参数的时候 可以根据 name 和 index 来赋值  type是可选的
0
0
分享到:
评论
2 楼 xuanjunqi 2012-12-28  
不错 谢谢LZ
1 楼 befairy 2012-12-17  
Mark....谢谢分享。。。

相关推荐

    Spring——IOC(控制反转)与DI(依赖注入).docx

    IOC与DI的理解及使用 控制反转IOC(Inversion of Control)是一种设计思想,DI(依赖注入)是实现IOC的一种方法 。... 在Spring中实现控制反转的是IOC容器 ,其 实现方法是依赖注入 (Dependency Injection,DI)

    Spring框架控制反转IOC和依赖注入DI详解

    本文介绍了Spring框架中的控制反转IOC和依赖注入DI,欢迎阅读,共同学习,一起进步。 Spring框架基础参考:深入学习Spring基础 文章目录一.入门程序和IOC简介二.IOC-控制反转三.DI-依赖注入四. IOC和DI五.Spring...

    IOC控制反转&DI依赖注入

    该项目实现了简单的IOC技术思想和DI依赖注入

    基于框架的Web开发-IoC(控制反转)和DI(依赖注入)入门.doc

    1.2 IoC(控制反转)和DI(依赖注入)入门 1 传统的Java类 在工程下创建包ioc,在ioc包中创建类Test。(为了看起来清楚,将三个类写在了同一个Java文件中,其中唯一的public类为Test)。类的含义和关系如下: Car类...

    springioc和spring aop

    其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体,将其所依赖的对象的...

    控制反转(IoC)与依赖注入(DI)1

    1. 软件系统在没有引IOC容器之前,如图1所示,对象A依赖于对象B,那么对象A在初始化或者 2. 软件系统在引IOC容器之后,这种情形就完全改变了,如图2所示

    我的Pro Spring 学习笔记 之二 控制反转(IoC)和依赖注入(DI), Spring初步

    源代码 博文链接:https://danielkwo.iteye.com/blog/40945

    Spring_01_入门篇_依赖注入(控制反转)_XML

    此文档仅供初学者学习,包括Spring的依赖注入(控制反转)的详细实例。以三层贯穿实例(持久层、业务层、控制层),由MAIN方法直接调用测试用例。

    Spring中依赖注入与容器

    依赖注入、IoC/DI Spring 框架(核心)IoC 容器 IoC:控制反转  DI:依赖注入  什么是依赖?一个组件(对象)的运行需要用到另一个组件(对象),称这种关系为依赖关系  举例:鱼依赖水,生命依赖空气、阳光、水...

    SSM框架的学习与应用-Java EE企业级应用开发学习记录-(第六天)初识Spring框架

    Spring框架简介:对Spring框架的基本概念进行介绍,包括依赖注入(DI)和面向切面编程(AOP)等核心特性,以及Spring的优点和在Java EE开发中的作用。 Spring IoC的控制反转实例:通过一个示例演示了使用Spring的...

    spring培训-笔记

    控制反转(IoC)/依赖注入(DI) 11 什么是控制反转/依赖注入? 11 依赖注入的三种实现形式 12 BeanFactory 14 BeanFactory管理Bean(组件)的生命周期 15 Bean的定义 16 Bean的之前初始化 19 Bean的准备就绪...

    Spring教程  主要内容:介绍Spring的历史,Spring的概论和它的体系结构,重点阐述它在J2EE中扮演的角色。

    控制反转(IoC)/依赖注入(DI) 11 什么是控制反转/依赖注入? 11 依赖注入的三种实现形式 12 BeanFactory 14 BeanFactory管理Bean(组件)的生命周期 15 Bean的定义 16 Bean的之前初始化 19 Bean的准备就绪(Ready...

    Spring IOC的快速入门案例

    Spring IOC的快速入门案例 &gt;下载Spring的开发包 ...&gt;理解IOC控制反转和DI依赖注入 &gt;编写Spring核心配置文件 &gt;在程序中读取Spring配置文件,通过Spring框架获得Bean,完成相应操作 Spring 4.x的目录结构  

    第一个Spring程序(DI的实现).docx

    依赖注入:Dependency Injection(DI)与控制反转(IoC),不同角度但是同一个概念。首先我们理解一点在传统方式中我们使用new的方式来创建一个对象,这会造成对象与被实例化的对象之间的耦合性增加以致不利于维护...

    Spring IOC DI AOP 事务)

    目录IOC(控制反转)DI(依赖注入)AOP(面向切面编程)Spring事务事务传播特性脏读,不可重复读,幻读事务隔离级别不喜勿喷 如有雷同请联系本人!! IOC(控制反转) IOC是一种设计思想,而不是什么技术 传统方法...

    简单谈谈Spring Ioc原理解析

    学习过Spring框架的人一定都会听过Spring的IoC(控制反转) 、DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC 、DI这两个概念是模糊不清的,是很难理解的,今天和大家分享网上的一些技术大牛们对Spring...

    IOC之深入理解SpringIoC

    IoC全称为InversionofControl,翻译为“控制反转”,它还有一个别名为DI(DependencyInjection),即依赖注入。如何理解“控制反转”好呢?理解好它的关键在于我们需要回答如下四个问题:谁控制谁控制什么为何是反转...

Global site tag (gtag.js) - Google Analytics