定义:

在运行期,由外部容器动态的将依赖对象动态地注入到组件中。

两种方式:

手工装配

-set方式

-构造器

-注解方式

自动装配(不推荐)

1利用构造器

2set方法注入

dao:

package dao;

public interface PersonDao {
public void add();
}

daoimpl:

package dao.impl;

import dao.PersonDao;

public class PersonDaoBean implements PersonDao{

	@Override
public void add() {
System.out.println("I am person dao");
} }

service:

package service;

public interface PersonService {

	public void save();

}

serviceimpl(set实现依赖注入):

package service.impl;

import dao.PersonDao;
import service.PersonService; public class PersonServiceBean implements PersonService { private PersonDao personDao; public PersonDao getPersonDao() {
return personDao;
} public void setPersonDao(PersonDao personDao) {
this.personDao = personDao;
} public void save(){
personDao.add();
} }

applicationContext.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-3.1.xsd"> <bean id = "personDao" class = "dao.impl.PersonDaoBean"></bean> <!-- 默认构造方法 -->
<bean id = "personService" class = "service.impl.PersonServiceBean">
<property name = "personDao" ref = "personDao">
</property>
</bean> </beans>

这样一来,dao方法会直接被spring注入到service里。运行service的save方法可以调用dao的save方法。 

 

 除了注入bean还可以注入基本属性类型,以及各种集合类。

编码剖析:

bean定义类:

package test;

import java.util.ArrayList;
import java.util.List; public class BeanDefinition {
private String id;
private String className;
private List<PropertyDefinition> propertys = new ArrayList<PropertyDefinition>(); public BeanDefinition(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;
}
public List<PropertyDefinition> getPropertys() {
return propertys;
}
public void setPropertys(List<PropertyDefinition> propertys) {
this.propertys = propertys;
} }

property定义类:

package test;

public class PropertyDefinition {
private String name;
private String ref;
private String value; public String getValue() {
return value;
} public void setValue(String value) {
this.value = value;
} public PropertyDefinition(String name, String ref, String value) {
this.name = name;
this.ref = ref;
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;
} }

自制spring容器

