写两个关于Spring中使用IoC的小例子,一个是半动态创建Bean,另一个是全动态创建Bean,它们适合不同的应用场景。

  一、半动态:在一个实际项目中遇到过这样的问题,项目组开发的某个系统具备在LED屏上显示信息的功能。不同客户那里的LED屏各不相同,主要区别是驱动卡和显示格式。如果每次换LED屏时都是靠程序员去替换不同实现的代码,成本可想而知。那么,在不修改既有代码(甚至是不用编译既有工程)的情况下,怎样才能让系统的这个功能适应变化呢?

  首先抽象出一个接口,代表向LED屏打印的功能。

package com.mmh.printer;

public interface LEDPrinter {

    public void print(String content);
}

  然后根据不同品牌的LED屏,编写具体的打印功能。

package com.mmh.printer;

public class Brand1LEDPrinter implements LEDPrinter {

    @Override
public void print(String content) {
// 模拟不同品牌的LED显示屏操作
System.out.println("这是品牌1的LED显示内容: " + content);
}
}

  紧接着编写一个辅助类,客户端程序通过它实现LED屏的打印功能。

package com.mmh.printer;

public class LEDPrintHelper {

    private LEDPrinter printer;

    public void setPrinter(LEDPrinter printer) {
this.printer = printer;
} public void print(String content) {
printer.print(content);
}
}

  最后实现一个客户端调用的演示程序。

package com.mmh.main;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import com.mmh.printer.LEDPrintHelper; public class Application { public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext(
"appContext.xml"); LEDPrintHelper ledPrintHelper = (LEDPrintHelper) context.getBean("LEDPrintHelper");
ledPrintHelper.print("业务层产生的数据");
}
}

  在LED屏更换时,以上的代码,不管是调用方的还是被调用方的,都不需要做任何的修改。假设现在客户使用的是Brand2品牌LED屏,那么程序员只需要针对这种屏编写具体操作即可。

package com.mmh.printer;

public class Brand2LEDPrinter implements LEDPrinter {

    @Override
public void print(String content) {
// 模拟不同品牌的LED显示屏操作
System.out.println("这是品牌2的LED显示内容: " + content);
}
}

这个具体实现类完全可以封装到一个单独的jar中,那么以前的既有代码对于现在的开发人员可以完全透明。

  应对变化的功能是靠Spring的IoC来实现的。

<?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.xsd"> <bean id="LEDPrintHelper" class="com.mmh.printer.LEDPrintHelper">
<property name="printer" ref="Brand1LEDPrinter" />
</bean> <bean id="Brand1LEDPrinter" class="com.mmh.printer.Brand1LEDPrinter" /> <bean id="Brand2LEDPrinter" class="com.mmh.printer.Brand2LEDPrinter" /> </beans>

该配置文件定义了三个Bean,LEDPrintHelper是调用程序的接口,Brand1LEDPrinter和Brand2LEDPrinter分别代表了两种屏的具体操作。通过属性注入的方式,开发人员手动修改(这就是半动态的意思)LEDPrintHelper的printer属性值,从而更改LED屏的具体操作。

  二、全动态:在实际项目中还遇到过这样的问题,不同类型用户的登录实现方式是不同的,并且在系统的使用过程中用户的类型会不断增加。那么,在不修改既有代码(甚至是不用编译既有工程)的情况下,怎样才能让系统的这个功能适应变化呢?

  首先抽象一个接口,代表用户登录功能。

package com.mmh.login;

public interface UserLogin {
public boolean login(String username, String password);
}

  然后实现不同类型用户的登录过程。

package com.mmh.login;

public class UserALogin implements UserLogin {

    @Override
public boolean login(String username, String password) {
System.out.println("根据UserA的业务逻辑处理登录过程"); return true;
}
}
package com.mmh.login;

public class UserBLogin implements UserLogin {

    @Override
public boolean login(String username, String password) {
System.out.println("根据UserB的业务逻辑处理登录过程"); return true;
}
}

  紧接着开放给客户调用端一个统一的接口。这个接口在实际系统中经常会被实现为一个web service。

package com.mmh.login;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class UserLoginService { private ApplicationContext context = new ClassPathXmlApplicationContext(
"appContext.xml"); public boolean login(String username, String password, String logintype) {
UserLogin userLogin = (UserLogin) context.getBean(logintype); return userLogin.login(username, password);
}
}

  最后还是编写一个客户调用的演示。

package com.mmh.main;

import com.mmh.login.UserLoginService;

public class Application {

    public static void main(String[] args) {
UserLoginService service = new UserLoginService(); service.login("userA", "123456", "UserALogin"); service.login("userB", "123456", "UserBLogin");
}
}

  从上面的代码可以看到,不同的用户可以调用相同的接口进行不同的登录操作,被调用程序根据用户输入的参数自动匹配登录过程(这就是全动态的意思)。并且当系统增加用户类型时,既有代码不需要修改。应对变化的功能仍是靠Spring的IoC来实现的。

<?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.xsd"> <bean id="UserALogin" class="com.mmh.login.UserALogin" /> <bean id="UserBLogin" class="com.mmh.login.UserBLogin" /> </beans>

