`
wanglihu
  • 浏览: 909416 次
  • 性别: Icon_minigender_1
  • 来自: 黑龙江
社区版块
存档分类

Spring3注释装配的最佳实践

阅读更多
Spring3注释装配的最佳实践


长久以来国内的众多应用都在使用Spring框架,它为我们带来的好处不言而喻。但问题是Spring2.0以下版本尚未支持注释装配,而企业应用大多分作MVC三层结构,每层Bean的配置渐渐膨胀,直到打开了XML文件,IDE不堪重负崩溃为止,情形实为惊人。后有了Convention over Configuration的软件设计范式,即“约定优于配置”,也作“约定编程”。Ruby and Rails和EJB3也都按此实现,Spring注释也基于此。

首先,在解答为什么要使用注释装配之前,先看看没有它时配置文件臃肿的样子,如:持久层DAO的Spring配置文件

Xml代码
<?xml version="1.0" encoding="UTF-8"?>  
<beans ‘略去声明’>  
               
    <bean id="xxDAO" class="com.data.switching.db.dao.impl.XxDAOImpl"  
        parent="sqlMapClientDAO" />  
                           
   
  
略去同样999个配置 ... ...   
使用后的情况:

Xml代码
<?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,实现类如下:

Java代码
import org.springframework.stereotype.Repository;   
...   
  
@Repository  
public class XxDAOImpl extends SqlMapClientDaoSupport implements XxDAO {   
...   
在配置文件中加入:

Xml代码
<context:annotation-config /> 
<context:component-scan base-package="com.db.dao"  
name-generator="com.seraph.bi.suite.support.core.generator.IBatisDaoBeanNameGenerator" />  
因接口名为XxDAO,而实现类名为 XxDAOImpl,引用类中的域名是接口的首字母小写名XxDAO,而容器生成的默认类名是 XxDAOImpl,所以不行,但spring预留了

接口BeanNameGenerator,只要实现它我们就可以自己指定生成bean的名字,这里的实现类如下:

Java代码
/**  
* 类说明: 生成iBatis的DAO的Spring注册名,规则是首字母小写,并去掉后缀名<br>  
* 创建时间: 2011-1-26 下午12:44:20<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"要如何处理呢?

Xml代码
<bean id="scRoleDAO" class="com.dao.impl.XxDAOImpl"  
        parent="sqlMapClientDAO" />  
Xml代码
<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中后注入其依赖。类代码如下:

Java代码
/**  
* 类说明: 向iBatis的DAO中注入依赖<br>  
* 创建时间: 2011-1-26 上午10:51:28<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;   
  
}  
然后加入此类的配置即可,

Xml代码
<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容器的工作原理和设计思想,而后我们可以对其实现有益且有必要的改进工作,但最终都是旨在简化配置,减少没有必要的工作量。

分享到:
评论

相关推荐

    spring-basic:弹簧基础

    spring Bean 自动装配(注释)@Atutowired Spring自定义事件(spring自定义事件) 春天@Profile Spring Profile XML 配置 spring-aop 初识spring aop AOP(注解) 弹簧 mvc 1.第一次Spring MVC 2.Spring MVC ...

    spring注解使用详解

    基于注释(Annotation)的配置有越来越流行的趋势,Spring 2.5 顺应这种趋势,提供了完全基于注释配置 Bean、装配 Bean 的功能,您可以使用基于注释的 Spring IoC 替换原来基于 XML 的配置

    Spring in Action(第2版)中文版

    第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的特殊...

    Spring in Action(第二版 中文高清版).part2

    第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 in Action(第二版 中文高清版).part1

    第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基础

    Spring 2.5 引入了 @Autowired 注释,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。 @Autowired 按照类型来装配 改变如下: package com.baobaotao; import org.springframework.beans....

    annotations-api-6.0.53.jar

    spring中注释 @Resource(按名称进行装配) jar包

    springMVC详解以及注解说明 中文WORD版.rar

    基于注释(Annotation)的配置有越来越流行的趋势,Spring 2.5 顺应这种趋势,提供了完全基于注释配置 Bean、装配 Bean 的功能,您可以使用基于注释的 Spring IoC 替换原来基于 XML 的配置。本文通过实例详细讲述了 ...

    spring

    春天1,HelloSpring IOC创建对象spring1模块2,依赖注入spring2模块3,自动装配spring3模块4,注释spring4模块5,JavaConfig spring5模块

    spring-example01:自动连接兼容的Intellij自定义注释

    Spring示例Spring 4.2.0(最低Java 7语言级别) 使用兼容的Intellij IDE“友好”注释自动装配。 显示XML配置和带有合格注入的自动装配注入相同类型的不同bean,例如Supplier,并创建注释分类器以选择实现。 这些也...

    spring-kotlin-divedive:使用Spring从Java到Kotlin的旅程

    当单个构造函数自动装配时(从Spring 4.3开始),无需注释构造函数,显示2种语法 @RequestMapping别名: @GetMapping , @PostMapping等。 在IDEA中通过CTRL + F9重新加载(在Mac上为CMD + SHIFT + F9)

    EWALectureNotes:幻灯片和讲座笔记Hacettepe大学的企业Web体系结构讲座的笔记

    spring-annotation-based-autowiring:基于Spring注释的自动装配bean spring-autowiring-constructor:构造函数注入自动装配 spring-bean-definition-override:使用多个Spring配置覆盖bean定义 spring-bean-...

    springboot光影视频.zip

    这些视频课程涵盖了Spring Boot的基本概念、配置、自动装配、数据访问、安全性、RESTful API等方面的内容,适合初学者和有经验的开发者学习。这个资源包的主要特点如下:内容丰富:包含多个视频课程,涵盖了Spring ...

    Java Web程序设计教程

    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 ...

    java web技术开发大全(最全最新)

    JSP+Servlet+Struts+Hibernate+Spring+Ajax》内容包括Web客户端技术、JSP/Servlet技术、Struts 2(*、类型转换、输入校验、上传和下载文件、Struts 2的各种标签、对 AJAX的支持等)、Spring(Ioc容器、装配Java Bean...

    SpringFundamentals_injectionExamples

    SpringFundamentals_injectionExamples ...带有自动装配示例的 Spring 注释 对于每个项目,我们包括以下示例: 自动装配 成员变量注入(反射) 二传手注入 构造函数注入 范围示例(单例和原型) 属性文件注入

    java web开发技术大全

    JSP+Servlet+Struts+Hibernate+Spring+Ajax》内容包括Web客户端技术、JSP/Servlet技术、Struts 2(*、类型转换、输入校验、上传和下载文件、Struts 2的各种标签、对 AJAX的支持等)、Spring(Ioc容器、装配Java Bean...

Global site tag (gtag.js) - Google Analytics