Spring松耦合示例

最近公司需要,项目中要用到Spring和Ibatis。趁着过年好好学习学习。Ibatis就如同Hibernate一样的持久层技术,学习起来难度不大,但Spring可不一样,揣着Ioc,DJ和AOP,四处走红。学起来可不容易。就市面上而言,就一本《expert one-on-one J2EE Development without EJB中文版》值得参考,为了生活,再贵也得买。这本书的前五章都是说EJB的不是,从第六章开始进入正题,介绍控制反转,以后基本都是说Spring了。

可能本人比较愚笨,控制反转弄得不明白。这样就得上网上找答案了。最后在一个叫Bromon的blog上找到的浅显易懂的答案。下面就是引用他说的话:


IoC与DI

  首先想说说IoC(Inversion of Control,控制倒转)。这是spring的核心,贯穿始终。所谓IoC,对于spring框架来说,就是由spring来负责控制对象的生命周期和 对象间的关系。这是什么意思呢,举个简单的例子,我们是如何找女朋友的?常见的情况是,我们到处去看哪里有长得漂亮身材又好的mm,然后打听她们的兴趣爱 好、qq号、电话号、ip号、iq号………,想办法认识她们,投其所好送其所要,然后嘿嘿……这个过程是复杂深奥的,我们必须自己设计和面对每个环节。传 统的程序开发也是如此,在一个对象中,如果要使用另外的对象,就必须得到它(自己new一个,或者从JNDI中查询一个),使用完之后还要将对象销毁(比 如Connection等),对象始终会和其他的接口或类藕合起来。

  那么IoC是如何做的呢?有点像通过婚介找女朋友,在我和女朋友之间引入了一个第三者:婚姻介绍所。婚介管理了很多男男女女的资料,我可以向婚 介提出一个列表,告诉它我想找个什么样的女朋友,比如长得像李嘉欣,身材像林熙雷,唱歌像周杰伦,速度像卡洛斯,技术像齐达内之类的,然后婚介就会按照我 们的要求,提供一个mm,我们只需要去和她谈恋爱、结婚就行了。简单明了,如果婚介给我们的人选不符合要求,我们就会抛出异常。整个过程不再由我自己控 制,而是有婚介这样一个类似容器的机构来控制。Spring所倡导的开发方式就是如此,所有的类都会在spring容器中登记,告诉spring你是个什 么东西,你需要什么东西,然后spring会在系统运行到适当的时候,把你要的东西主动给你,同时也把你交给其他需要你的东西。所有的类的创建、销毁都由 spring来控制,也就是说控制对象生存周期的不再是引用它的对象,而是spring。对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象 都被spring控制,所以这叫控制反转。如果你还不明白的话,我决定放弃。

IoC的一个重点是在系统运行中,动态的向某个对象提供它所需要的其他对象。这一点是通过DI(Dependency Injection,依赖注入)来实现的。比如对象A需要操作数据库,以前我们总是要在A中自己编写代码来获得一个Connection对象,有了 spring我们就只需要告诉spring,A中需要一个Connection,至于这个Connection怎么构造,何时构造,A不需要知道。在系统 运行时,spring会在适当的时候制造一个Connection,然后像打针一样,注射到A当中,这样就完成了对各个对象之间关系的控制。A需要依赖 Connection才能正常运行,而这个Connection是由spring注入到A中的,依赖注入的名字就这么来的。那么DI是如何实现的呢? Java 1.3之后一个重要特征是反射(reflection),它允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性,spring就是通过反射来实现注入的。关于反射的相关资料请查阅java doc。

我想通过Bromon的介绍,大家对IoC和DI都有了比较生动的理解了。再来看看《expert one-on-one J2EE Development without EJB中文版》是怎么解释这两个概念的。书上是这么说的:

IoC是一个很大的概念,可以用不同的方式来实现。主要的实现形式有两种:

依赖查找:容器提供回调接口和上下文环境给组件。EJB和Apache Avalon都是使用这种方式。

依赖注入:组件不做定位查询,只是提供普通的Java方法让容器去决定依赖关系。容器全权负责组件的装配,它会把符合依赖关系的对象通过JavaBean属性或者构造子传递给需要的对象。通过JavaBean属性注射依赖关系的做法称为设值方法注入(Setter Injection);将依赖关系作为构造子参数传入的做法称为构造子注入(Constructor Injection)。

面向对象设计的理念是把整个系统分成一组可重用的组件,然而,当系统变得越大的时候,尤其是在java中,这最大的对象依赖将会紧紧耦合,以至于非常难以管理和修改,而现在,你可以使用Spring框架扮演一个中间模块的角色,方便高效地管理其他组件依赖

