一:IOC容器的定义

  控制反转(Inversion of Control,英文缩写为IoC)是一个重要的面向对象编程的法则来削减计算机程序的耦合问题,也是轻量级的Spring框架的核心。 控制反转一般分为两种类型,依赖注入(Dependency Injection,简称DI)和依赖查找。依赖注入应用比较广泛。

二:Ioc容器相关含义

    许多强大的功能都是由两个或是更多的类通过彼此的合作来实现业务逻辑,这使得每个对象和其他的对象产生依赖或者关联。(也就是对象持有其他对象的引用)。如果这个获取过程要靠自身实现,那么如你所见,这将导致代码高度耦合并且难以测试。
 
    工厂模式只是一定程度上降低了这种代码的耦合性,
    IoC模式可以彻底解决这种耦合,它把耦合从代码中移出去,放到统一的XML 文件中,通过一个容器在需要的时候把这个依赖关系形成,即把需要的接口实现注入到需要它的类中。这可能就是“依赖注入”说法的来源了。

    优点:因为把对象生成放在了XML里定义,所以当我们需要换一个实现子类将会变成很简单,只要修改XML就可以了,这样我们甚至可以实现对象的热插拨(象USB)

   缺点:1.创建对象的过程变得复杂,对于不习惯这种方式的人,会觉得有些别扭和不直观。
               2.对象生成因为是使用反射编程,在效率上有些损耗。但相对于IoC提高的维护性和灵活性来说,这点损耗是微不足道的,除非某对象的生成对效率要求特别高

三:IOC容器实现原理

----->ioc容器实现原理项目图

  

----->beans.xml对应的java类

【1】一个xml节点在可以映射成一个java类。

beans根节点对应的java类

 package org.shangxiaofei.bjsxt.shang;
import java.util.ArrayList;
import java.util.List; import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
/**
* Beans.xml中相当于根节点对应的java对象
* @ClassName: Bean
* @Description: TODO(这里用一句话描述这个类的作用)
* @author 尚晓飞
* @date 2014-8-27 下午4:55:19
*
*/
@XmlRootElement
public class Beans {
//根节点下多有bean对象的集合
private List<Bean> list=new ArrayList<Bean>(); public Beans() {
super();
} //name定义的是beans.xml中节点的名字
@XmlElement(name="bean")
public List<Bean> getList() {
return list;
} public void setList(List<Bean> list) {
this.list = list;
} }

bean节点对应的java类

 package org.shangxiaofei.bjsxt.shang;

 import java.util.ArrayList;
import java.util.List; import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement; /**
* 相当于beans.xml中<beans></beans>根节点下每一个<bean id="" className=""></bean>节点对应的java对象
* @ClassName: Bean
* @Description: TODO(这里用一句话描述这个类的作用)
* @author 尚晓飞
* @date 2014-8-27 下午5:00:58
*
*/
public class Bean {
//<bean></bean>节点中的属性
private String id; //<bean></bean>节点中的属性
private String className; //<bean></bean>节点下的<property></property>节点对应java对象的集合
private List<Property> list=new ArrayList<Property>();
public Bean() {
super();
} //<bean></bean>节点中的属性
@XmlAttribute
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
} //<bean></bean>节点中的属性
@XmlAttribute
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
} //<bean></bean>节点下的<property></property>节点集合
@XmlElement(name="property")
public List<Property> getList() {
return list;
}
public void setList(List<Property> list) {
this.list = list;
} }

property节点对应的java类

 package org.shangxiaofei.bjsxt.shang;

 import javax.xml.bind.annotation.XmlAttribute;

 /**
* <beans>节点下<bean>节点中<property>节点在java中对应的对象
* @ClassName: Property
* @Description: TODO(这里用一句话描述这个类的作用)
* @author 尚晓飞
* @date 2014-8-27 下午5:11:43
*
*/
public class Property {
//<property>节点中的属性
private String name; //<property>节点中的属性
private String require;
public Property() {
super();
} //<property>节点的属性
@XmlAttribute
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
} //<property>节点的属性
@XmlAttribute
public String getRequire() {
return require;
}
public void setRequire(String require) {
this.require = require;
} }

【2】beans.xml的配置内容

 <?xml version="1.0" encoding="UTF-8"?>
<beans> <bean id="MyAction" className="com.bjsxt.shang.action.MyAction">
<property name="studentService" require="StudentService"></property>
<property name="teacherService" require="TeacherService"></property>
</bean> <bean id="StudentService" className="com.bjsxt.shang.service.impl.StudentServiceImp"></bean>
<bean id="TeacherService" className="com.bjsxt.shang.service.impl.TeacherServiceImp"></bean> </beans>

【3】BeansFactory工厂类解析beans.xml来实现对象的生成和关系的建立

BeansFactory工厂类

 package com.bjsxt.shang.util;

 import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map; import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller; import org.shangxiaofei.bjsxt.shang.Bean;
