写两个关于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. 让Sqlite脱离VC++ Runtime独立执行

    前段时间在开发OrayTalk(傲瑞通企业即时通信系统)的聊天记录模块时用到了Sqlite,这是我第一次接触和使用Sqlite,整体感觉还是很不错的.这里把我使用Sqlite的经验跟大家分享一下. 一 ...

  2. 用python 爬取网页图片

    import re import string import sys import os import urllib url="http://tieba.baidu.com/p/252129 ...

  3. 关于UtilTimerStack类的使用--XWork2、Struts2内置性能诊断类

    关于UtilTimerStack类的使用--XWork2.Struts2内置性能诊断类 一.UtilTimerStack做什么用的? 这个本来是Xwork2(Struts2的核心)的相关的工具类,可以 ...

  4. 文字超出DIV后,隐藏文字并显示...

    <html> <head> <style type="text/css"> #cs{width:100px;height:50px;line-h ...

  5. Asp.Net MVC5入门学习系列⑤

    原文:Asp.Net MVC5入门学习系列⑤ 检查VS生产的编辑方法和编辑窗体 前面我们一步使用强类型,然后创建Controller(控制器)的时候,VS默认已经给我们把CURD都简单的实现了.这篇的 ...

  6. 3-05. 寻求倒数第二链线性表K项目(15)(STL list应用 ZJU_PAT)

    主题链接:http://pat.zju.edu.cn/contests/ds/3-05 给定一系列正整数,请设计一个尽可能高效的算法.查找倒数第K个位置上的数字. 输入格式说明: 输入首先给出一个正整 ...

  7. 苹果iOS苹果公司的手机用户都有权索赔

    大家知道.手机中的操作系统(基础软件)存储在手机固(firm,ware)之中,一般而言,手机用户自己是不能修改的. 苹果iOS手机的系统后门(服务程序)也存储在手机固件之中.手机用户自己是无法删除的. ...

  8. c语言内存对齐(1)

    在<C陷阱与缺陷>有这样一个例子: #include <stdio.h> int main(void) { int i; char c; ;i<;i++){ scanf( ...

  9. Ora中select某时间段记录sql语句

    要查找某时间段的记录,例如查找2013-11-1到2013-11-30的记录. ' group by user_name, user_id 注意:SQL语句中含有sum累加函数,末尾要加group b ...

  10. JavaScript一个类继承中实现

    JavaScript类是默认原型对象继承: var Person = function() { this.name = "people"; this.hello = functio ...