输出生成的例子

看个例子,假设你的项目有一个方法可以输出内容到csv或者json格式,你可能写出这样的代码

package com.mkyong.output;

public interface IOutputGenerator
{
public void generateOutput();
}

,然后是实现接口的类

package com.mkyong.output.impl;

import com.mkyong.output.IOutputGenerator;

public class CsvOutputGenerator implements IOutputGenerator
{
public void generateOutput(){
System.out.println("Csv Output Generator");
}
}

再写个Json生成的类

package com.mkyong.output.impl;

import com.mkyong.output.IOutputGenerator;

public class JsonOutputGenerator implements IOutputGenerator
{
public void generateOutput(){
System.out.println("Json Output Generator");
}
}

有好几种方法来调用IOutputGenerator接口,以及我们如何使用Spring来避免对象的过度耦合。

方法1-直接调用

package com.mkyong.common;

import com.mkyong.output.IOutputGenerator;
import com.mkyong.output.impl.CsvOutputGenerator; public class App
{
public static void main( String[] args )
{
IOutputGenerator output = new CsvOutputGenerator();
output.generateOutput();
}
}

问题:

这种方法,output这个对象和CsvOutputGenerator耦合在了一起,每次要改变输出格式的话都要修改代码,如果这类代码遍布项目,那么改起来就跪了

方法2-通过帮助类调用

也许你会想创建一个Helper类吧所有的output实现都移进去

package com.mkyong.output;

import com.mkyong.output.IOutputGenerator;
import com.mkyong.output.impl.CsvOutputGenerator; public class OutputHelper
{
IOutputGenerator outputGenerator; public OutputHelper(){
outputGenerator = new CsvOutputGenerator();
} public void generateOutput(){
outputGenerator.generateOutput();
} }

然后可以这样调用

package com.mkyong.common;

import com.mkyong.output.OutputHelper;

public class App
{
public static void main( String[] args )
{
OutputHelper output = new OutputHelper();
output.generateOutput();
}
}

问题:

看起来似乎更加优雅了,你仅仅需要管理这个Helper类就可以实现不同格式的输出需求改变了,然而,Helper还是和CvsOutputGenerator耦合,每一次要改变输出格式的时候,都要对Helper类做一下微调。

方法3-Spring

Spring依赖注入很合适,可以使不同的格式生成类分离开来

首先对OutputHelper做一点微调,添加了一个参数

package com.mkyong.output;

import com.mkyong.output.IOutputGenerator;

public class OutputHelper
{
IOutputGenerator outputGenerator; public void generateOutput(){
outputGenerator.generateOutput();
} public void setOutputGenerator(IOutputGenerator outputGenerator){
this.outputGenerator = outputGenerator;
}
}

然后创建一个Spring bean配置文件,并声明所有的Java对象依赖

<!-- Spring-Common.xml -->
<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-2.5.xsd"> <bean id="OutputHelper" class="com.mkyong.output.OutputHelper">
<property name="outputGenerator" ref="CsvOutputGenerator" />
</bean> <bean id="CsvOutputGenerator" class="com.mkyong.output.impl.CsvOutputGenerator" />
<bean id="JsonOutputGenerator" class="com.mkyong.output.impl.JsonOutputGenerator" /> </beans>

然后通过Spring调用

package com.mkyong.common;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import com.mkyong.output.OutputHelper; public class App
{
public static void main( String[] args )
{
ApplicationContext context =
new ClassPathXmlApplicationContext(new String[] {"Spring-Common.xml"}); OutputHelper output = (OutputHelper)context.getBean("OutputHelper");
output.generateOutput(); }
}

以后要改Json格式,直接改一下xml配置文件就行了。能够减少错误

结论

通过Spring框架的依赖注入,可以优雅的管理对象依赖,更大的灵活性,尤其是对于Java项目非常好用。