package 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; public class MyClassPathXMLApplicationContext {
private List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>();
private Map<String, Object> sigletons = new HashMap<String, Object>(); public MyClassPathXMLApplicationContext(String filename){
this.readXML(filename);
this.instanceBeans();
this.injectObject();
} /**
* 为bean对象的属性注入值
*/
private void injectObject() {
for(BeanDefinition beanDefinition : beanDefines){
Object bean = sigletons.get(beanDefinition.getId());
if(bean!=null){
try {
PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
for(PropertyDefinition propertyDefinition : beanDefinition.getPropertys()){
for(PropertyDescriptor properdesc : ps){
if(propertyDefinition.getName().equals(properdesc.getName())){
Method setter = properdesc.getWriteMethod();//获取属性的setter方法 ,private
if(setter!=null){
Object value = null;
if(propertyDefinition.getRef()!=null && !"".equals(propertyDefinition.getRef().trim())){
value = sigletons.get(propertyDefinition.getRef());
}else{
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");
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);
}
}

 

  

Spring 依赖注入控制反转实现,及编码解析(自制容器)的更多相关文章

  1. Helloworld之Spring依赖注入/控制反转(DI/IoC)版

    Helloworld之Spring依赖注入/控制反转(DI/IoC)版 作者:雨水, 日期:2014-10-29 摘要:本文主要用于培训刚開始学习的人理解Spring中的依赖注入的基本概念. 先介绍依 ...

  2. C#依赖注入控制反转IOC实现详解

    原文:C#依赖注入控制反转IOC实现详解 IOC的基本概念是:不创建对象,但是描述创建它们的方式.在代码中不直接与对象和服务连接,但在配置文件中描述哪一个组件需要哪一项服务.容器负责将这些联系在一起. ...

  3. PHP关于依赖注入(控制反转)的解释和例子说明

    PHP关于依赖注入(控制反转)的解释和例子说明 发表于2年前(2014-03-20 10:12)   阅读(726) | 评论(1) 8人收藏此文章, 我要收藏 赞2 阿里云双11绽放在即 1111 ...

  4. spring依赖注入(反转控制)

    SPRING依赖注入机制(反转控制)解析 Spring能有效地组织J2EE应用各层的对象.不管是控制层的Action对象,还是业务层的 Service对象,还是持久层的DAO对象,都可在Spring的 ...

  5. laravel5.2总结--服务容器(依赖注入,控制反转)

    1.依赖 我们定义两个类:class Supperman 和 class Power,现在我们要使用Supperman ,而Supperman 依赖了Power class Supperman { p ...

  6. Spring进阶之路(1)-Spring核心机制:依赖注入/控制反转

    原文地址:http://blog.csdn.net/wangyang1354/article/details/50757098 我们经常会遇到这样一种情景,就是在我们开发项目的时候经常会在一个类中调用 ...

  7. Benefits of Using the Spring Framework Dependency Injection 依赖注入 控制反转

    小结: 1. Dependency Injection is merely one concrete example of Inversion of Control. 依赖注入是仅仅是控制反转的一个具 ...

  8. 依赖注入&控制反转

    IoC——Inversion of Control  控制反转DI——Dependency Injection   依赖注入 要想理解上面两个概念,就必须搞清楚如下的问题: 参与者都有谁? 依赖:谁依 ...

  9. MVC 依赖注入/控制反转

    http://www.cnblogs.com/cnmaxu/archive/2010/10/12/1848735.html http://www.cnblogs.com/artech/archive/ ...

随机推荐

  1. debian vi

    这次用DigitalOcean VPS发现vi的方向键变成字母,没办法正常使用,搜索了下找到了解决办法. 1 vi /etc/vim/vimrc.tiny 找到set compatible改为set ...

  2. E. Santa Claus and Tangerines 二分答案 + 记忆化搜索

    http://codeforces.com/contest/752/problem/E 首先有一个东西就是,如果我要检测5,那么14我们认为它能产生2个5. 14 = 7 + 7.但是按照平均分的话, ...

  3. DrawerLayout学习,抽屉效果

    第一节: 注意事项 *主视图一定要是DrawerLayout的第一子视图 *主视图宽度和高度匹配父视图,因为当你显示主视图时,要铺满整个屏幕,用户体验度较高 *必须显示指定的抽屉视图的android: ...

  4. java io学习之File类

    1.先看下四个静态变量 static String pathSeparator The system-dependent path-separator character, represented a ...

  5. python学习笔记-socket

    socket socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. sock ...

  6. DB2不记录事务日志

    1. DB2大数据处理不记录事务日志步骤:  建表需要添加属性“NOT LOGGED INITIALLY”  在大批量更改操作的同一个事务开始时执行:“ALTER TABLE tabname ACTI ...

  7. github 项目版本控制

    1.申请github账号 2.安装github for windows工具 安装后就可以使用Git Bash打开特制的终端,在里面用来命令行了.喜欢Git命令行方式的朋友到这里就够了. 打开Git B ...

  8. sam9x5 sam-ba

     调试参考 http://www.docin.com/p-872951702.html AT91SAM9x5 EK Board SoC Features Kit Information Kit Ove ...

  9. ASP.NET访问网络映射盘&实现文件上传读取功能

    最近在改Web的时候,遇到一个问题,要跨机器访问共享文件夹,以实现文件正常上传下载功能. 要实现该功能,可以采用HTTP的方式,也可以使用网络映射磁盘的方式,今天主要给大家分享一下使用网络映射磁盘的方 ...

  10. MSSERVER创建链接服务器

    exec sp_addlinkedserver 'DB_RASS','','SQLOLEDB','127.0.0.1' ' exec sp_serveroption 'DB_RASS','rpc ou ...