- 浏览: 442523 次
- 性别:
- 来自: 上海
文章分类
最新评论
-
建悦胡:
好文,必须顶
关于系统中使用多个PropertyPlaceholderConfigurer的配置 -
阿毛色色:
感谢!解决问题
关于系统中使用多个PropertyPlaceholderConfigurer的配置 -
fangwei06056115:
...
Maven中指定得AspectJ依赖无法添加得解决方案 -
abc3720:
Dashboard配置系统 是是商业的吗?如果不是发我看一下吗 ...
图示ExtJS商业智能的仪表盘配置系统 - (Season 1) -
maidou80:
的确有帮助 3Q
Ext表单中的combobox回填显示值问题
2005夏于上海,初次使用了Spring框架开发企业应用,当时还没有中文书籍,只能看Spring官方提供的Reference,甚是简陋,直到一年后人民邮电出版了第一本关于Spring技术的中文翻译书籍《Spring in action》,解决了广大人民群众的精神需求,也因此书让我认识了Manning出版社,之后一直在关注他的Action系列图书,此前将众多书籍封面整理成册,闲时品茶拿来翻阅不亦乐乎,有兴趣的同学可以雅俗共赏《Manning出版社In Action系列图书 》。此篇且谈Spring注释配置之实践。
关键词: Spring, Annotation, iBatis, 依赖注入(IOC), BeanNameGenerator, Inner Class, 后依赖注入
引言:
长久以来国内的众多应用都在使用Spring框架,它为我们带来的好处不言而喻。但问题是Spring2.0以下版本尚未支持注释装配,而企业应用大多分作MVC三层结构,每层Bean的配置渐渐膨胀,直到打开了XML文件,IDE不堪重负崩溃为止,情形实为惊人。后有了Convention over Configuration的软件设计范式,即“约定优于配置”,也作“约定编程”。Ruby and Rails和EJB3也都按此实现,Spring注释也基于此。
首先,在解答为什么要使用注释装配之前,先看看没有它时配置文件臃肿的样子,如:持久层DAO的Spring配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans ‘略去声明’> <bean id="scDbInfoDAO" class="com.data.switching.db.dao.impl.ScDbInfoDAOImpl" parent="sqlMapClientDAO" /> <bean id="scFtpInfoDAO" class="com.data.switching.db.dao.impl.ScFtpInfoDAOImpl" parent="sqlMapClientDAO" /> <bean id="scParmInfoDAO" class="com.data.switching.db.dao.impl.ScParmInfoDAOImpl" parent="sqlMapClientDAO" /> <bean id="scParmTypeDAO" class="com.data.switching.db.dao.impl.ScParmTypeDAOImpl" parent="sqlMapClientDAO" /> <bean id="scRoleDAO" class="com.data.switching.db.dao.impl.ScRoleDAOImpl" parent="sqlMapClientDAO" /> <bean id="scRoleMenuDAO" class="com.data.switching.db.dao.impl.ScRoleMenuDAOImpl" parent="sqlMapClientDAO" /> <bean id="scSiteLoadDAO" class="com.data.switching.db.dao.impl.ScSiteLoadDAOImpl" parent="sqlMapClientDAO" /> <bean id="scSiteStatDAO" class="com.data.switching.db.dao.impl.ScSiteStatDAOImpl" parent="sqlMapClientDAO" /> 略去同样999个配置 ... ...
使用后的情况:
<?xml version="1.0" encoding="UTF-8"?> <beans> <context:annotation-config /> <context:component-scan base-package="com.longtop.data.switching.db.dao" name-generator="com.seraph.bi.suite.support.core.generator.IBatisDaoBeanNameGenerator" /> </beans>
现在大家想必都了解到为什么使用注释配置,两者之间后者很优雅,而这全在于约定优于配置。
解决方案:
改造过程是,首先在DAO的实现类中加入@Repository标签,说明这是持久层的服务。另外两层的标签@Service, @Controller,实现类如下:
import org.springframework.stereotype.Repository; ... @Repository public class ScDbInfoDAOImpl extends SqlMapClientDaoSupport implements ScDbInfoDAO { ...
在配置文件中加入:
<context:annotation-config /> <context:component-scan base-package="com.longtop.data.switching.db.dao" name-generator="com.seraph.bi.suite.support.core.generator.IBatisDaoBeanNameGenerator" />
因接口名为ScDbInfoDAO,而实现类名为 ScDbInfoDAOImpl,引用类中的域名是接口的首字母小写名scDbInfoDAO ,而容器生成的默认类名是 scDbInfoDAOImpl,所以不行,但spring预留了
接口BeanNameGenerator,只要实现它我们就可以自己指定生成bean的名字,这里的实现类如下:
/** * 类说明: 生成iBatis的DAO的Spring注册名,规则是首字母小写,并去掉后缀名<br> * 创建时间: 2011-1-26 下午12:44:20<br> * * @author seraph<br> * @email: seraph115@gmail.com<br> */ public class IBatisDaoBeanNameGenerator implements BeanNameGenerator { private static final Logger logger = Logger .getLogger(IBatisDaoBeanNameGenerator.class); private static final String DAO_IMPLEMENTS_SUFFIX = "Impl"; public String generateBeanName(BeanDefinition paramBeanDefinition, BeanDefinitionRegistry paramBeanDefinitionRegistry) { String[] strs = paramBeanDefinition.getBeanClassName().split("\\."); String shortName = strs[strs.length - 1]; shortName = StringUtils.uncapitalize(shortName); shortName = shortName.replace(DAO_IMPLEMENTS_SUFFIX, ""); logger.debug("Generated a ibatis DAO bean's name: [" + shortName + "]"); return shortName; } }
到这里我们可以自由的指定注释类的bean名称,但对于为DAO提供dataSource和sqlMapClient的Inner Class,即parent="sqlMapClientDAO"要如何处理呢?
<bean id="scRoleDAO" class="com.data.switching.db.dao.impl.ScRoleDAOImpl" parent="sqlMapClientDAO" />
<bean id="sqlMapClientDAO" class="org.springframework.orm.ibatis.support.SqlMapClientDaoSupport" abstract="true"> <property name="dataSource" ref="${jdbc.dataSource}" /> <property name="sqlMapClient" ref="sqlMapClient" /> </bean> <bean id="sqlMapClient" class="com.seraph.bi.suite.support.core.IncludesSqlMapClientFactoryBean"> <property name="configLocation" value="classpath:ibatis/platform/orcl/sqlmap.xml" /> </bean>
为了解决此问题,我们实现了一个后置注入的类:SqlMapClientDaoInjector用来在DAO加载到context中后注入其依赖。类代码如下:
/** * 类说明: 向iBatis的DAO中注入依赖<br> * 创建时间: 2011-1-26 上午10:51:28<br> * * @author seraph<br> * @email: seraph115@gmail.com<br> */ public class SqlMapClientDaoInjector implements ApplicationContextAware, InitializingBean { private static final Logger logger = Logger.getLogger(SqlMapClientDaoInjector.class); @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { SpringContext.setApplicationContext(applicationContext); } public void afterPropertiesSet() throws Exception { Assert.notNull(dataSource, "Property 'dataSource' is required."); Assert.notNull(sqlMapClient, "Property 'sqlMapClient' is required."); injectDependence(); } private void injectDependence() { // 获取Context上下文 ApplicationContext ctx = SpringContext.getApplicationContext(); // 按类型获取上下文中的对象 Map<String, SqlMapClientDaoSupport> map = ctx.getBeansOfType(org.springframework.orm.ibatis.support.SqlMapClientDaoSupport.class, true, true); for (Iterator<String> i = map.keySet().iterator(); i.hasNext();) { try { String supportName = (String) i.next(); SqlMapClientDaoSupport support = map.get(supportName); // 后注入依赖 support.setSqlMapClient(sqlMapClient); support.setDataSource(dataSource); } catch (RuntimeException e) { logger.error("SqlMapClientDaoInjector.injectDependence()", e); } } } public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } public void setSqlMapClient(SqlMapClient sqlMapClient) { this.sqlMapClient = sqlMapClient; } private DataSource dataSource; private SqlMapClient sqlMapClient; }
然后加入此类的配置即可,
<bean id="sqlMapClientDaoInjector" class="com.seraph.bi.suite.support.dao.assembly.SqlMapClientDaoInjector"> <property name="dataSource" ref="${jdbc.dataSource}" /> <property name="sqlMapClient" ref="sqlMapClient" /> </bean>
至此我们完成了Spring注释配置的改造。
总结下实现思路,首先是在需要自动加载的类上加入@Repository注释标签,对于需要改变默认类名生成规则的约定,编写实现BeanNameGenerator接口的类,然后对于需要抽象的内置类的配置,自实现后依赖注入的实现。针对此例我们要体会实现的思路,即了解Spring容器的工作原理和设计思想,而后我们可以对其实现有益且有必要的改进工作,但最终都是旨在简化配置,较少没有必要的工作量。
人的懒惰,推进了科技的发展。新年好,祝工作学习愉快!2011年Beijing
评论
对于你们公司的这种特殊需求,对于使用Annotation并无影响,给出我的解决方案,首先你们的配置文件以员工名命名,这个可以使用javadoc,如:
xxx
签上大名后就可以搜索了,同样也可以跟踪
用配置文件,我在可以看一个配置文件就可以了解所有类相关的注入情况,依赖关系直接在配置文件中修改即可,也无需修改类源代码,如果用注释的话,恐怕要进入源代码中修改吧
至于是否能快速的查找到你想要的类,也要看你的包结构设计是否合理,类名是否真实的反应出类的作用,马汀大叔的敏捷一书中也提到好的类名方法名要比代码注释更重要。
Seraph云云
但xml使用起来清晰 易懂 后期维护人员 不要那么蛋疼了。。。
仅有那种规则性的,牵涉到众多类的BEAN值得在XML里写
比较喜欢这样的形式。
呵呵,用了这个所谓的约定,确实感觉编程方便了,如果是做一次性项目,这样做确实省确了不少的时间
我现在的思路:
赞同一次性的小项目这样弄还是不错的
如果是比较庞大的项目(或者是产品有N多现场的项目),错更复杂,明确的bean定义更加整洁清晰(特别是那种多存储、有需要整合重复服务的)
囧,这个太有特色了,难道不测试就提交?有多大可能在配置问题上出错?
即使出错了难道没有svn,hg什么的查历史?
再说起码的实践,版本管理+CI应该有的
最后,用人名这个,我觉得简直是个joke了,太欢乐了
哈哈,的确非常囧,小作坊,必须的
我猜这么做是为了最大限度节省每日集成的时间吧,领导要求这样,我也不多嘴问
推荐持续集成,让CI不厌其烦的执行集成工作,毕竟人的耐心不如冷冰冰的电脑,同时可以单元测试,覆盖率,Checkstyle,代码质量等等
囧,这个太有特色了,难道不测试就提交?有多大可能在配置问题上出错?
即使出错了难道没有svn,hg什么的查历史?
再说起码的实践,版本管理+CI应该有的
最后,用人名这个,我觉得简直是个joke了,太欢乐了
哈哈,的确非常囧,小作坊,必须的
我猜这么做是为了最大限度节省每日集成的时间吧,领导要求这样,我也不多嘴问
对于你们公司的这种特殊需求,对于使用Annotation并无影响,给出我的解决方案,首先你们的配置文件以员工名命名,这个可以使用javadoc,如:
/** * 类说明: 需求A<br> * 创建时间: 2011-1-26 上午10:51:28<br> * * @author 员工007<br> * @email: <br> */
签上大名后就可以搜索了,同样也可以跟踪
囧,这个太有特色了,难道不测试就提交?有多大可能在配置问题上出错?
即使出错了难道没有svn,hg什么的查历史?
再说起码的实践,版本管理+CI应该有的
最后,用人名这个,我觉得简直是个joke了,太欢乐了
-__________-# 离职了、换人维护了,要改名不?
是可以用import的方式拆分,不过也只是解决了大XML文件编辑的问题,但目的并不在于此,而在于去除配置的不便及开发过程的繁琐问题,开发一个MVC三层的应用,要配置三层的类,而类文件本身已说明了自己的用途,何必要在配置文件中配置,还有很多同学的IDE没有类似SpringIDE的插件,这样就更麻烦了,因为你需要自己确认包名类名,不知大家对此可有体会?
不然就像楼主说的
注入dao层 services层多的吓死你
注解只需要2行就解决问题了
<context:component-scan base-package="com.longtop" > <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository" /> </context:component-scan>
发表评论
-
System.getProperty()系统参数
2011-09-21 13:17 1167Properties props=System.ge ... -
jchardet字符编码自动检测工具
2011-04-08 11:25 2053jchardet is a java port of the ... -
Maven中指定得AspectJ依赖无法添加得解决方案
2011-01-30 17:30 8932使用Maven长久以来一直遇到这样得一个问题,就是pom文件中 ... -
Eclipse自动注释模版
2010-12-12 22:00 1071/** * 类说明:<br> ... -
[Spring AOP] 基于AspectJ的@AfterReturning注释示例(附参考书目)
2010-11-19 11:41 20473注释形式的AOP编程,便利的实现了运行时对类及其方法的监控及干 ... -
数据仓库学习网站及图书
2010-09-08 15:28 1531Web Sites Archit ... -
获取中文字符数
2010-06-22 12:03 0private boolean isChineseWo ... -
LoadProperties
2010-06-22 10:36 0import java.io.FileNotFoundE ... -
晒书名:已收藏O'Reilly出版社‘动物世界’系列图书(二)
2010-04-01 15:30 1516书接上回,下所列为后23部经典动物书,书目及图片 ... -
晒书名:已收藏O'Reilly出版社‘动物世界’系列图书(一)
2010-04-01 15:17 4237引言:)子在川上,曾经曰:逝者如斯夫,不舍昼夜。恩,眼一睁一闭 ... -
Log4j异步日志简明配制
2009-11-10 20:15 3795最近搭建一个新的WebService工程,感觉日志系统有些慢, ... -
Mac下的Eclipse3.4反编译插件
2009-09-17 10:26 3436Mac的朋友如最近在使用eclipse3.4以上版本做开发,对 ... -
iBatis的SqlMap简化
2009-09-02 11:54 0啊 -
Jetty嵌入式服务器的JNDI快速配置指南
2009-07-30 15:02 6174J etty提供HTTP服务器、客户端,它是javax ... -
关于系统中使用多个PropertyPlaceholderConfigurer的配置
2009-07-29 11:51 24380多数的鲜为人知方法都是因为有着罕见的应用,就比如说Spring ... -
Abator正式更名为Ibator
2009-06-26 17:57 1048好久没有使用Ibatis了,今天使用Ibatis的生成器Aba ... -
倒排索引,反向索引-Inverted index
2009-05-04 11:17 2296倒排索引(英语:Inverted index),也常被称为 ... -
晒书名:已收藏Manning出版社In Action系列图书
2009-04-22 16:39 4787引言:-) 曾几何时俺还在上海学习、生活、工作,欣赏着外滩的美 ... -
Run to create a run-able Java Package?
2008-10-24 12:33 1174怎样创建一个可运行的Java程序包? Manifest-V ... -
Spring中form绑定找不到commandClass问题的解决
2008-08-11 17:18 4052今天在使用<spring:bind>标签绑定表单中 ...
相关推荐
spring Bean 自动装配(注释)@Atutowired Spring自定义事件(spring自定义事件) 春天@Profile Spring Profile XML 配置 spring-aop 初识spring aop AOP(注解) 弹簧 mvc 1.第一次Spring MVC 2.Spring MVC ...
基于注释(Annotation)的配置有越来越流行的趋势,Spring 2.5 顺应这种趋势,提供了完全基于注释配置 Bean、装配 Bean 的功能,您可以使用基于注释的 Spring IoC 替换原来基于 XML 的配置
第3章高级bean装配 3.1声明父bean和子bean 3.1.1抽象基bean类型 3.1.2抽象共同属性 3.2方法注入 3.2.1基本的方法替换 3.2.2获取器注入 3.3注入非springbean 3.4注册自定义属性编辑器 3.5使用spring的特殊...
第3章 高级Bean装配 3.1 声明父Bean和子Bean 3.1.1 抽象基Bean类型 3.1.2 抽象共同属性 3.2 方法注入 3.2.1 基本的方法替换 3.2.2 获取器注入 3.3 注入非Spring Bean 3.4 注册自定义属性编辑器 3.5 使用...
第3章 高级Bean装配 3.1 声明父Bean和子Bean 3.1.1 抽象基Bean类型 3.1.2 抽象共同属性 3.2 方法注入 3.2.1 基本的方法替换 3.2.2 获取器注入 3.3 注入非Spring Bean 3.4 注册自定义属性编辑器 3.5 使用...
Spring 2.5 引入了 @Autowired 注释,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。 @Autowired 按照类型来装配 改变如下: package com.baobaotao; import org.springframework.beans....
spring中注释 @Resource(按名称进行装配) jar包
基于注释(Annotation)的配置有越来越流行的趋势,Spring 2.5 顺应这种趋势,提供了完全基于注释配置 Bean、装配 Bean 的功能,您可以使用基于注释的 Spring IoC 替换原来基于 XML 的配置。本文通过实例详细讲述了 ...
春天1,HelloSpring IOC创建对象spring1模块2,依赖注入spring2模块3,自动装配spring3模块4,注释spring4模块5,JavaConfig spring5模块
Spring示例Spring 4.2.0(最低Java 7语言级别) 使用兼容的Intellij IDE“友好”注释自动装配。 显示XML配置和带有合格注入的自动装配注入相同类型的不同bean,例如Supplier,并创建注释分类器以选择实现。 这些也...
当单个构造函数自动装配时(从Spring 4.3开始),无需注释构造函数,显示2种语法 @RequestMapping别名: @GetMapping , @PostMapping等。 在IDEA中通过CTRL + F9重新加载(在Mac上为CMD + SHIFT + F9)
spring-annotation-based-autowiring:基于Spring注释的自动装配bean spring-autowiring-constructor:构造函数注入自动装配 spring-bean-definition-override:使用多个Spring配置覆盖bean定义 spring-bean-...
这些视频课程涵盖了Spring Boot的基本概念、配置、自动装配、数据访问、安全性、RESTful API等方面的内容,适合初学者和有经验的开发者学习。这个资源包的主要特点如下:内容丰富:包含多个视频课程,涵盖了Spring ...
3.2.2jsp注释方式 37 3.2.3jsp声明方式 38 3.2.4jsp表达式的应用 39 3.2.5jsp的脚本段 39 3.2.6jsp的编译指令 40 3.2.7jsp的动作指令 41 3.2.8jsp的内置对象 43 3.3认识servlet 46 3.3.1servlet的开发 46 ...
JSP+Servlet+Struts+Hibernate+Spring+Ajax》内容包括Web客户端技术、JSP/Servlet技术、Struts 2(*、类型转换、输入校验、上传和下载文件、Struts 2的各种标签、对 AJAX的支持等)、Spring(Ioc容器、装配Java Bean...
SpringFundamentals_injectionExamples ...带有自动装配示例的 Spring 注释 对于每个项目,我们包括以下示例: 自动装配 成员变量注入(反射) 二传手注入 构造函数注入 范围示例(单例和原型) 属性文件注入
JSP+Servlet+Struts+Hibernate+Spring+Ajax》内容包括Web客户端技术、JSP/Servlet技术、Struts 2(*、类型转换、输入校验、上传和下载文件、Struts 2的各种标签、对 AJAX的支持等)、Spring(Ioc容器、装配Java Bean...