IoC in Spring
写两个关于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的更多相关文章
- Spring源码-IOC部分-Spring是如何解决Bean循环依赖的【6】
实验环境:spring-framework-5.0.2.jdk8.gradle4.3.1 Spring源码-IOC部分-容器简介[1] Spring源码-IOC部分-容器初始化过程[2] Spring ...
- Spring学习3—控制反转(IOC)Spring依赖注入(DI)和控制反转(IOC)
一.思想理解 Spring 能有效地组织J2EE应用各层的对象.不管是控制层的Action对象,还是业务层的Service对象,还是持久层的DAO对象,都可在Spring的 管理下有机地协调.运行.S ...
- spring ioc 原理 spring aop原理
大家一直都说spring的IOC如何如何的强大,其实我倒觉得不是IOC如何的强大,说白了IOC其实也非常的简单.我们先从IOC说起,这个概念其实是从我们平常new一个对象的对立面来说的,我们平常使用对 ...
- AS3 IOC框架Spring Actionscript 的使用总结
Spring Actionscript 是众多围绕依赖注入提供解决方案的Flex控制反转框架之一 AS3 下经典的IOC框架有Spring ActionScript.Parsley.Flicc和Swi ...
- Spring IOC和Spring AOP的实现原理(源码主线流程)
写在前面 正本文参考了<spring技术内幕>和spring 4.0.5源码.本文只描述原理流程的主线部分,其他比如验证,缓存什么可以具体参考源码理解. Spring IOC 一.容器初始 ...
- IoC之Spring.Net在Mvc项目中的使用
MVC中使用Spring.net 前面学习了使用Autofac来实现控制反转,这里简单记录Spring.Net实现IoC和DI的步骤 第一步:安装如下Nuget包 (Spring.Web.Mvc) i ...
- spring揭密学习笔记(3)-spring ioc容器:Spring的IoC容器之BeanFactory
1. Spring的IoC容器和IoC Service Provider的关系 Spring的IoC容器和IoC Service Provider所提供的服务之间存在一定的交集,二者的关系如图4-1所 ...
- 关于 IOC和spring基本配置详解
Spring 中的两个概念 IOC控制反转(也叫依赖注入DI): AOP面向切面编程: 控制反转:当某个java对象需要(依赖)另一个java对象是,不是直接创建依赖对象,而是由实现IOC的容器来创建 ...
- .net IoC 之 Spring.Net 适合刚开始使用
Spring.Net包括控制反转(IoC) 和面向切面(AOP),这篇文章主要说下IoC方面的入门. 一.首先建立一个MVC项目名称叫SpringDemo,然后用NuGet下载spring(我用的是S ...
随机推荐
- [CLR via C#]5.1 基元类型
原文:[CLR via C#]5.1 基元类型 某些数据类在开发中非常常用,以至于许多编译器允许代码已简化的语法来操作它们.例如可以使用以下语法来分配一个整数: System.Int32 a = ne ...
- CSS3+HTML5特效4 - 横向无缝滚动
先看例子 This is a test 1. This is a test 2. This is a test 3. This is a test 4. This is a test 5. This ...
- JS中5秒中跳转到其他页面
原文:JS中5秒中跳转到其他页面 <head> <meta http-equiv="Content-Type" content="text/html; ...
- C# 之 托付
托付(delegate) 托付是一种能够把引用存储为函数的类型.托付也能够看成是一种数据类型,能够用于定义变量,但它是一种特殊的数据类型,它所定义的变量能接受的数值仅仅能是一个函数,更确切的说 ...
- VC++.Net CAD编程架构
1.每个对应的菜单项的图形抽象的, 图形抽象基类, 取决于改变来自子(如矩形.椭圆形) 2.在Doc对象管理列表管理,图形对象,当图形需要重绘或序列存储,通过遍历该列表的对象可以是 3. 每个类的职责 ...
- PHP 17: MySQL的简单介绍
原文:PHP 17: MySQL的简单介绍 这一章将简单介绍MySQL的基本知识. 本文来自http://lib.hackbase.com/html/8/35125.htm. MySQL是最受欢迎的开 ...
- SQL点滴24—监测表的变化
原文:SQL点滴24-监测表的变化(转载) 在网上看到一篇关于监测表中的插入,更新,删除的方法,使用触发器实现的,很有价值. 地址:http://www.dbaunion.com/u/livecoac ...
- 开源文档管理系统LogicalDOC测试报告---安装篇
开源文档管理系统LogicalDOC测试报告---安装篇 分类: Linux2011-06-22 15:40 7436人阅读 评论(3) 收藏 举报 文档管理测试mysql数据库installerja ...
- SQL Server中如何备份存储过程(SP)和函数(Fun)
考虑到安全因素,我们经常需要对数据库的存储过程(SP)和函数(Fun)进行备份 下面提供了一种简单的方式, 存储过程(SP)SQL代码如下: select p.name as SpName,m.def ...
- C++关于数字逆序输出的两种思路,及字符串逆序输出
C++关于数字逆序输出的两种思路,及字符串逆序输出 作者:GREATCOFFEE 发布时间:NOVEMBER 15, 2012 分类:编程的艺术 最近在跟女神一起学C++(其实我是不怀好意),然后女神 ...