Spring为应用系统的开发提供了极大的方便,其IoC反向注入(或DI依赖注入)的概念也彻底地改变了旧的编程方式,让我们只需关注如何使用对象,而创建对象交给Spring去完成,即把使用对象和创建对象分离。

同时,Spring也为我们提供了创建对象的多种配置方法。以前我们大都用XML来配置,而在Spring 3.1后用Java代码配置已能完全取代XML配置(用Java代码配置也称为JavaConfig)。新的应用系统建议都采用JavaConfig方式进行配置。用JavaConfig比用XML来配置的好处是让程序员更容易地进行配置,以及更容易地找到在哪里配置的。

不过,对于大型系统其配置分散在多处,大量的@Autowired让程序员有时也难以琢磨依赖是从哪里注入进来的。比如,下面的@Autowired:

@Configuration
public class AppConfig {
@Autowired
DataSource dataSource; ...
}

@Autowired将指示Spring从其容器里注入依赖对象,但程序员有时会关心该依赖项是在哪里定义的,以便检查或修改。

这篇文章说到了一种可行的方法。即先定义一个接口:

public interface DataConfig {
DataSource dataSource();
}

然后实现该接口:

@Configuration
public class JndiDataConfig implements DataConfig {
@Bean
public DataSource dataSource() {
...
}
}

最后再注入该接口:

@Configuration
public class AppConfig {
@Autowired
private DataConfig dataConfig; @Bean
public AccountRepository accountRepository() {
return new JdbcAccountRepository(dataConfig.dataSource());
}
}

注意,这里不是直接注入DataSource依赖项,而是间接注入DataConfig接口,并通过该接口去获取依赖项。

该文章也说到,这样做的好处是,在Eclipse里我们可以通过Ctrl+T来查看DataConfig的实现类有哪些,这样就可以方便地知道DataConfig是在哪里定义的了。

同时该文章还说到可以用注解来进一步显化配置,请查看该文章的@Dev部分,这里不再赘述。

本人今天也在思考相同的问题,即如何让程序员更容易地找到配置的地方,也正好想到基于接口的配置方法。书写本文时发现了这篇文章,深感认同。不过,这里还有个小问题可能产生隐患。上面我们实现了DataConfig接口,再摘抄如下:

@Configuration
public class JndiDataConfig implements DataConfig {
@Bean
public DataSource dataSource() {
...
}
}

在Eclipse中我们经常是先书写public class ... 这一行,然后用Ctrl+1来自动生成实现接口的方法,再然后才开始写自己的代码,而此时就很容易忘记加上@Bean注解了,尤其是在DataConfig接口有大量方法的情况下更容易疏忽。一旦没加上@Bean注解则在AppConfig中获取到的DataSource(dataConfig.dataSource())依赖项就是一个new出来的普通对象,而不是一个Spring Bean,这将导致两个问题:

  1. 每次调用dataConfig.dataSource()都将重新创建DataSource对象。这或许不是我们希望的结果。
  2. 虽然这个例子注入的DataSource对象不太可能需要Spring AOP拦截,但如果我们需要注入的对象是一个需要被AOP拦截的对象(如需要事务控制)则将造成假象,因为它只是一个new出来的普通对象,而不是Spring Bean,此时Spring并不会对该对象进行AOP处理。

当然,即使@Configuration类不实现某个接口,只要其方法上没加上@Bean注解都会有此问题,但让@Configuration类实现某个接口后,再结合Eclipse IDE工具的方便性,我们就更加容易地忘记加上@Bean注解。忘记加上@Bean注解导致的系统隐患是,系统仍能运行但失去了Spring为我们提供的诸如AOP事务控制的功能,将产生不可预计的后果,并且很难去发现原因。

为应对此问题,经实测我们可以在接口上增加@Bean注解,如下:

public interface DataConfig {
@Bean
DataSource dataSource();
}

此后一切不变,我们仍然要在实现该接口的@Configuration类(即上面的JdbcDataConfig类)的方法加上@Bean(Eclipse不会自动加上)。而一旦忘记加则上面AppConfig中的dataConfig.dataSource()调用将报错:No bean named 'dataSource' is defined。

让系统在启动时报错也是一种消除隐患的方法。:)

上面,我们用接口来定义要配置的内容,这种做法还有另一个使用场景。试想一下某个系统有基础层和应用层两层,基础层提供了很多模块,有些模块应用层要用,有些不用。并且假设基础层的所有模块都在同一个jar包中。我们该如何配置基础层呢?此时需要考虑两个问题:

  1. 如果用@ComponentScan来扫描基础层,则那些不需要的模块也将被扫描出来。如果这些不需要的模块必须配置才能启动起来则造成整个系统无法启动。因此,我们要避免用@ComponentScan来扫描基础层(以及第三方软件),而只去扫描应用层。
  2. 基础层和应用层大都是由不同团队负责开发,如何让应用层团队做好基础层模块的配置呢?一种做法是口头交流,更好的做法是代码级交流。

利用上面的基于接口的配置方法可有效地解决配置的难题。

首先,基础层为每个模块都定义独自的配置接口,应用层团队只要实现该配置接口即可,这样就解决了交流的问题。其次,基础层的每个模块都有一个入口配置,应用层只需@Import进去即可。