import org.shangxiaofei.bjsxt.shang.Beans;
import org.shangxiaofei.bjsxt.shang.Property; import com.bjsxt.shang.action.MyAction;
/**
* 此类是解析bens.xml文件,在解析过程中生成项目中配置好的类的对象,并根据配置的关系,建立项目中类与类之间的关联关系
*
* 面向接口编程,就是降低了代码的耦合度。
*
* 我们只要修改配置中接口对应的实现类,我们就可以改变功能。
* @ClassName: BeansFactory
* @Description: TODO(这里用一句话描述这个类的作用)
* @author 尚晓飞
* @date 2014-8-28 上午11:12:25
*
*/
public class BeansFactory {
//创建一个容器,用来存放xml解析过来的所有对象
private Map<String, Object> contaniner=new HashMap<String, Object>(); //利用空构造器。来解析xml,并将解析过来的对象存放入容器中
public BeansFactory() throws JAXBException, ClassNotFoundException, InstantiationException, IllegalAccessException, SecurityException, NoSuchFieldException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException{
//解析xml jaxb
JAXBContext context=JAXBContext.newInstance(Beans.class); //context.createMarshaller() 编码 java-->XmlAccessOrder
//context.createUnmarshaller() 解码 xml-->java Unmarshaller unmarshaller=context.createUnmarshaller(); Beans beans=(Beans) unmarshaller.unmarshal(BeansFactory.class.getClassLoader().getResourceAsStream("beans.xml")); //获取bens.xml中所有bean节点转换成的java对象
List<Bean> listBean=beans.getList(); //将beans.xml中所有配置好的程序需要用的java对象生成,并将生成的对象存放入容器中,对应的key-value 为id-object
for (Iterator iterator = listBean.iterator(); iterator.hasNext();) {
Bean bean = (Bean) iterator.next(); //获取bean对象中的属性值 配置的id和id对应的类名
String id=bean.getId();
String className=bean.getClassName(); //利用反射生成配置类名的对象
Class cls=Class.forName(className);
Object obj=cls.newInstance(); //将每个类的对象存放到容器中
this.contaniner.put(id, obj);
} //根据bean节点的下的配置,将java的对象与对象之间的关系建立起来,依赖注入set注入
for (Iterator iterator = listBean.iterator(); iterator.hasNext();) {
Bean bean = (Bean) iterator.next(); //获取当前bean节点下的property节点的集合
List<Property> listProperty=bean.getList();
//迭代当前bean下的property节点集合
for (Iterator iterator2 = listProperty.iterator(); iterator2.hasNext();) {
Property property = (Property) iterator2.next();
//获取bean对象需要进行关联的属性名和对象引用的id
String name=property.getName();
String require=property.getRequire(); //获取当前的bean对象
Object obj1=contaniner.get(bean.getId());//当前宿主对象
Object obj2=contaniner.get(require);//当前从属对象 //拼接set方法的方法名
String methodName="set"+name.substring(0,1).toUpperCase()+name.substring(1);
//获取set方法的参数类型
Field field=obj1.getClass().getDeclaredField(name);
//获取属性的类型
field.getType(); //获取set方法
Method method=obj1.getClass().getMethod(methodName, field.getType()); //执行set方法,将需要关联的对象进行set注入 执行obj对象的set放入,注入obj2
method.invoke(obj1, obj2); } } } public Map<String, Object> getContaniner() {
return contaniner;
} public void setContaniner(Map<String, Object> contaniner) {
this.contaniner = contaniner;
} //测试方法
public static void main(String[] args) throws SecurityException, IllegalArgumentException, JAXBException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException, InvocationTargetException, NoSuchMethodException { /**
* myAction类中引用了两个接口的引用。添加setget方法
*
* 两个接口各自有一个实现类。
*
*/
BeansFactory beansFactory=new BeansFactory();
Map<String, Object> contaninerMap=beansFactory.getContaniner();
MyAction myAction=(MyAction) contaninerMap.get("MyAction");
myAction.add(); //打印结果,是实现类中的方法中的打印语句:
//我需要添加一个学生在数据库
//我需要添加一个老师在数据库中
}
}

【4】MyAction类,此处省略了接口,和接口实现类的代码(在接口中定义一个方法,实现类实现,并在方法中打印一句话)

MyAction类

package com.bjsxt.shang.action;

import com.bjsxt.shang.service.StudentService;
import com.bjsxt.shang.service.TeacherService; public class MyAction {
private StudentService studentService;
private TeacherService teacherService; /**
* 一个测试方法
* @Title: add
* @Description: TODO(这里用一句话描述这个方法的作用)
* @return
* @return String 返回类型
* @author 尚晓飞
* @date 2014-8-27 下午5:29:33
*/
public String add(){
studentService.addStudent();
teacherService.addTeacher();
return null;
} public StudentService getStudentService() {
return studentService;
} public void setStudentService(StudentService studentService) {
this.studentService = studentService;
} public TeacherService getTeacherService() {
return teacherService;
} public void setTeacherService(TeacherService teacherService) {
this.teacherService = teacherService;
} }

     

