`

为什么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
分享到:
评论
1 楼 tongyitaiwan 2013-08-17  
难怪呢,我正发现这个问题,明白了

相关推荐

    STRUTS+Spring+Ibats

    5. 整合Spring和iBatis:通过Spring的SqlMapClientFactoryBean创建iBatis的SqlMapClient实例,并注入到需要使用数据库操作的Service中。 这样的整合使得系统具有良好的模块化和松耦合特性,方便开发、测试和维护。...

    SPRING IBATIS 保留IBATIS事务的配置方式

    当我们将Spring与iBatis进行整合时,可以充分利用Spring的依赖注入(DI)和面向切面编程(AOP)能力来简化iBatis的配置和使用。其中一种重要的整合方式就是保留iBatis本身的事务管理机制,而不是完全依赖Spring的...

    ibatis与spring整合

    ### ibatis与Spring框架整合详解 #### 一、ibatis简介 ibatis是一个开源的、基于Java的持久层框架,它提供了SQL映射的方式来进行数据库访问。与Hibernate等其他ORM框架相比,ibatis更加轻量级,对于那些只需要简单...

    Spring整合ibatis

    - `sqlMapClient`:注入由Spring创建的SqlMapClient实例。 ##### 5. DAO层设计 DAO层需要继承`SqlMapClientDaoSupport`类或实现相应的接口,以便于使用SqlMapClient。 ```java public class TestDao extends ...

    ibatis spring

    Spring提供了依赖注入(DI)和面向切面编程(AOP)等特性,这些特性有助于提高代码的可测试性和可维护性。 #### 集成iBatis与Spring 将iBatis与Spring框架结合使用,可以充分利用两者的优势。例如,在Spring环境中...

    struts+spring+ibaits配置详解

    这段配置创建了一个名为 `sqlMapClient` 的 Bean,使用的是 Spring ORM 模块提供的 SqlMapClientFactoryBean。该 Bean 负责读取指定路径下的 SQL 映射配置文件(`SqlMapConfig.xml`),并使用之前配置的数据源 `...

    WEB项目-集成Flex3+BlazeDS3.2+Spring2.5.6+iBatis2.3.4

    &lt;bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"&gt; ``` `ibatis.xml`通常包含SQL映射文件的路径。 7. **Spring与iBatis的整合**: 定义`sqlMapClientTemplate`...

    Spring与iBATIS的集成示例代码

    &lt;bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"&gt; &lt;property name="sqlMapClient" ref="sqlMapClient" /&gt; ``` 接着,我们需要创建iBATIS的SQL映射文件(如`...

    ibatis整合spring

    &lt;bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"&gt; &lt;property name="sqlMapClient" ref="sqlMapClient"/&gt; ``` 在这个配置中,`dataSource`定义了数据源,...

    Spring+iBatis整合详解

    在Java企业级应用开发中,Spring框架以其强大的依赖注入(DI)和面向切面编程(AOP)能力深受开发者喜爱,而iBatis(现更名为MyBatis)作为一款优秀的持久层框架,通过SQL映射的方式提供对数据访问的支持,简化了...

    struts2,spring整合及ibatis基础

    - 在 `src` 目录下编写 Spring 配置文件,使用 `SqlMapClientFactoryBean` 完成 SqlMapClient 的定义。 - 注入 `dataSource` 和 iBatis 全局配置文件(无需在此配置文件中指定数据源)。 - 必须将 Spring 框架...

    Spring+Webwork+iBatis 组合实例

    &lt;bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"&gt; ``` 这里创建了一个`SqlMapClient` Bean,它是iBatis的核心组件,用于执行SQL查询。`dataSource`属性引用之前定义...

    Spring+ibatis 保留ibatis事务的配置

    这里设置事务管理器类型为JDBC,表示ibatis将直接使用底层的JDBC连接进行事务控制,而不是使用Spring提供的事务管理器。 ```xml ``` 这种配置方式使得ibatis能够在不依赖Spring事务管理的情况...

    多文件上传

    在Spring中整合MyBatis,需要配置`SqlMapClientFactoryBean`,指定`configLocation`为MyBatis的主配置文件路径,以便Spring管理SQL映射。 ```xml &lt;!-- ibatis sqlMapClient的bean配置 --&gt; &lt;bean id="sqlMapClient...

    ibatis和mybatis的前世今生.txt

    2. **Spring集成配置**:ibatis也可以与Spring框架结合使用,以实现更高效的依赖注入和事务管理。 ```xml &lt;bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"&gt; &lt;value&gt;...

    ibatis+spring完全整合

    在软件开发过程中,将ORM框架(如ibatis)与应用框架(如Spring)进行整合可以极大地提高开发效率和系统的可维护性。本文将详细介绍如何实现ibatis与Spring框架的完全整合,包括数据库配置、实体类设计、DAO层实现、...

    Struts+Spring+Ibatis整合框架搭建文档

    &lt;bean id="SqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"&gt; ``` - **作用**:配置Ibatis的数据源和映射文件,使得可以通过Spring管理Ibatis的实例。 - **配置**:定义一个`...

    图文搭建SSI(struts+spring+ibatis)框架

    &lt;bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"&gt; &lt;value&gt;classpath:SqlMapConfig.xml ``` 7. **配置iBatis文件** 创建`SqlMapConfig.xml`和`sqlMapping....

Global site tag (gtag.js) - Google Analytics