- 浏览: 958500 次
- 性别:
- 来自: 魔都
文章分类
- 全部博客 (745)
- MultiThread (19)
- My Plan (118)
- JavaBasic (61)
- MyInterview (104)
- InternetTechnique (5)
- ProjectConclusion (1)
- Maven (5)
- MogoDb (5)
- Hadoop (11)
- Memcached (6)
- TechniqueCollect (1)
- Ibaits (1)
- Android (34)
- ItLife (40)
- Tree (2)
- ProjectArchitect (7)
- Open Source (3)
- liunx (5)
- socket (8)
- Spring (27)
- DesginPattern (35)
- WebBasic (13)
- English (13)
- structs (1)
- structs2 (2)
- Oracle (17)
- Hibernate (2)
- JavaScript (4)
- Jdbc (1)
- Jvm (15)
- Ibatis (1)
- DataStructures (13)
- Https/Socket/Tcp/Ip (3)
- Linux (4)
- Webservice (7)
- Io (2)
- Svn (1)
- Css (1)
- Ajax (1)
- ExtJs (1)
- UML (2)
- DataBase (6)
- BankTechnique (3)
- SpringMvc (3)
- Nio (3)
- Load Balancing/Cluster (3)
- Tools (1)
- javaPerformanceOptimization (8)
- Lucene(SEO) (1)
- My Think (80)
- NodeJs (1)
- Quartz (1)
- Distributed-java (1)
- MySql (7)
- Project (4)
- junit (4)
- framework (1)
- enCache (1)
- git (2)
- SCJP (1)
- sd (1)
最新评论
-
lkjxshi:
你都这水平了还考这个证干嘛
SCJP 认证考试指南 -
钟逸华:
问的真多
百度java开发面试题(转) -
zuimeitulip:
觉得我就是这样的,从小阅读量就很少,导致现在的读的速度非常慢, ...
让读书成为一种习惯 -
DDT_123456:
我觉得你是不符合要求。问你hashmap的那个问题,你那样回答 ...
阿里面试2(转) -
jingjing0907:
刚刚写了很多读过此博客的感受,竟然没有发上去,以为我注册账号还 ...
让读书成为一种习惯
文章链接:http://stamen.iteye.com/blog/1489223
http://www.iteye.com/topic/86339
http://www.iteye.com/topic/1113459
引述:IoC(控制反转:Inverse of Control)是Spring容器的内核,AOP、声明式事务等功能在此基础上开花结果。但是IoC这个重要的概念却比较晦涩隐讳,不容易让人望文生义,这不能不说是一大遗憾。不过IoC确实包括很多内涵,它涉及代码解耦、设计模式、代码优化等问题的考量,我们打算通过一个小例子来说明这个概念。
通过实例理解IoC的概念
贺岁大片在中国已经形成了一个传统,每到年底总有多部贺岁大片纷至沓来让人应接不暇。在所有贺岁大片中,张之亮的《墨攻》算是比较出彩的一部。该片讲述了战国时期墨家人革离帮助梁国反抗赵国侵略的个人英雄主义故事,恢宏壮阔、浑雄凝重的历史场面相当震撼。其中有一个场景:当刘德华所饰演的墨者革离到达梁国都城下,城上梁国守军问到:“来者何人?”刘德华回答:“墨者革离!”我们不妨通过一个Java类为这个“城门叩问”的场景进行编剧,并借此理解IoC的概念:
代码清单3-1 MoAttack:通过演员安排剧本
- public class MoAttack {
- public void cityGateAsk(){
- //①演员直接侵入剧本
- LiuDeHua ldh = new LiuDeHua();
- ldh.responseAsk("墨者革离!");
- }
- }
我们会发现以上剧本在①处,作为具体角色饰演者的刘德华直接侵入到剧本中,使剧本和演员直接耦合在一起(图3-1)。
一个明智的编剧在剧情创作时应围绕故事的角色进行,而不应考虑角色的具体饰演者,这样才可能在剧本投拍时自由地遴选任何适合的演员,而非绑定在刘德华一人身上。通过以上的分析,我们知道需要为该剧本主人公革离定义一个接口:
代码清单3-2 MoAttack:引入剧本角色
- public class MoAttack {
- public void cityGateAsk()
- {
- //①引入革离角色接口
- GeLi geli = new LiuDeHua();
- //②通过接口开展剧情
- geli.responseAsk("墨者革离!");
- }
- }
在①处引入了剧本的角色——革离,剧本的情节通过角色展开,在拍摄时角色由演员饰演,如②处所示。因此墨攻、革离、刘德华三者的类图关系如图 3 2所示:
可是,从图3 2中,我们可以看出MoAttack同时依赖于GeLi接口和LiuDeHua类,并没有达到我们所期望的剧本仅依赖于角色的目的。但是角色最终必须通过具体的演员才能完成拍摄,如何让LiuDeHua和剧本无关而又能完成GeLi的具体动作呢?当然是在影片投拍时,导演将LiuDeHua安排在GeLi的角色上,导演将剧本、角色、饰演者装配起来(图3-3)。
通过引入导演,使剧本和具体饰演者解耦了。对应到软件中,导演像是一个装配器,安排演员表演具体的角色。
现在我们可以反过来讲解IoC的概念了。IoC(Inverse of Control)的字面意思是控制反转,它包括两个内容:
- 其一是控制
- 其二是反转
那到底是什么东西的“控制”被“反转”了呢?对应到前面的例子,“控制”是指选择GeLi角色扮演者的控制权;“反转”是指这种控制权从《墨攻》剧本中移除,转交到导演的手中。对于软件来说,即是某一接口具体实现类的选择控制权从调用类中移除,转交给第三方决定。
因为IoC确实不够开门见山,因此业界曾进行了广泛的讨论,最终软件界的泰斗级人物Martin Fowler提出了DI(依赖注入:Dependency Injection)的概念用以代替IoC,即让调用类对某一接口实现类的依赖关系由第三方(容器或协作类)注入,以移除调用类对某一接口实现类的依赖。“依赖注入”这个名词显然比“控制反转”直接明了、易于理解。
IoC的类型
从注入方法上看,主要可以划分为三种类型:构造函数注入、属性注入和接口注入。Spring支持构造函数注入和属性注入。下面我们继续使用以上的例子说明这三种注入方法的区别。
构造函数注入
在构造函数注入中,我们通过调用类的构造函数,将接口实现类通过构造函数变量传入,如代码清单3-3所示:
代码清单3-3 MoAttack:通过构造函数注入革离扮演者
- public class MoAttack {
- private GeLi geli;
- //①注入革离的具体扮演者
- public MoAttack(GeLi geli){
- this.geli = geli;
- }
- public void cityGateAsk(){
- geli.responseAsk("墨者革离!");
- }
- }
MoAttack的构造函数不关心具体是谁扮演革离这个角色,只要在①处传入的扮演者按剧本要求完成相应的表演即可。角色的具体扮演者由导演来安排,如代码清单3-4所示:
代码清单3-4 Director:通过构造函数注入革离扮演者
- public class Director {
- public void direct(){
- //①指定角色的扮演者
- GeLi geli = new LiuDeHua();
- //②注入具体扮演者到剧本中
- MoAttack moAttack = new MoAttack(geli);
- moAttack.cityGateAsk();
- }
- }
在①处,导演安排刘德华饰演革离的角色,并在②处,将刘德华“注入”到墨攻的剧本中,然后开始“城门叩问”剧情的演出工作。
属性注入
有时,导演会发现,虽然革离是影片《墨攻》的第一主角,但并非每个场景都需要革离的出现,在这种情况下通过构造函数注入相当于每时每刻都在革离的饰演者在场,可见并不妥当,这时可以考虑使用属性注入。属性注入可以有选择地通过Setter方法完成调用类所需依赖的注入,更加灵活方便:
代码清单3-5 MoAttack:通过Setter方法注入革离扮演者
- public class MoAttack {
- private GeLi geli;
- //①属性注入方法
- public void setGeli(GeLi geli) {
- this.geli = geli;
- }
- public void cityGateAsk() {
- geli.responseAsk("墨者革离");
- }
- }
MoAttack在①处为geli属性提供一个Setter方法,以便让导演在需要时注入geli的具体扮演者。
代码清单3-6 Director:通过Setter方法注入革离扮演者
- public class Director {
- public void direct(){
- GeLi geli = new LiuDeHua();
- MoAttack moAttack = new MoAttack();
- //①调用属性Setter方法注入
- moAttack.setGeli(geli);
- moAttack.cityGateAsk();
- }
- }
和通过构造函数注入革离扮演者不同,在实例化MoAttack剧本时,并未指定任何扮演者,而是在实例化MoAttack后,在需要革离出场时,才调用其setGeli()方法注入扮演者。按照类似的方式,我们还可以分别为剧本中其他诸如梁王、巷淹中等角色提供注入的Setter方法,这样,导演就可以根据所拍剧段的不同,注入相应的角色了。
接口注入
将调用类所有依赖注入的方法抽取到一个接口中,调用类通过实现该接口提供相应的注入方法。为了采取接口注入的方式,必须先声明一个ActorArrangable接口:
然后,MoAttack实现ActorArrangable接口提供具体的实现:
代码清单3-7 MoAttack:通过接口方法注入革离扮演者
- public class MoAttack implements ActorArrangable {
- private GeLi geli;
- //①实现接口方法
- public void injectGeli (GeLi geli) {
- this.geli = geli;
- }
- public void cityGateAsk() {
- geli.responseAsk("墨者革离");
- }
- }
Director通过ActorArrangable的injectGeli()方法完成扮演者的注入工作。
代码清单3-8 Director:通过接口方法注入革离扮演者
- public class Director {
- public void direct(){
- GeLi geli = new LiuDeHua();
- MoAttack moAttack = new MoAttack();
- moAttack. injectGeli (geli);
- moAttack.cityGateAsk();
- }
- }
由于通过接口注入需要额外声明一个接口,增加了类的数目,而且它的效果和属性注入并无本质区别,因此我们不提倡采用这种方式。
通过容器完成依赖关系的注入
虽然MoAttack和LiuDeHua实现了解耦,MoAttack无须关注角色实现类的实例化工作,但这些工作在代码中依然存在,只是转移到Director类中而已。假设某一制片人想改变这一局面,在选择某个剧本后,希望通过一个“海选”或者第三中介机构来选择导演、演员,让他们各司其职,那剧本、导演、演员就都实现解耦了。
所谓媒体“海选”和第三方中介机构在程序领域即是一个第三方的容器,它帮助完成类的初始化与装配工作,让开发者从这些底层实现类的实例化、依赖关系装配等工作中脱离出来,专注于更有意义的业务逻辑开发工作。这无疑是一件令人向往的事情,Spring就是这样的一个容器,它通过配置文件或注解描述类和类之间的依赖关系,自动完成类的初始化和依赖注入的工作。下面是Spring配置文件的对以上实例进行配置的配置文件片断:
- <?xml version="1.0" encoding="UTF-8" ?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:p="http://www.springframework.org/schema/p"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
- <!--①实现类实例化-->
- <bean id="geli" class="LiuDeHua"/>
- <bean id="moAttack" class="com.baobaotao.ioc.MoAttack"
- p:geli-ref="geli"/><!--②通过geli-ref建立依赖关系-->
- </beans>
通过new XmlBeanFactory(“beans.xml”)等方式即可启动容器。在容器启动时,Spring根据配置文件的描述信息,自动实例化Bean并完成依赖关系的装配,从容器中即可返回准备就绪的Bean实例,后续可直接使用之。
Spring为什么会有这种“神奇”的力量,仅凭一个简单的配置文件,就能魔法般地实例化并装配好程序所用的Bean呢?这种“神奇”的力量归功于Java语言本身的类反射功能。
发表评论
-
spring原理
2013-07-31 23:21 8771、spring原理 s ... -
通过实例浅谈Spring运作机制
2013-07-31 23:06 1174看到这个标题大家可能又想:哎,又一个重新发明轮子的人。在这里 ... -
spring用到的设计模式
2013-06-24 21:45 1200spring源码也读了两遍了,但对于里面描述的关系还是不太 ... -
SPRING事务的属性有哪些?其中,事务隔离级别有哪几种?什么情况需要使用这几种事务隔离级别?
2013-04-14 20:45 3860Spring 声明式事务,propagation属性列表 PR ... -
Spring定时任务的几种实现
2013-01-24 10:32 1017Spring定时任务的几种实现 近日项目开发中需要执行一些 ... -
Spring多数据源解决方案
2012-10-02 22:49 1096... -
spring是如何管理 事务的
2012-07-08 14:43 1530Spring提供的事务管理可以分为两类:编程式的和声明式的。 ... -
【第六章】 AOP 之 6.9 代理机制 ——跟我学spring3
2012-07-07 12:36 875Spring AOP通过代理模式实现,目前支持两 ... -
【第九章】 Spring的事务 之 9.1 数据库事务概述 ——跟我学spring3
2012-07-07 12:37 9939.1 数据库事务概述 事 ... -
【第九章】 Spring的事务 之 9.2 事务管理器 ——跟我学spring3
2012-07-07 12:37 10079.2.1 概述 ... -
【第九章】 Spring的事务 之 9.3 编程式事务 ——跟我学spring3
2012-07-06 00:03 9169.3 编程式事务 9.3.1 编程式事务 ... -
【第九章】 Spring的事务 之 9.4 声明式事务 ——跟我学spring3
2012-07-06 00:03 7599.4 声明式事务 9.4.1 声明式事务 ... -
我对AOP的理解
2012-07-06 00:02 8891、问题 问题:想要添加日志记录 ... -
我对IoC/DI的理解
2012-07-06 00:01 1028IoC IoC: Inversion of ... -
基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别。
2012-07-06 00:02 2361基于JDK动态代理和CGLIB动态代理的实现S ... -
Spring对事务管理的支持的发展历程(基础篇)
2012-07-05 23:00 9821、问题 Java代 ... -
阅读spring源码
2012-07-05 21:22 1725读Spring源码之前,你要先清楚,为什么你要用S ... -
spring aop 详解
2012-07-01 18:41 1187文章链接:http://stamen.itey ... -
spring事务探索
2012-07-01 16:46 1007文章链接:http://www.iteye.com/topic ... -
spring aopframework实现
2012-06-18 09:51 1097package cn.itcast.day3.aopfr ...
相关推荐
**Spring Ioc 实现原理详解** Spring Ioc(Inversion of Control,控制反转)是Spring框架的核心特性之一,它改变了传统应用程序中对象的创建和管理方式。在传统的软件设计中,对象的创建和依赖关系的维护通常由...
SpringIOC Spring 框架是一个流行J2EE的开源产品,它提供了统一的应用架构方式、大量的中间层功能模块,大大简化了传统J2EE的开发模式。它的核心代码均来自于真实的项目,是由Spring 之父Rod Johnson 从商业项目开发...
### Spring_IOC详解:深入探索Spring框架的IOC容器原理 #### 引言 Spring框架作为Java企业级应用开发的基石,其核心组件之一便是IOC(Inverse of Control)容器。IOC容器负责管理应用程序中的对象及其依赖关系,...
### Spring IoC与注解依赖注入详解 #### 一、Spring框架简介 Spring框架是由Rod Johnson创建的一个开源项目,最初是为了解决企业级应用开发中的复杂性问题而诞生的。Spring框架的核心特性包括IoC(Inversion of ...
### Spring IOC控制反转详解 #### 一、Spring框架简介 Spring框架是一个开源的Java平台,提供了全面的基础架构支持,让开发者能够轻松地开发出松耦合的应用程序。它通过依赖注入(Dependency Injection, DI)和...
Spring IOC原理详解 Spring IOC(Inversion of Control,控制反转)是 Spring 框架的核心概念,它解决了对象之间的耦合问题,实现了松耦合编程。IOC 的思想是,Spring 容器来实现对象之间的创建、协调工作,而不是...
Spring 框架系列(7)- Spring IOC 实现原理详解之 IOC 初始化流程 本文将详细解释 Spring 框架中的 IOC(Inversion of Control,控制反转)实现原理之 IOC 初始化流程。IOC 是一种软件设计模式,用于将软件系统中...
Spring IOC 容器启动流程分析 Spring IOC 容器是 Java 企业级应用程序的核心组件之一,它提供了一个统一的依赖注入机制,使得应用程序的组件之间能够松耦合。Spring IOC 容器的启动流程是整个 Spring 框架的核心...
在“Java进阶之SpringIoC应用共18页.pdf”文档中,可能会涵盖以下几个关键知识点: 1. **Spring容器初始化**:Spring容器的启动和初始化过程,包括如何通过XML配置文件或Java配置类加载bean定义。 2. **Bean的生命...
### Spring IoC 搭建与配置详解 #### 一、Spring IoC 概述 Spring 是一个分层的 Java SE/EE 轻量级开源框架,它为 Java 应用提供了广泛的解决方案,覆盖了从表现层到业务逻辑层再到持久层。Spring 的核心优势之一...
Spring 框架的IoC(Inversion of Control,控制反转)实现原理是其核心特性之一,它使得组件之间的依赖关系不再由代码直接管理,而是交由容器负责。本篇文章将详细探讨Spring IoC的体系结构设计,以及如何实现这些...
**Spring的IOC原理详解** **一、IoC理论背景** 在面向对象的软件设计中,对象间的耦合是不可避免的,它们通过相互合作实现业务逻辑。这种耦合就像机械手表中的齿轮,彼此啮合共同完成任务。随着软件系统规模的扩大...
Spring 框架中的IoC(Inversion of Control,控制反转)是一种设计模式,它将对象的创建和管理权从代码本身转移到一个外部容器,即Spring的IoC容器。在这个例子中,我们将深入理解如何使用IoC并通过一个简单的`...
SpringIOC DI 循环依赖实例详解 SpringIOC 是一个基于依赖注入(Dependency Injection,简称 DI)的容器,用于管理 Bean 的生命周期。 DI 循环依赖是指在 Bean 初始化过程中出现的循环依赖问题,即一个 Bean 依赖于...
在 Spring 中,IOC(Inversion of Control,控制反转)和 DI(Dependency Injection,依赖注入)是两个核心概念,而 AOP(Aspect Oriented Programming,面向切面编程)则是实现模块化和解耦的重要工具。现在,我们...
### Spring IoC容器部署实现详解 #### 一、Spring IoC容器概述 Spring框架的核心特性之一就是Inversion of Control(IoC),也被称为Dependency Injection(DI)。IoC容器是Spring框架的重要组成部分,它负责管理...
Spring IOC和AOP的原理及实例详解 在软件开发中,控制反转(IOC)和面向切面编程(AOP)是两种非常重要的设计模式。Spring框架正是基于这两种模式的思想设计的。下面我们将详细介绍Spring IOC和AOP的原理及实例详解...