如何有效地配置基于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 中.迁移过程中,遇到不少有趣的问题.本文将通过一个简单的样例来还原迁移过程中遇到的问题和相关解决 ...
随机推荐
- socket基础(二)
Microsoft.Net Framework为应用程序访问Internet提供了分层的.可扩展的以及受管辖的网络服务,其名字空间System.Net和System.Net.Sockets包含丰富的类 ...
- HDU1754(线段树)
I Hate It Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total S ...
- 【错误】:Could not open JDBC Connection for transaction; nested exception is: Communications link failure;The last packet sent successfully to the server was 1 milliseconds ago
# #错误日志 2016-11-10 16:19:20,834 ERROR [org.quartz.core.JobRunShell] - Job DEFAULT.jobtask threw an u ...
- PL/SQL Developer 如何显示行号
一.工具-首选项-用户界面-编辑器-其它-显示行号二.工具-首选项-窗口类型-SQL窗口-显示隔号(行号)
- java web分页查询初试
ssh2分页查询初试,放着记录学习一下. entity:student.java: package com.zte.entity; /** * 数据持久化,跟数据库的的相应的表的字段是对应的. * * ...
- Collections你用对了吗?
.Net有两类基础的集合类型:List和Dictionary.List是基于Index的,Dictionary是基于key的.集合类型一般实现了IEnumberable,ICollection或者Il ...
- Spting使用memcached
applicationContext.xml配置文件: <?xml version="1.0" encoding="UTF-8"?> <bea ...
- SSH框架-unexpected token: * near line 1, column 8 [select * from tb_chaper where course_id = 2];报错解决方法
SSH项目,访问jsp页面出现报错,控制台显示报错信息: org.springframework.orm.hibernate3.HibernateQueryException: unexpected ...
- Atom编辑器
Atom介绍 Github的员工Nathan Sobo在Atom的博客中提到:”Sublime和TextMate十分方便,但是扩展性不足:另一方面,Emacs和 Vim扩展性很强却需要学习日程工作中很 ...
- 使用 React和webpack开发和打包发布
建议在 React 中使用 CommonJS 模块系统,比如 browserify 或 webpack,本次使用 webpack. 第一步.安装全局包 $ npm install babel -g $ ...