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

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....谢谢分享。。。

相关推荐

    springIOC控制反转 依赖注入实例

    Spring IOC(Inversion of Control,控制反转)是Spring框架的核心特性,它改变了传统Java应用程序中对象的创建和管理方式。在传统的程序设计中,我们通常手动创建对象并管理它们之间的依赖关系,而在Spring中,这些...

    Spring IOC 控制反转

    ### Spring IOC控制反转详解 #### 一、Spring框架简介 Spring框架是一个开源的Java平台,提供了全面的基础架构支持,让开发者能够轻松地开发出松耦合的应用程序。它通过依赖注入(Dependency Injection, DI)和...

    Spring 控制反转 依赖注入

    **Spring 框架中的控制反转 (IoC) 和依赖注入 (DI)** 在软件开发中,控制反转(Inversion of Control,简称IoC)是一种设计原则,它将对象的创建和管理权从代码中剥离出来,转交给一个外部容器(如Spring框架)。...

    Spring Ioc 注解 依赖注入

    其中,IoC和依赖注入(Dependency Injection, DI)是Spring框架最核心的部分之一。 #### 二、IoC容器概述 在传统的Java应用程序中,对象的创建和管理通常由程序员来完成。这种方式会导致代码之间存在高度耦合,难以...

    spring 控制反转和依赖注入.docx

    Spring 框架的核心是控制反转(IOC)和依赖注入(DI),它可以将对象的创建和依赖关系管理,实现高内聚、低耦合的开发模式。 下面是 Spring 框架的核心知识点: 1. 控制反转(IOC):控制反转是 Spring 框架的...

    helloIoc.zip spring ioc控制反转简单测试代码

    Spring框架的核心特性之一就是依赖注入(Dependency Injection,简称DI),它通过控制反转(Inversion of Control,简称IOC)实现。这个"helloIoc.zip"压缩包包含的是一组用于演示Spring IOC基本概念和使用的测试...

    IOC控制反转&DI依赖注入

    在软件开发领域,IOC(Inversion of Control,控制反转)和DI(Dependency Injection,依赖注入)是两种重要的设计模式,特别是在Java和Spring框架中被广泛使用。这些概念有助于提高代码的可测试性、可维护性和模块...

    Spring Ioc(依赖注入)入门例子--属性注入

    Spring的核心特性之一就是它的Inversion of Control(IoC,控制反转)容器,也被称为Dependency Injection(DI,依赖注入)。这个概念是Spring框架使应用程序组件之间解耦的关键。让我们深入探讨一下Spring的IoC和...

    Spring IOC控制反转 1

    **Spring IOC控制反转详解** 在Java开发中,Spring框架的核心特性之一就是IOC(Inversion of Control,控制反转),它改变了传统程序设计中的对象依赖管理方式,使得开发者可以更专注于业务逻辑,而不是对象的创建...

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

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

    springIoc实现原理

    总之,Spring Ioc通过控制反转和依赖注入,极大地提高了代码的可维护性和可测试性,降低了系统的复杂度,使得开发人员能够更加专注于业务逻辑的实现。在实际开发中,理解并熟练运用Spring Ioc,对于提升开发效率和...

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

    Spring框架中的IOC(控制反转)和DI(依赖注入)是两种关键的设计模式,它们极大地提升了软件的可维护性和可扩展性。控制反转是一种设计思想,它改变了传统的对象创建方式,将对象的创建和管理权从应用程序自身转移...

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

    在本文中,我们将深入探讨Spring框架的核心概念——控制反转(Inversion of Control,IoC)和依赖注入(Dependency Injection,DI)。这些概念是Spring框架的基础,对于理解和掌握Spring的使用至关重要。 首先,让...

    spring IOC容器依赖注入XML配置

    Spring框架是Java开发中不可或缺的一部分,它以IoC(Inversion of Control,控制反转)和DI(Dependency Injection,依赖注入)为核心,极大地简化了应用程序的复杂性。在本教程中,我们将深入探讨如何通过XML配置在...

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

    【控制反转(IoC)与依赖注入(DI)详解】 控制反转(Inversion of Control,简称IoC)是面向对象编程领域的一种设计原则,旨在降低软件组件间的耦合度。在传统的程序设计中,对象A如果依赖于对象B,那么对象A在...

    自定义spring控制反转(依赖注入)

    在Spring框架中,控制反转(IoC,Inversion of Control)和依赖注入(DI,Dependency Injection)是核心设计理念,它们极大地简化了Java应用的开发和维护。本文将深入探讨如何自定义Spring实现读取`...

    Spring中使用Ioc控制反转

    ### Spring框架中的IoC控制反转详解 #### 一、IoC概述 控制反转(Inversion of Control,简称IoC)是一种设计思想,在Spring框架中,它主要用来解决对象依赖问题。传统的面向对象编程中,对象之间的依赖关系由对象...

    Springioc注入Demo

    Spring IOC(Inversion of Control,控制反转)是Spring框架的核心特性,它将对象的创建和管理权交由Spring容器来负责,从而实现了依赖倒置,增强了代码的可测试性和可维护性。DI(Dependency Injection,依赖注入)...

    自己实现的Spring反转控制和依赖注入

    Spring框架是Java开发中广泛应用的一个开源框架,以其优秀的反转控制(Inversion of Control,IoC)和依赖注入(Dependency Injection,DI)理念为核心,极大地简化了企业级应用的开发工作。下面将详细介绍这两个...

    spring dom4j 解析 依赖DI注入 ioc 反转 反射原理

    在IT行业中,Spring框架是Java开发中的核心工具,它提供了许多功能,如依赖注入(DI)、面向切面编程(AOP)以及IoC(控制反转)。在这个话题中,我们将深入探讨Spring框架如何利用DOM4J解析XML配置文件,依赖注入...

Global site tag (gtag.js) - Google Analytics