为什么SqlMapClientFactoryBean与SqlMapClient类型不同也可被注入

在对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 FactoryBean

Interface to be implemented by objects used within a BeanFactory which are themselves factories. If a bean implements
this interface, it is used as a factory for an object to expose, not directly as a bean instance that will be exposed
itself.

NB: A bean that implements this interface cannot be used as a normal bean. A FactoryBean is defined in a bean style, but
the 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 on
startup. 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 the
JndiObjectFactoryBean. It can be used for application components as well; however, this is not common outside of
infrastructure code.

NOTE: FactoryBean objects participate in the containing BeanFactory's synchronization of bean creation. There is usually
no need for internal synchronization other than for purposes of lazy initialization within the FactoryBean itself (or
the like).

Since:
    08.03.2003
Author:
    Rod Johnson, Juergen Hoeller
See Also:
    BeanFactory, ProxyFactoryBean, JndiObjectFactoryBean





转载于:https://www.cnblogs.com/hibernate3-example/archive/2011/11/13/2492532.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值