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容器的工作原理和设计思想,而后我们可以对其实现有益且有必要的改进工作,但最终都是旨在简化配置,减少没有必要的工作量。
分享到:
相关推荐
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,控制反转...