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. Safari HTML5 Canvas Guide: Creating Charts and Graphs

    Safari HTML5 Canvas Guide: Creating Charts and Graphs Bar graphs are similar to data plots, but each ...

  2. PHP MySQL Update 之 Update

    更新数据库中的数据 UPDATE 语句用于在数据库表中修改数据. 语法 UPDATE table_name SET column_name = new_value WHERE column_name ...

  3. 怎么用MindMapper分类功能整理导图

    我们在绘制导图时是按着我们大脑中的思维来的,虽然有着总体逻辑,但是在细节上面还是不可避免的有些小杂乱,我们则可以通过MindMapper分类功能来对导图进行整理. 我们在打开MindMapper思维导 ...

  4. structs2标签

    Struts2常用标签总结 一 介绍 1.Struts2的作用 Struts2标签库提供了主题.模板支持,极大地简化了视图页面的编写,而且,struts2的主题.模板都提供了很好的扩展性.实现了更好的 ...

  5. ng-cli

    angluar2 cli 是一个比较好的工具 .解决 Angular 2 环境设置是一大入门门槛,有22%的人说环境设置太过复杂.Angular CLI的诞生,正是为了解决这个问题. 1. 基本介绍 ...

  6. 怎样使用jetty

    一直都听说jetty跟Tomcat一样,是一个web容器.之前做项目的时候,也使用过jetty,只是当时jetty是作为一个插件,跟maven集成使用的.那个时候,因为是第一次使用jetty,感觉je ...

  7. Swift中的设计模式

    设计模式(Design Pattern)是 对软件设计中普遍存在的各种问题,所提出的解决方案.这个术语是由埃里希·伽玛等人(Erich Gamma,Richard Helm,Ralph Johnson ...

  8. 中秋佳节--理解Enum枚举

    一.Enum枚举的作用 1.使用枚举可以限定取值范围,枚举中定义的每个常量都可以理解为对象: Eg: Public enum Color{ RED, GREEN,BULE; } 说明:RED实际上就表 ...

  9. PHP安装mcrypt.so报错 mcrypt.h not found 的解决办法

    报错内容:configure: error: mcrypt.h not found. Please reinstall libmcrypt 网上搜索了很多,包括自带的 yum install libm ...

  10. visual studio 2010 C语言声明异常

    如下这段程序,是C_Primer_plus_第五版内的一个复习题答案(感觉声明i的值有问题),在GCC上面可以运行,但是移植到VS2010就一堆错误, #include<stdio.h> ...