IoC in Spring的更多相关文章

  1. Spring源码-IOC部分-Spring是如何解决Bean循环依赖的【6】

    实验环境:spring-framework-5.0.2.jdk8.gradle4.3.1 Spring源码-IOC部分-容器简介[1] Spring源码-IOC部分-容器初始化过程[2] Spring ...

  2. Spring学习3—控制反转(IOC)Spring依赖注入(DI)和控制反转(IOC)

    一.思想理解 Spring 能有效地组织J2EE应用各层的对象.不管是控制层的Action对象,还是业务层的Service对象,还是持久层的DAO对象,都可在Spring的 管理下有机地协调.运行.S ...

  3. spring ioc 原理 spring aop原理

    大家一直都说spring的IOC如何如何的强大,其实我倒觉得不是IOC如何的强大,说白了IOC其实也非常的简单.我们先从IOC说起,这个概念其实是从我们平常new一个对象的对立面来说的,我们平常使用对 ...

  4. AS3 IOC框架Spring Actionscript 的使用总结

    Spring Actionscript 是众多围绕依赖注入提供解决方案的Flex控制反转框架之一 AS3 下经典的IOC框架有Spring ActionScript.Parsley.Flicc和Swi ...

  5. Spring IOC和Spring AOP的实现原理(源码主线流程)

    写在前面 正本文参考了<spring技术内幕>和spring 4.0.5源码.本文只描述原理流程的主线部分,其他比如验证,缓存什么可以具体参考源码理解. Spring IOC 一.容器初始 ...

  6. IoC之Spring.Net在Mvc项目中的使用

    MVC中使用Spring.net 前面学习了使用Autofac来实现控制反转,这里简单记录Spring.Net实现IoC和DI的步骤 第一步:安装如下Nuget包 (Spring.Web.Mvc) i ...

  7. spring揭密学习笔记(3)-spring ioc容器:Spring的IoC容器之BeanFactory

    1. Spring的IoC容器和IoC Service Provider的关系 Spring的IoC容器和IoC Service Provider所提供的服务之间存在一定的交集,二者的关系如图4-1所 ...

  8. 关于 IOC和spring基本配置详解

    Spring 中的两个概念 IOC控制反转(也叫依赖注入DI): AOP面向切面编程: 控制反转:当某个java对象需要(依赖)另一个java对象是,不是直接创建依赖对象,而是由实现IOC的容器来创建 ...

  9. .net IoC 之 Spring.Net 适合刚开始使用

    Spring.Net包括控制反转(IoC) 和面向切面(AOP),这篇文章主要说下IoC方面的入门. 一.首先建立一个MVC项目名称叫SpringDemo,然后用NuGet下载spring(我用的是S ...

随机推荐

  1. C语言库函数大全及应用实例七

    原文:C语言库函数大全及应用实例七 [编程资料]C语言库函数大全及应用实例七 函数名: getw 功 能: 从流中取一整数 用 法: int getw(FILE *strem); 程序例: #i nc ...

  2. Java项目生成静态页面

    第一次做项目需要生成静态页面,网上很多大牛对将网页生成静态页面有很多异议.说一下我的看法. 不外乎有以下因素: 1.从页面加载时间来看:静态页面不需要与数据库建立连接,尤其是访问数据量较大的页面,这种 ...

  3. SQL常规查询详解

    一.交叉连接(cross join) 交叉连接(cross join):有两种,显式的和隐式的,不带on子句,返回的是两表的乘积,也叫笛卡尔积. 例如:下面的语句1和语句2的结果是相同的. 语句1:隐 ...

  4. JUnit介绍

    8.1.1  JUnit简介 JUnit主要用来帮助开发人员进行Java的单元测试,其设计非常小巧,但功能却非常强 大. 下面是JUnit一些特性的总结: — 提供的API可以让开发人员写出测试结果明 ...

  5. 数以百万计美元的融资YO是什么东东?

    给自己做个广告哈,新栏目"面试"已经推出,回复"面试"就可以获取. 这两天最火的应用是什么.非yo莫属,堪称史上最简单的社交应用,仅仅能向好友发送一个yo. 出 ...

  6. Linux下使用Photorec恢复误格U盘

    photorec包含在testdisk软件包中, 所以直接通过包管理器直接安装testdisk安装即可. 使用root权限来运行软件,在终端键入 [shell] photorec [/shell] 然 ...

  7. Asterisk 未来之路3.0_0004

    原文:Asterisk 未来之路3.0_0004 Asterisk Wiki   asterisk 的Wiki是很多启迪和困惑的发源地,另外一个最重要的VOIP知识库www.voip-info.org ...

  8. JS获取字符串实际长度

    JS中默认中文字符长度和其它字符长度计算方法是一样的,但某些情况下我们需要获取中文字符串的实际长度,代码如下: function strLength(str) { var realLength = 0 ...

  9. JJG 623-2005 电阻应变仪计量检定规程

    JJG 623-2005 电阻应变仪计量检定规程 点击下载 JJG533-2007标准模拟应变量校准器检定规程 点击下载 JJG 533-1988标准(里面含有一些更具体的电路图供参考)

  10. 深入浅出SQL Server 2008 分区函数和分区表

    原文:深入浅出SQL Server 2008 分区函数和分区表 当我们数据量比较大的时候,我们需要将大型表拆分为多个较小的表,则只访问部门数据的查询就可以更快的运行,基本原理就是,因为要扫描的数据变的 ...