重新学习Spring之核心IOC容器的底层原理的更多相关文章

  1. IoC容器(底层原理)

    IoC(概念和原理) 1,什么是IoC (1)控制反转,把对象创建和对象之间的调用过程,交给Spring进行管理 (2)使用IoC目的:为了降低耦合度 (3)做入门案例就是IoC实现 2,IoC底层原 ...

  2. 转 Spring源码剖析——核心IOC容器原理

    Spring源码剖析——核心IOC容器原理 2016年08月05日 15:06:16 阅读数:8312 标签: spring源码ioc编程bean 更多 个人分类: Java https://blog ...

  3. 学习Spring5必知必会(3)~Spring的核心 IoC 和 DI

    一.Spring的核心 IoC(基于XML) 1.IoC容器 (1)BeanFactory容器创建对象: //使用BeanFactory @Test void testBeanFactory() th ...

  4. Spring之一:IoC容器体系结构

    温故而知心. Spring IoC概述 常说spring的控制反转(依赖反转),看看维基百科的解释: 如果合作对象的引用或依赖关系的管理要由具体对象来完成,会导致代码的高度耦合和可测试性降低,这对复杂 ...

  5. 比Spring简单的IoC容器

    比Spring简单的IoC容器 Spring 虽然比起EJB轻量了许多,但是因为它需要兼容许多不同的类库,导致现在Spring还是相当的庞大的,动不动就上40MB的jar包, 而且想要理解Spring ...

  6. 使用Spring.NET的IoC容器

    使用Spring.NET的IoC容器 0. 辅助类库 using System; using System.Collections.Generic; using System.Linq; using ...

  7. Spring.NET的IoC容器(The IoC container)——简介(Introduction)

    简介 这个章节介绍了Spring Framework的控制反转(Inversion of Control ,IoC)的实现原理. Spring.Core 程序集是Spring.NET的 IoC 容器实 ...

  8. Spring框架中IoC(控制反转)的原理(转)

    原文链接:Spring框架中IoC(控制反转)的原理 一.IoC的基础知识以及原理: 1.IoC理论的背景:在采用面向对象方法设计的软件系统中,底层实现都是由N个对象组成的,所有的对象通过彼此的合作, ...

  9. git的核心命令使用和底层原理解析

    文章目录: GIT体系概述 GIT 核心命令使用 GIT 底层原理 一.GIT体系概述 GIT 与 svn 主要区别: 存储方式不一样 使用方式不一样 管理模式不一样 1.存储方式区别 GIT把内容按 ...

随机推荐

  1. MyBatis—mapper.xml映射配置

    SQL文件映射(mapper文件),几个顶级元素的配置: mapper元素:根节点只有一个属性namespace(命名空间)作用: 1:用于区分不同的mapper,全局唯一. 2:绑定DAO接口,即面 ...

  2. python安装mysql-python1.2.5

    首先安装好python 然后安装C++ Microsoft Visual C++ Compiler for Python 2.7 下载后双击安装 登录https://pypi.python.org/p ...

  3. 常用php操作redis命令整理(三)LIST类型

    LIST 头元素和尾元素:头元素指的是列表左端/前端第一个元素,尾元素指的是列表右端/后端第一个元素.举个例子,列表list包含三个元素:x, y, z,其中x是头元素,而z则是尾元素.空列表:指不包 ...

  4. GOEXIF读取和写入EXIF信息

    最新版本的gexif,直接基于gdi+实现了exif信息的读取和写入,代码更清晰. /* * File: gexif.h * Purpose: cpp EXIF reader * 3/2/2017 & ...

  5. 《Java程序设计》第三章-基础语法

    20145221<Java程序设计>第三章-基础语法 总结 教材学习内容总结 类型.变量与运算符 类型 Java可区分为基本类型(Primitive Type)和类类型(Class Typ ...

  6. MAC、MII、PHY的关系与区别

    嗯,实验室的嵌入式项目需要写设备驱动,我分到了网络驱动的活,写一个适配SylixOS的(这里夸一句,这个真是国内相当不错的嵌入式实时操作系统了)MPC8377的网卡驱动,说实话原来从来没接触过写驱动的 ...

  7. ubuntu18.04 install pip

    1. environment release version: bionic kernel version:4.15.0-29-generic 2.install pip 2.1 sudo apt-g ...

  8. OpenDayLight Helium实验三 OpenDaylight二层转发机制实验

    本文基于OpenDaylight二层转发机制实验 而成 在SDN网络中,处于末端的主机并不知道其连接的网络是SDN,某台主机要发送数据包到另一台主机,仍然需要进行IP到MAC地址的ARP解析.SDN网 ...

  9. 【异常记录(七)】MVC:从客户端中检测到有潜在危险的 Request.Form 值 的解决方法 [转]

    从客户端(Content="<EM ><STRONG ><U >这是测试这...")中检测到有潜在危险的Request.Form 值. 说明:  ...

  10. Qt532__std::numeric_limits<qint64>::min();

    1.C:\Qt\Qt5.3.2_vs10_opengl\5.3\msvc2010_opengl\include\QtCore\qdatetime.h static inline qint64 null ...