zoukankan      html  css  js  c++  java
  • SqlSessionTemplate使用SqlSessionFactoryBean实例化之谜(以及xml配置信息迁移到java的方法)

    最近在学习mybatis源码时,发现了一个问题。

    首先,在xml配置文件中配置了SqlSessionTemplate与SqlSessionFactoryBean。

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
      <property name="dataSource" ref="dataSource" />
      <property name="configLocation" value="classpath:${mybatis.config}"/>
      <property name="mapperLocations" value="classpath*:mybatis/mapper.xml"/>
    </bean>
    <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
      <constructor-arg>
        <ref bean="sqlSessionFactory" />
      </constructor-arg>
    </bean>

    看起来,SqlSessionTemplate是使用SqlSessionFactoryBean实例化的。

    然而,查看SqlSessionTemplate的构造方法,发现:

    public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
      this(sqlSessionFactory, sqlSessionFactory.getConfiguration().getDefaultExecutorType());
    }

    SqlSessionTemplate其实是用SqlSessionFactory实例化的!

    可是xml中明明写着这个bean的类型是SqlSessionFactoryBean呀,难道SqlSessionFactoryBean继承或实现了SqlSessionFactory?

    继续查看源码,发现:

    public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent> {
      ......
    }

    总之,SqlSessionFactoryBean并没有继承或实现了SqlSessionFactory。

    这样就奇怪了,类型不匹配的话,SqlSessionTemplate到底是怎么实例化的?

    后来,通过百度发现:

    SqlSessionFactoryBean 实现了 Spring 的 FactoryBean 接口,
    就说明了由 Spring 最终创建的 bean 不是 SqlSessionFactoryBean 本身,
    而是工厂类的 getObject() 返回的方法的结果。
    这种情况下, Spring 将会在应用启动时为你创建 SqlSessionFactory 对象,然后将它以  SqlSessionFactory 为名来存储。

    好吧,这波操作666,本人完全没想到。

    本人猜测,可能是这样实现的(正好举一个xml迁移进java的例子):

    import org.apache.ibatis.session.SqlSessionFactory;
    import org.mybatis.spring.SqlSessionFactoryBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import javax.annotation.Resource;
    import javax.sql.DataSource;
    
    @Configuration
    public class MybatisConfig {
        //从spring容器中获取配置数据源的其它bean对象
        @Resource
        private DataSource dataSource;
        //从spring容器中获取处理好的对象,对应:
        //classpath:${mybatis.config}
        @Resource
        private org.springframework.core.io.Resource configLocation;
        //从spring容器中获取处理好的对象,对应:
        //classpath*:mybatis/mapper.xml
        @Resource
        private org.springframework.core.io.Resource[] mapperLocations;
    
        @Bean(name="sqlSessionFactory")
        public SqlSessionFactory sqlSessionFactoryBeanTosqlSessionFactory() throws Exception {
            SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
            sqlSessionFactoryBean.setDataSource(dataSource);
            sqlSessionFactoryBean.setConfigLocation(configLocation);
            sqlSessionFactoryBean.setMapperLocations(mapperLocations);
            SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBean.getObject();
            //虽然new了SqlSessionFactoryBean,但是返回的是SqlSessionFactory
            return sqlSessionFactory;
        }
    }

    你以为xml中配了class,获得的对象就一定是class指定的对象吗?

    你以为是SqlSessionFactoryBean,其实是我SqlSessionFactory哒!

    不得不说,源码这波操作是真的6……

  • 相关阅读:
    三种方法处理文字中的空格
    text——文本属性大全
    font——文字属性大全
    padding和margin——内边距和外边距
    background——背景属性
    C# 解析excel时,字段内有内容,却读取不到的解决方法
    jqprint 打印分页
    pre标签 首行会自动换行解决方案
    正则表达式 清除所有标签的属性
    针对安卓微信浏览器网页 置顶悬浮框浮动固定 的问题
  • 原文地址:https://www.cnblogs.com/codeToSuccess/p/13906190.html
Copyright © 2011-2022 走看看