Spring松耦合示例(转)& IOC的更多相关文章

  1. Spring松耦合实例

    假设你的项目有一个函数输出的内容,以CSV或JSON格式.您的代码可能看起来像下面的例子: File : IOutputGenerator.java – 输出生成器接口 package com.yii ...

  2. C#进阶系列——MEF实现设计上的“松耦合”(四):构造函数注入

    前言:今天十一长假的第一天,本因出去走走,奈何博主最大的乐趣是假期坐在电脑前看各处堵车,顺便写写博客,有点收获也是好的.关于MEF的知识,之前已经分享过三篇,为什么有今天这篇?是因为昨天分享领域服务的 ...

  3. Spring(一)之IOC、bean、注入

    [TOC] spring简介 首先它是一个开源的.用来简化企业级应用开发的框架. Spring为编写企业应用程序提供了轻量的解决方案,同时仍然支持使用声明式事务. 用RMI或web service远程 ...

  4. Spring详解篇之IoC控制反转

    ###一.Spring概况 spring是一个开源框架 是一个轻量的控制反转和面向切面的容器框架 大小和开销都是轻量的. 通过控制反转技术可以达到松耦合的目的 切面编程,允许通过分离应用的业务逻辑. ...

  5. Spring框架系列(3) - 深入浅出Spring核心之控制反转(IOC)

    在Spring基础 - Spring简单例子引入Spring的核心中向你展示了IoC的基础含义,同时以此发散了一些IoC相关知识点; 本节将在此基础上进一步解读IOC的含义以及IOC的使用方式.@pd ...

  6. 1.【转】spring MVC入门示例(hello world demo)

    1. Spring MVC介绍 Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦,基于 ...

  7. Spring3系列2 -- 松耦合的实现

    Spring3系列2 -- 松耦合的实现 一.      环境 spring-framework-3.2.4.RELEASE jdk1.7.0_11 Maven3.0.5 eclipse-jee-ju ...

  8. 【SSH系列】spring中为什么要使用IOC

    开篇前言 在前面的博文中,小编主要简单的介绍了spring的入门知识,随着学习的深入,我们知道spring最核心的两大技术,IOC和AOP,这两个技术也是spring最耀眼的地方,在后续的博文中小编将 ...

  9. 【spring源码分析】IOC容器初始化——查漏补缺(一)

    前言:在[spring源码分析]IOC容器初始化(十一)中提到了初始化bean的三个步骤: 激活Aware方法. 后置处理器应用(before/after). 激活自定义的init方法. 这里我们就来 ...

随机推荐

  1. 关于电容与Q值

    1, 电容模型 电容阻抗可以表示为: 可算得自谐振频率点为: 在该点,容抗与感抗差为0,电容表现出纯电阻性. 2, 阻抗曲线 自谐点是区分电容器呈容性还是感性的分界点.从阻抗曲线看,在自谐点附近阻抗较 ...

  2. 廖雪峰Java14Java操作XML和JSON-1XML-4第三方XML库

    总结: 使用Jackson可以快速在XML和JavaBean之间互相转换 可使用Annotation定制序列化和反序列化

  3. 单独安装Babel或者Less

    1.直接安装Babel法: 1)初始化自动创建package.json npm init 2)首先全局安装Babel. npm install -g babel-cli 3)项目安装Babel. np ...

  4. Poj 2559 最大矩形面积 v单调栈 分类: Brush Mode 2014-11-13 20:48 81人阅读 评论(0) 收藏

    #include<iostream> #include<stack> #include<stdio.h> using namespace std; struct n ...

  5. exiftool(-k)与gui的联合使用

    首先下载一个exiftool下载后改名字https://sno.phy.queensu.ca/~phil/exiftool/ 根据自己的操作系统选择,我需要这个 然后下载guihttp://u88.n ...

  6. java日志管理 - slf4j+log4j2

    1 . 概述 1.1  日志框架实现 log4j是apache实现的一个开源日志组件: logback同样是由log4j的作者设计完成的,拥有更好的特性,用来取代log4j的一个日志框架,是slf4j ...

  7. 短URL系统、301/302重定向

    短 URL 系统是怎么设计的?https://yq.aliyun.com/articles/87600 短网址(short URL)系统的原理及其实现 https://hufangyun.com/20 ...

  8. 从一个prismWpfMVVM的例子中学到的

    整个程序如下,从博客园一个作者看到的例子,但是对这个例子做了点修改.我觉得这个更符合MVVM模式.这个用到了prism框架,在项目中要引用Microsoft.Practices.Prism.dll 按 ...

  9. PLSQL远程访问Oracle数据库配置

    PLSQL远程访问Oracle数据库的配置 监听器(LISTENER) :监听器是Oracle基于服务器端的一种网络服务,主要用于监听客户端向数据库服务器端提出的连接请求.既然是基于服务器端的服务,那 ...

  10. 2019-5-21-Roslyn-使用-Directory.Build.props-管理多个项目配置

    title author date CreateTime categories Roslyn 使用 Directory.Build.props 管理多个项目配置 lindexi 2019-05-21 ...