如果参照Spring MVC的做法,我们也可以为每个模块创建一个@EnableModule1、@EnableModule2等这样的注解,让配置更加显化。

通过接口来显化要配置的内容对于多人多团队开发将起到积极的作用,使整个系统的配置过程更加清晰,配置与实际运行更加可控,遇到问题时更容易找到配置点。

如何有效地配置基于Spring的应用系统的更多相关文章

  1. 基于Spring的异步系统实现方案

    一般的实现方案 发送异步消息所使用的工具类: import java.util.Date; import javax.jms.Destination; import javax.jms.JMSExce ...

  2. 基于Spring框架应用的权限控制系统的研究和实现

    摘 要: Spring框架是一个优秀的多层J2EE系统框架,Spring本身没有提供对系统的安全性支持.Acegi是基于Spring IOC 和 AOP机制实现的一个安全框架.本文探讨了Acegi安全 ...

  3. Spring Cloud Config(一):聊聊分布式配置中心 Spring Cloud Config

    目录 Spring Cloud Config(一):聊聊分布式配置中心 Spring Cloud Config Spring Cloud Config(二):基于Git搭建配置中心 Spring Cl ...

  4. 基于Spring Boot、Spring Cloud、Docker的微服务系统架构实践

    由于最近公司业务需要,需要搭建基于Spring Cloud的微服务系统.遍访各大搜索引擎,发现国内资料少之又少,也难怪,国内Dubbo正统治着天下.但是,一个技术总有它的瓶颈,Dubbo也有它捉襟见肘 ...

  5. spring security 一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架

    Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架.它提供了一组可以在Spring应用上下文中 配置的Bean,充分利用了Spring ...

  6. 简单两步快速实现shiro的配置和使用,包含登录验证、角色验证、权限验证以及shiro登录注销流程(基于spring的方式,使用maven构建)

    前言: shiro因为其简单.可靠.实现方便而成为现在最常用的安全框架,那么这篇文章除了会用简洁明了的方式讲一下基于spring的shiro详细配置和登录注销功能使用之外,也会根据惯例在文章最后总结一 ...

  7. Weshop基于Spring Cloud开发的小程序商城系统

    WESHOP | 基于微服务的小程序商城系统 Weshop是基于Spring Cloud(Greenwich)开发的小程序商城系统,提供整套公共微服务服务模块,包含用户中心.商品中心.订单中心.营销中 ...

  8. 基于Spring Cloud 几行配置完成单点登录开发

    单点登录概念 单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一.SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统. ...

  9. 实战:基于 Spring 的应用配置如何迁移至阿里云应用配置管理 ACM

    最近遇到一些开发者朋友,准备将原有的Java Spring的应用配置迁移到 阿里云应用配置管理 ACM 中.迁移过程中,遇到不少有趣的问题.本文将通过一个简单的样例来还原迁移过程中遇到的问题和相关解决 ...

随机推荐

  1. Arcgis api For silverlight 加载高德地图

    原文 http://www.cnblogs.com/thinkaspx/archive/2012/11/13/2767752.html 地图仅供演示,研究使用.如要商用 请联系厂商. public c ...

  2. SVN的错误: working copy locked

    提示:your working copy appears to be locked. run cleanup to amend the situation. 产生这种情况大多是因为上次svn命令执行失 ...

  3. [一步一步MVC]第二回:还是ActionFilter,实现对业务逻辑的统一Authorize处理 OnActionExecuting内如何获取参数

    如何获取参数:http://www.cnblogs.com/anytao/archive/2009/04/23/anytao-mvc-02-actionauthorize.html 由问题引出 在AS ...

  4. Android framework浅析[转]

    Android系统从底向上一共分了4层,每一层都把底层实现封装,并暴露调用接口给上一层. 1. Linux内核(Linux Kernel) 1)Android运行在linux kernel 2.6之上 ...

  5. Webix快速跨浏览器的JavaScript UI组件

    网址:http://webix.com/ 寥寥几行代码就将页面渲染出来了,确实值得一试!

  6. hdu 3874 Necklace(bit树+事先对查询区间右端点排序)

    Mery has a beautiful necklace. The necklace is made up of N magic balls. Each ball has a beautiful v ...

  7. Trie树|字典树(字符串排序)

    有时,我们会碰到对字符串的排序,若采用一些经典的排序算法,则时间复杂度一般为O(n*lgn),但若采用Trie树,则时间复杂度仅为O(n). Trie树又名字典树,从字面意思即可理解,这种树的结构像英 ...

  8. [每日一题] OCP1z0-047 :2013-08-18 禁用启用约束――主键与外键 ..................................61

    正确答案:C 根据题意,测试结果如下: 1.创建表emp,并且设emp_no字段为主键,设mgr_no字段为外键. gyj@MYDB> create table emp 2 (emp_no nu ...

  9. Base64编码和解码算法

    Base64么新鲜的算法了.只是假设你没从事过页面开发(或者说动态页面开发.尤其是邮箱服务),你都不怎么了解过,仅仅是听起来非常熟悉. 对于黑客来说,Base64与MD5算法有着相同的位置.由于电子邮 ...

  10. 阿里云RDS导入服务器数据库 XtraBackup

    如果是centos系统,默认会开启selinux 一定需关闭selinux 解决方法:关闭它,打开/etc/selinux/config,把SELINUX=enforcing改为SELINUX=dis ...