如何有效地配置基于Spring的应用系统
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,这将导致两个问题:
- 每次调用dataConfig.dataSource()都将重新创建DataSource对象。这或许不是我们希望的结果。
- 虽然这个例子注入的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包中。我们该如何配置基础层呢?此时需要考虑两个问题:
- 如果用@ComponentScan来扫描基础层,则那些不需要的模块也将被扫描出来。如果这些不需要的模块必须配置才能启动起来则造成整个系统无法启动。因此,我们要避免用@ComponentScan来扫描基础层(以及第三方软件),而只去扫描应用层。
- 基础层和应用层大都是由不同团队负责开发,如何让应用层团队做好基础层模块的配置呢?一种做法是口头交流,更好的做法是代码级交流。
利用上面的基于接口的配置方法可有效地解决配置的难题。
首先,基础层为每个模块都定义独自的配置接口,应用层团队只要实现该配置接口即可,这样就解决了交流的问题。其次,基础层的每个模块都有一个入口配置,应用层只需@Import进去即可。
如果参照Spring MVC的做法,我们也可以为每个模块创建一个@EnableModule1、@EnableModule2等这样的注解,让配置更加显化。
通过接口来显化要配置的内容对于多人多团队开发将起到积极的作用,使整个系统的配置过程更加清晰,配置与实际运行更加可控,遇到问题时更容易找到配置点。
如何有效地配置基于Spring的应用系统的更多相关文章
- 基于Spring的异步系统实现方案
一般的实现方案 发送异步消息所使用的工具类: import java.util.Date; import javax.jms.Destination; import javax.jms.JMSExce ...
- 基于Spring框架应用的权限控制系统的研究和实现
摘 要: Spring框架是一个优秀的多层J2EE系统框架,Spring本身没有提供对系统的安全性支持.Acegi是基于Spring IOC 和 AOP机制实现的一个安全框架.本文探讨了Acegi安全 ...
- Spring Cloud Config(一):聊聊分布式配置中心 Spring Cloud Config
目录 Spring Cloud Config(一):聊聊分布式配置中心 Spring Cloud Config Spring Cloud Config(二):基于Git搭建配置中心 Spring Cl ...
- 基于Spring Boot、Spring Cloud、Docker的微服务系统架构实践
由于最近公司业务需要,需要搭建基于Spring Cloud的微服务系统.遍访各大搜索引擎,发现国内资料少之又少,也难怪,国内Dubbo正统治着天下.但是,一个技术总有它的瓶颈,Dubbo也有它捉襟见肘 ...
- spring security 一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架
Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架.它提供了一组可以在Spring应用上下文中 配置的Bean,充分利用了Spring ...
- 简单两步快速实现shiro的配置和使用,包含登录验证、角色验证、权限验证以及shiro登录注销流程(基于spring的方式,使用maven构建)
前言: shiro因为其简单.可靠.实现方便而成为现在最常用的安全框架,那么这篇文章除了会用简洁明了的方式讲一下基于spring的shiro详细配置和登录注销功能使用之外,也会根据惯例在文章最后总结一 ...
- Weshop基于Spring Cloud开发的小程序商城系统
WESHOP | 基于微服务的小程序商城系统 Weshop是基于Spring Cloud(Greenwich)开发的小程序商城系统,提供整套公共微服务服务模块,包含用户中心.商品中心.订单中心.营销中 ...
- 基于Spring Cloud 几行配置完成单点登录开发
单点登录概念 单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一.SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统. ...
- 实战:基于 Spring 的应用配置如何迁移至阿里云应用配置管理 ACM
最近遇到一些开发者朋友,准备将原有的Java Spring的应用配置迁移到 阿里云应用配置管理 ACM 中.迁移过程中,遇到不少有趣的问题.本文将通过一个简单的样例来还原迁移过程中遇到的问题和相关解决 ...
随机推荐
- Qt中调用PolarSSL库(一)
最近一直在学习SSL相关的知识,也是先了解理论相关的知识,主要是SSL相关的基本概念和连接建立过程,主要是基于PolarSSL开源库进行学习.学习完了之后就希望能给有所运用,就想用Qt写一个简单的程序 ...
- ./configure : /bin/sh^M : bad interpreter
用命令行来编译Qt的时候发生标题尚的错误. 原因是文件中带有DOS行结束符,必须把它转换成UNix结束符 references: http://stackoverflow.com/questions/ ...
- Oracle 唯一主键引发的行锁
SQL> create table test(id int PRIMARY KEY, name char(10)); 表已创建. Session 1: SQL> select * from ...
- C# Cookie编程
Cookie,他最早出现是在Netscape Navigator 2.0中.Cookie其实就是由Web服务器创建的.将信息存储在机上的文件.那么为什么Web服务器要在客户机上面创建如此文件?这是因为 ...
- 关于Winsock编程中IO重叠的概念
我在看<Windows网络与通信程序设计>(王艳平)这本书时,对重叠IO很不理解,突然就冒出这么一个概念,没一点头绪.就目前的理解做一个整理. 第一种理解:OVERLAPPED,顾名思义为 ...
- 一起来学canvas (前言)
codeyy - 一依丫丫 一起来学canvas (前言)
- C#常用語法糖(Csharp Syntactic sugar)
首先需要声明的是“语法糖”这个词绝非贬义词,它可以给我带来方便,是一种便捷的写法,编译器会帮我们做转换:而且可以提高开发编码的效率,在性能上也不会带来损失.这让java开发人员羡慕不已,呵呵. 1. ...
- start_kernel——local_irq_disable
在启动初期须要关闭CPU的IRQ,原因: 因为尚未对中断代码.向量表,中断处理器进行初始化,所以必须关闭中断. 我的源码里面定义了 CONFIG_TRACE_IRQFLAGS_SUPPORT,所以调用 ...
- Oracle学习(十):视图,索引,序列号,同义词
1.知识点:能够对比以下的录屏进行阅读 视图,序列,索引,同义词 SQL> --视图:虚表 SQL> --视图的长处:简化复杂查询.限制数据訪问(银行用的多).提供数据的相互独立.相同的数 ...
- poj 3308 (最大流)
题意:n*m的地图,给出L个火星人登陆的坐标,要在火星人登陆地球的瞬间全部消灭他们,有一种激光枪,一次可以消灭一行(或一列),消灭一行(或一列)有不同的代价,总代价是所有激光枪的代价之积. 思路:之前 ...