- 浏览: 447678 次
- 性别:
- 来自: 上海
文章分类
最新评论
-
建悦胡:
好文,必须顶
关于系统中使用多个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 1198Properties props=System.ge ... -
jchardet字符编码自动检测工具
2011-04-08 11:25 2087jchardet is a java port of the ... -
Maven中指定得AspectJ依赖无法添加得解决方案
2011-01-30 17:30 9010使用Maven长久以来一直遇到这样得一个问题,就是pom文件中 ... -
Eclipse自动注释模版
2010-12-12 22:00 1100/** * 类说明:<br> ... -
[Spring AOP] 基于AspectJ的@AfterReturning注释示例(附参考书目)
2010-11-19 11:41 20506注释形式的AOP编程,便利的实现了运行时对类及其方法的监控及干 ... -
数据仓库学习网站及图书
2010-09-08 15:28 1560Web 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 1552书接上回,下所列为后23部经典动物书,书目及图片 ... -
晒书名:已收藏O'Reilly出版社‘动物世界’系列图书(一)
2010-04-01 15:17 4283引言:)子在川上,曾经曰:逝者如斯夫,不舍昼夜。恩,眼一睁一闭 ... -
Log4j异步日志简明配制
2009-11-10 20:15 3857最近搭建一个新的WebService工程,感觉日志系统有些慢, ... -
Mac下的Eclipse3.4反编译插件
2009-09-17 10:26 3468Mac的朋友如最近在使用eclipse3.4以上版本做开发,对 ... -
iBatis的SqlMap简化
2009-09-02 11:54 0啊 -
Jetty嵌入式服务器的JNDI快速配置指南
2009-07-30 15:02 6215J etty提供HTTP服务器、客户端,它是javax ... -
关于系统中使用多个PropertyPlaceholderConfigurer的配置
2009-07-29 11:51 24459多数的鲜为人知方法都是因为有着罕见的应用,就比如说Spring ... -
Abator正式更名为Ibator
2009-06-26 17:57 1083好久没有使用Ibatis了,今天使用Ibatis的生成器Aba ... -
倒排索引,反向索引-Inverted index
2009-05-04 11:17 2330倒排索引(英语:Inverted index),也常被称为 ... -
晒书名:已收藏Manning出版社In Action系列图书
2009-04-22 16:39 4845引言:-) 曾几何时俺还在上海学习、生活、工作,欣赏着外滩的美 ... -
Run to create a run-able Java Package?
2008-10-24 12:33 1204怎样创建一个可运行的Java程序包? Manifest-V ... -
Spring中form绑定找不到commandClass问题的解决
2008-08-11 17:18 4089今天在使用<spring:bind>标签绑定表单中 ...
相关推荐
3. **Web**:该模块包含 Spring MVC(模型-视图-控制器)框架,用于构建 Web 应用程序。Spring MVC 提供了一个灵活的架构,支持多种视图技术,如 JSP、FreeMarker 和 Velocity。 4. **AOP(面向切面编程)**:...
这份"spring 源码中文注释"包含了对Spring框架源码的详细解读,对于理解其工作原理、优化代码以及定制化开发具有重要意义。 首先,我们来看看Spring的核心组件——IoC容器。IoC容器是Spring的核心,它负责管理对象...
这份"spring源码(注释+测试版)"提供了Spring框架的源代码,带有注释和测试用例,对于开发者深入理解Spring的工作原理非常有帮助。 1. **spring-core**:这是Spring框架的基础模块,包含了核心的工具类和资源处理...
3. **IoC容器(Inversion of Control, IOC)**:Spring的IoC容器负责管理对象的生命周期和装配。`BeanFactory`和`ApplicationContext`是IoC容器的主要接口。通过这些接口,可以初始化、配置、查找和管理bean。 4. *...
总的来说,这个"最全中文注释版Spring4源码"是一份宝贵的资源,对于想要提升Java和Spring技术的开发者而言,它提供了深入学习和实践的平台。通过系统地研究源码,我们可以提高对Spring的理解,从而更好地运用它来...
在这个"Spring注释包"中,我们将深入探讨Spring框架如何通过注释来简化开发,提高代码的可读性和可维护性。 首先,让我们了解一下Spring中的核心注解: 1. `@Component`:这是最基础的组件注解,用于标记一个类为...
3. **Bean的生命周期**:Spring中的Bean有多种生命周期状态,包括初始化、活跃、销毁等。开发者可以通过实现接口或使用注解来定制Bean的生命周期行为,如`InitializingBean`和`DisposableBean`,或者使用`@...
Spring框架还支持注解驱动开发,如`@Autowired`用于自动装配依赖,`@Service`、`@Repository`和`@Controller`用于组件扫描和类型安全的注入。同时,`@Transactional`用于声明式事务管理,使得开发者可以在不编写事务...
在 Spring 3.x 中,提供了两种用于属性装配的注解:@Autowired 和 @Resource。 1. @Autowired @Autowired 注解用于自动装配依赖项,默认按照类型匹配的方式(byType)进行注入。可以用于成员变量、setter 方法、...
### Spring基于注释(Annotation)的配置 #### 一、`@Autowired` 注释 `@Autowired` 是Spring框架提供的一种自动装配机制,用于简化Bean的依赖注入过程。该注解可以应用于类成员变量、方法及构造函数,帮助实现按...
3. **Bean**:在Spring中,一个Java对象被称为bean,它是由Spring容器管理的对象。Bean可以通过XML、注解或Java配置进行定义,并且可以被注入到其他bean中。 4. **AOP(面向切面编程)**:Spring的AOP模块提供了在...
2. **Bean容器**:Spring Bean容器是应用程序的主要入口点,负责创建、配置、管理和装配对象。`ApplicationContext`是主要的Bean容器接口,提供了一系列方法来获取Bean实例和处理应用上下文的事件。 3. **AOP(面向...
通过阅读`@Autowired`、`@PostConstruct`、`@PreDestroy`等注解的实现,我们可以了解到Spring如何进行自动装配。同时,对于`BeanDefinition`、`BeanPostProcessor`等关键接口的注释,能帮助我们深入理解bean的生命...
3. **Spring注解**: - `@Component`: 基本的组件注解,用于标记为Spring管理的bean。 - `@Service`: 通常用于业务层,是@Component的子注解。 - `@Repository`: 用于数据访问层,处理DAO对象,也是@Component的...
在本项目中,我们主要探讨的是基于Maven和Spring 3.0 MVC框架,采用注解方式进行开发的一个Web应用程序,特别地,它还利用了SimpleJdbcTemplate进行数据操作。这个项目是一个基本的CRUD(创建、读取、更新、删除)...
Spring 2.5 版本引入了基于注释(Annotation)的配置,提供了完全基于注释配置 Bean、装配 Bean 的功能,以替换原来基于 XML 的配置。这种新的配置方式可以充分利用 Java 的反射机制获取类结构信息,减少配置的工作...
3. **Web**:Spring Web模块提供了在Web环境中使用Spring的功能,包括Model-View-Controller(MVC)架构的支持,使得开发RESTful API和Web应用程序变得简单。它还包括WebSocket、Servlet监听器和过滤器等Web相关的...
spring Bean 自动装配(注释)@Atutowired Spring自定义事件(spring自定义事件) 春天@Profile Spring Profile XML 配置 spring-aop 初识spring aop AOP(注解) 弹簧 mvc 1.第一次Spring MVC 2.Spring MVC ...
在 Spring 2.5 引入了 @Autowired 注释,我们平常直接引用的时候很少注意这些,只是自己写好了一个方法或者 springboot 自动配置好的一个方法我们要在另一个类中去调用,这个时候,我们就会采用该注释。 2. @...
**Spring 2.5 注释驱动的 IoC 功能详解** Spring 框架自 2.5 版本开始引入了对注解的强大支持,极大地简化了依赖注入(Dependency Injection,简称 DI)的配置过程。注解驱动的 IoC(Inverse of Control,控制反转...