mybaits与spring整合

思考如果需要整合的话,我们mybaits需要做什么事情呢?
1.肯定是要把我们的Mapper文件注入到我们的springIOC容器里面
2.而且还要为我们的Mapper文件的接口创建动态代理对象

我们来看整合需要的配置文件

<!-- sqlSessionFactory 1.spring-mybaits整合-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 加载 MyBatis 的配置文件 -->
        <!--<property name="configLocation" value="SqlMapConfig.xml"/>-->
        <property name="mapperLocations" value="classpath:mapper/*.xml"></property>

        <!-- 数据源 -->
        <property name="dataSource" ref="dataSource"/>
    </bean>
    
      <!-- Mapper 扫描器  2.spring-mybaits整合-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- 扫描 cn.wmyskxz.mapper 包下的组件 -->
        <property name="basePackage" value="com.tx.mapper"/>
    </bean>

我们今天重点来讲第二个:org.mybatis.spring.mapper.MapperScannerConfigurer

查看源码:

dmn整合spring spring整合mybaits_spring整合


实现了:BeanDefinitionRegistryPostProcessor接口

实现postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)方法

:该方法是往spring中的beanDefintionMap里面注册一个bean定义对象

dmn整合spring spring整合mybaits_mbyaits spring_02


DefaultListableBeanFactory:

beanDefinitionMap:中保存了bean的定义信息,spring会根据这些定义的信息,创建具体对应的对象

dmn整合spring spring整合mybaits_sql_03


BeanDefinition

dmn整合spring spring整合mybaits_mybaits与spring_04

ClassPathMapperScanner扫描我们的mapper,添加到beanDefintionMap,修改mapper的beanClass为(我们都知道mapper是接口,不能创建对象,所以我们修改这个bean的class为MapperFactoryBean):

MapperFactoryBean

dmn整合spring spring整合mybaits_dmn整合spring_05


dmn整合spring spring整合mybaits_mbyaits spring_06


MapperFactoryBean:implements FactoryBean接口,这里返回代理对象就是调用sqlsession的getMapper方法,因为这里我们需要SqlSessionFacotory

dmn整合spring spring整合mybaits_sql_07


MapperFactoryBean:继承了SqlSessionDaoSupport,前面修改了注入模型,所以这里会根据set方法来注入SqlSessionFacotry,注意spring的单例池中是有SqlSessionFacotry对象的哈!

dmn整合spring spring整合mybaits_sql_08


至此!!简单的逻辑基本及已经完成!

1.完成了 把mapper加入到IOC容器中!

2.也完成了返回代理对象!

mybaits开发人员太厉害了!!

案例

下面就是我们自己根据前面学到的写一个
首先定义一个类似于扫描的,把我们扫描到的所有mapper文件全部加入到bean定义的map中去,所以这里也要实现spring的接口:BeanDefinitionRegistryPostProcessor

public class SelfDefinetion implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        //向beanDefinitionRegistry 添加一个mapper
        //也可以循环的添加,暂时举一个例子
        BeanDefinitionBuilder builder  = BeanDefinitionBuilder.genericBeanDefinition(SelfMapper.class);
        //获取selfMapper 的bean定义信息
        GenericBeanDefinition beanDefinition = (GenericBeanDefinition) builder.getBeanDefinition();
        //修改mapper的beanClass信息,因为接口是不能创建对象的
        /**
         * 所以
         * 1.这里我们需要一个可以让我们自己返回我们需要的代理类:FactoryBean
         * 2.返回代理对象就需要调用我们的sqlSession的getMapper(),方法返回一个动态代理类:SelfSqlSessionDao
         * 所以这里才继承SelfSqlSessionDao,通过改变注入模型注入sqlSessionFactory,然后在获取sqlSession
         *
         */
        beanDefinition.setBeanClass(SelfFatcoryBean.class); //这里我们把beanClass修改SelfFatcoryBean
        /**
         * 2.1 这里修改注入模型就是为了让我们的SelfSqlSessionDao里面的sqlSessionFactory注入值
         */
        beanDefinition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
        beanDefinitionRegistry.registerBeanDefinition("selfMapper",beanDefinition);
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {

    }

向bean定义的map中加入了mapper的bean定义信息,也修改了beanClass为:
SelfFatcoryBean(接口是不能创建对象的) 所以这里我们要写我们的:SelfFatcoryBean
这里我们知道要完成2件事情:
1.返回自定义代理对象:实现FactoryBean
2.既然要返回代理对象,肯定就要调用我们sqlSession的getMapper()方法,所以肯定要注入我们的SqlsessionFactory,
所以继承:SelfSqlSessionDao

public class SelfFatcoryBean  extends SelfSqlSessionDao implements FactoryBean{

    //这里我们返回一个具体的代理对象。这里我们暂时默认设置为静态代理吧
    @Override
    public Object getObject(){

     // new SelfMapperProxy(); //返回我们定义的self Mapper的静态代理对象
    //升级:改成我们的动态代理  因为下面需要一个动态代理的一个class,所以这里我们要传入一个信息

        System.out.println(this.getSqlSessionFactory()+"验证修改注入模型,是否会注入数据======sqlSession====太厉害 了,真的注入成功了");

        //Proxy.newProxyInstance(UserMapper.class.getClassLoader(),clazz,new SelfInvocation());
        System.out.println(this.getSqlSession()+"sqlSession的值"); //这里创建了session
        return this.getSqlSession().getMapper(SelfMapper.class); //这里mybaits会帮我们创建一个动态代理对象
    }


    @Override
    public Class<?> getObjectType() {
     //   return SelfMapperProxy.class;
        return SelfMapper.class;
    }

所以肯定要注入我们的SqlsessionFactory,前面修改注入模型,就是为了这里能够注入SqlsessionFactory对象,来获取sqlSession对象,调用getMapper()方法!

/**
 * 我们通过改变beanDefineMap里面注入模型,我们查看sqlSessionTemplate是否会注入成功
 */
public class SelfSqlSessionDao {
    private SqlSessionFactory sqlSessionFactory;

    public SqlSession getSqlSession(){
        return new SqlSessionTemplate(sqlSessionFactory);
    }


    public SqlSessionFactory getSqlSessionFactory() {
        return sqlSessionFactory;
    }

    public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
        this.sqlSessionFactory = sqlSessionFactory;
    }


}

在我们的xml文件中配置我们自己的类:

<!-- 自定义的一个-->
    <bean class="com.tx.service.SelfDefinetion"></bean>

测试代码:

public class ApplicationRun {
    public static void main(String[] args) {
       ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");

       //这里其实获取的是 selfMapper的代理对象了
        /**
         * 证实了,我们往beanDefinitionMap里面自已注册一个bean定义,spring会去根据该bean定义创建对应的信息
         */
        SelfMapper selfMapper = (SelfMapper) context.getBean("selfMapper");
        System.out.println(selfMapper.selectUser());
    }
}

测试结果:

dmn整合spring spring整合mybaits_mbyaits spring_09


end!!所以spring的生命周期是真的很重要,mybaits与spring的整合就是完完全全的用到了这些东西,继续加油学习吧!准备看一下spring的事务底层是怎么做的!