为什么SqlMapClientFactoryBean与SqlMapClient类型不同也可被注入
来源:互联网 发布:武汉大数据培训班 编辑:程序博客网 时间:2024/05/21 15:48
在对spring和ibatis进行整合时,大家都会用到如下的配置以在ibatis中使用spring提供的事务处理功能。
<beans>
......
<!-- 配置相关数据源 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<! -- 此处省略数据库属性配置-->
</bean>
<!-- Transaction manager for a single JDBC DataSource事务管理的定义-->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- Spring提供的iBatis的SqlMap配置-->
<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="configLocation" value="WEB-INF/sql-map-config.xml"/>
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- DAO定义-->
<bean id="productDao"class="com.specl.api.dao.release.ShopDaoRelease">
<property name="sqlMapClient" ref="sqlMapClient"/>
</bean>
...
</beans>
在上面的配置片段中可以,类ShopDaoRelease是我们具体的一个dao实现,其继承了SqlMapClientDaoSupport,后者暴露出一个sqlMapClient属性,用于接受Spring的注射。SqlMapClientDaoSupport会对其中封装的SqlMapClientTemplate做相应的设置,所以DAO子类便可在取用SqlMapClientTemplate时正常地工作了。
但是我们可以通过查看源码发现在SqlMapClientDaoSupport类中,关于setSqlMapClient方法的定义:
/** * Set the iBATIS Database Layer SqlMapClient to work with. * Either this or a "sqlMapClientTemplate" is required. * @see #setSqlMapClientTemplate */ public final void setSqlMapClient(SqlMapClient sqlMapClient) { if (!this.externalTemplate) { this.sqlMapClientTemplate.setSqlMapClient(sqlMapClient); } }
而我们的配置文件中名字为“sqlMapClient”的bean的类型却为org.springframework.orm.ibatis.SqlMapClientFactoryBean,而非为com.ibatis.sqlmap.client.SqlMapClient。这不免让人产生疑问,怎么能把org.springframework.orm.ibatis.SqlMapClientFactoryBean类型的实例注入给com.ibatis.sqlmap.client.SqlMapClient类型的属性呢?这是因为Spring的机制的缘故。简单的说,如果一个bean实现了 FactoryBean接口,那么Spring就不会把该bean本身实例化并返回,而是返回该bean的getObject()返回的对象。这是Sprign的游戏规则。我们来看一眼 SqlMapClientFactoryBean的源码片段:
public class SqlMapClientFactoryBean implements FactoryBean,InitializingBean { private SqlMapClient sqlMapClient; protected SqlMapClient buildSqlMapClient(Resource configLocation,Properties properties) throws IOException { InputStream is = configLocation.getInputStream(); if (properties != null) { if (buildSqlMapClientWithInputStreamAndPropertiesMethodAvailable) { return SqlMapClientBuilder.buildSqlMapClient(is,properties); } else { return SqlMapClientBuilder.buildSqlMapClient(new InputStreamReader(is), properties); } } else { if (buildSqlMapClientWithInputStreamMethodAvailable) { return SqlMapClientBuilder.buildSqlMapClient(is); } else { return SqlMapClientBuilder.buildSqlMapClient(new InputStreamReader(is)); } } } //这里就是返回的、并会被注入到其它类里的对象 public Object getObject() { return this.sqlMapClient; }}
Spring这种机制的官方说明:
public interface FactoryBeanInterface to be implemented by objects used within a BeanFactory which are themselves factories. If a bean implementsthis interface, it is used as a factory for an object to expose, not directly as a bean instance that will be exposeditself.NB: A bean that implements this interface cannot be used as a normal bean. A FactoryBean is defined in a bean style, butthe object exposed for bean references (getObject() is always the object that it creates.FactoryBeans can support singletons and prototypes, and can either create objects lazily on demand or eagerly onstartup. The SmartFactoryBean interface allows for exposing more fine-grained behavioral metadata.This interface is heavily used within the framework itself, for example for the AOP ProxyFactoryBean or theJndiObjectFactoryBean. It can be used for application components as well; however, this is not common outside ofinfrastructure code.NOTE: FactoryBean objects participate in the containing BeanFactory's synchronization of bean creation. There is usuallyno need for internal synchronization other than for purposes of lazy initialization within the FactoryBean itself (orthe like).Since: 08.03.2003Author: Rod Johnson, Juergen HoellerSee Also: BeanFactory, ProxyFactoryBean, JndiObjectFactoryBean
- 为什么SqlMapClientFactoryBean与SqlMapClient类型不同也可被注入
- SqlMapClientFactoryBean为什么能转为SqlMapClient
- SqlMapClientTemplate与SqlMapClient
- Ibatis,Spring注解方式注入sqlMapClient
- Ibatis,Spring注解方式注入sqlMapClient
- ibatis中SqlMapClientTemplate与SqlMapClient的区别
- 【ibatis】SqlMapClient.insert返回值与selectKey
- C# 值类型与类的不同
- sqlMapClientFactoryBean的简单介绍
- SqlMapClientFactoryBean的理解
- 指针大小为什么与类型无关
- 指针大小为什么与类型无关?
- 编译时类型与运行时类型不同
- baseservice 中按继承的类型来注入不同的dao
- 美国的孩子为什么与中国的不同
- 为什么object_getClass(obj)与[OBJ class]返回的指针不同
- 为什么深度学习与机器学习完全不同?
- spring注入时bean的set方法为什么不能是static类型的?
- java基础笔记
- DataTable 的用法
- 成员函数、虚函数、this指针
- 乐趣是什么--《全景探秘游戏设计艺术》笔记
- dip,dpi,sp,density官方解答
- 为什么SqlMapClientFactoryBean与SqlMapClient类型不同也可被注入
- 1.4、单例模式
- iOS5新特性:Core Image 图片处理的强力框架
- 常用16种视图切换动画
- 第一章、左旋转字符串
- Socket 编程 windows到Linux代码移植遇到的问题
- 大家好 ,
- JAVASCRIPT正则中的RegExp.$1
- 深入理解C语言指针的奥秘