`
wanglihu
  • 浏览: 919538 次
  • 性别: 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源码注释中文

    3. **Web**:该模块包含 Spring MVC(模型-视图-控制器)框架,用于构建 Web 应用程序。Spring MVC 提供了一个灵活的架构,支持多种视图技术,如 JSP、FreeMarker 和 Velocity。 4. **AOP(面向切面编程)**:...

    spring 源码中文注释

    这份"spring 源码中文注释"包含了对Spring框架源码的详细解读,对于理解其工作原理、优化代码以及定制化开发具有重要意义。 首先,我们来看看Spring的核心组件——IoC容器。IoC容器是Spring的核心,它负责管理对象...

    spring源码(注释+测试版)

    这份"spring源码(注释+测试版)"提供了Spring框架的源代码,带有注释和测试用例,对于开发者深入理解Spring的工作原理非常有帮助。 1. **spring-core**:这是Spring框架的基础模块,包含了核心的工具类和资源处理...

    spring源码中英文注释

    3. **IoC容器(Inversion of Control, IOC)**:Spring的IoC容器负责管理对象的生命周期和装配。`BeanFactory`和`ApplicationContext`是IoC容器的主要接口。通过这些接口,可以初始化、配置、查找和管理bean。 4. *...

    最全中文注释版Spring4源码

    总的来说,这个"最全中文注释版Spring4源码"是一份宝贵的资源,对于想要提升Java和Spring技术的开发者而言,它提供了深入学习和实践的平台。通过系统地研究源码,我们可以提高对Spring的理解,从而更好地运用它来...

    Spring注释包

    在这个"Spring注释包"中,我们将深入探讨Spring框架如何通过注释来简化开发,提高代码的可读性和可维护性。 首先,让我们了解一下Spring中的核心注解: 1. `@Component`:这是最基础的组件注解,用于标记一个类为...

    spring源码,配套完善的注释

    3. **Bean的生命周期**:Spring中的Bean有多种生命周期状态,包括初始化、活跃、销毁等。开发者可以通过实现接口或使用注解来定制Bean的生命周期行为,如`InitializingBean`和`DisposableBean`,或者使用`@...

    spring-framework-5.0.2.RELEASE-中文注释版-终极完美版.rar

    Spring框架还支持注解驱动开发,如`@Autowired`用于自动装配依赖,`@Service`、`@Repository`和`@Controller`用于组件扫描和类型安全的注入。同时,`@Transactional`用于声明式事务管理,使得开发者可以在不编写事务...

    spring3.x注解

    在 Spring 3.x 中,提供了两种用于属性装配的注解:@Autowired 和 @Resource。 1. @Autowired @Autowired 注解用于自动装配依赖项,默认按照类型匹配的方式(byType)进行注入。可以用于成员变量、setter 方法、...

    Spring基于注释(Annotation)的配置.pdf

    ### Spring基于注释(Annotation)的配置 #### 一、`@Autowired` 注释 `@Autowired` 是Spring框架提供的一种自动装配机制,用于简化Bean的依赖注入过程。该注解可以应用于类成员变量、方法及构造函数,帮助实现按...

    spring-source中文注释版.zip

    3. **Bean**:在Spring中,一个Java对象被称为bean,它是由Spring容器管理的对象。Bean可以通过XML、注解或Java配置进行定义,并且可以被注入到其他bean中。 4. **AOP(面向切面编程)**:Spring的AOP模块提供了在...

    spring-5.0.2中文注释版

    2. **Bean容器**:Spring Bean容器是应用程序的主要入口点,负责创建、配置、管理和装配对象。`ApplicationContext`是主要的Bean容器接口,提供了一系列方法来获取Bean实例和处理应用上下文的事件。 3. **AOP(面向...

    spring-framework-5.2.0.RELEASE-master.zip

    通过阅读`@Autowired`、`@PostConstruct`、`@PreDestroy`等注解的实现,我们可以了解到Spring如何进行自动装配。同时,对于`BeanDefinition`、`BeanPostProcessor`等关键接口的注释,能帮助我们深入理解bean的生命...

    struts2+hibernate+Spring 框架 关于注释用法说明

    3. **Spring注解**: - `@Component`: 基本的组件注解,用于标记为Spring管理的bean。 - `@Service`: 通常用于业务层,是@Component的子注解。 - `@Repository`: 用于数据访问层,处理DAO对象,也是@Component的...

    Maven+spring3.0MVC注释方式开发的Web应用

    在本项目中,我们主要探讨的是基于Maven和Spring 3.0 MVC框架,采用注解方式进行开发的一个Web应用程序,特别地,它还利用了SimpleJdbcTemplate进行数据操作。这个项目是一个基本的CRUD(创建、读取、更新、删除)...

    Spring2.5详细注解.doc

    Spring 2.5 版本引入了基于注释(Annotation)的配置,提供了完全基于注释配置 Bean、装配 Bean 的功能,以替换原来基于 XML 的配置。这种新的配置方式可以充分利用 Java 的反射机制获取类结构信息,减少配置的工作...

    spring API英文版

    3. **Web**:Spring Web模块提供了在Web环境中使用Spring的功能,包括Model-View-Controller(MVC)架构的支持,使得开发RESTful API和Web应用程序变得简单。它还包括WebSocket、Servlet监听器和过滤器等Web相关的...

    spring-basic:弹簧基础

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

    关于spring boot中几种注入方法的一些个人看法

    在 Spring 2.5 引入了 @Autowired 注释,我们平常直接引用的时候很少注意这些,只是自己写好了一个方法或者 springboot 自动配置好的一个方法我们要在另一个类中去调用,这个时候,我们就会采用该注释。 2. @...

    使用 Spring 2_5 注释驱动的 IoC 功能.mht

    **Spring 2.5 注释驱动的 IoC 功能详解** Spring 框架自 2.5 版本开始引入了对注解的强大支持,极大地简化了依赖注入(Dependency Injection,简称 DI)的配置过程。注解驱动的 IoC(Inverse of Control,控制反转...

Global site tag (gtag.js) - Google Analytics