mybatis插件与spring整合

MyBatis 允许你在映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis 允许使用插件来拦截的方法调用包括:

  • Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
  • ParameterHandler (getParameterObject, setParameters)
  • ResultSetHandler (handleResultSets, handleOutputParameters)
  • StatementHandler (prepare, parameterize, batch, update, query)(最常用的拦截对象)

使用插件

// ExamplePlugin.java
@Intercepts({@Signature(
  type= Executor.class,
  method = "update",
  args = {MappedStatement.class,Object.class})})
public class ExamplePlugin implements Interceptor {
  private Properties properties = new Properties();
  public Object intercept(Invocation invocation) throws Throwable {
    // implement pre processing if need
    Object returnObject = invocation.proceed();
    // implement post processing if need
    return returnObject;
  }
  public void setProperties(Properties properties) {
    this.properties = properties;
  }
}

!-- mybatis-config.xml -->
<plugins>
  <plugin interceptor="org.mybatis.example.ExamplePlugin">
    <property name="someProperty" value="100"/>
  </plugin>
</plugins>

上面的插件将会拦截在 Executor 实例中所有的 “update” 方法调用, 这里的 Executor 是负责执行底层映射语句的内部对象
具体示例可以参考pagehelper插件

MyBatis插件调用流程 

与 Spring 整合分析

几个关键的问题,我们要弄清楚:

1、 SqlSessionFactory 是什么时候创建的?

2、 SqlSession 去哪里了?为什么不用它来 getMapper?

3、 为什么@Autowired 注入一个接口,在使用的时候却变成了代理对象?在 IOC 的容器里面我们注入的是什么? 注入的时候发生了什么事情?

关键配置

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


<bean id="mapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.study.crud.dao"/>
</bean>

1、创建会话工厂

SqlSessionFactoryBean它实现了 InitializingBean 接口,所以要实现 afterPropertiesSet()方法,这个方法 会在 bean 的属性值设置完的时候被调用。 另外它实现了 FactoryBean 接口,所以它初始化的时候,实际上是调用 getObject() 方法,它里面调用的也是 afterPropertiesSet()方法。最后跟下去代码,返 回 了 一 个 DefaultSqlSessionFactory

2、创建 SqlSession

DefaultSqlSession它是线程不安全的。所以使用SqlSessionTemplate

public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType 
                          executorType,PersistenceExceptionTranslator exceptionTranslator) {

    this.sqlSessionFactory = sqlSessionFactory;
    this.executorType = executorType;
    this.exceptionTranslator = exceptionTranslator;
    this.sqlSessionProxy = (SqlSession) newProxyInstance(
        SqlSessionFactory.class.getClassLoader(),
        new Class[] { SqlSession.class },
        new SqlSessionInterceptor());
  }

所有的方法都会先走到内部代理类 SqlSessionInterceptor 的 invoke()方法。MyBatis 它提供了一个 SqlSessionDaoSupport,里面持有一个 SqlSessionTemplate 对象,并且提供了一个 getSqlSession()方法,让我们获得一个 SqlSessionTemplate。然后让dao的实现类继承它,并使用方法操作。(通常和spring结合后不这样用)

3、接口的扫描注册

MapperScannerConfigurer 实现了 BeanDefinitionRegistryPostProcessor 接口,重写 postProcessBeanDefinitionRegistry()方法,在这个方法里面: 调用了scanner.scan()中 调 用 了 processBeanDefinitions在注册 beanDefinitions 的时候,BeanClass 被改为 MapperFactoryBean。MapperFactoryBean 继 承 了 SqlSessionDaoSupport , 可 以 拿 到 SqlSessionTemplate

4、接口注入使用

Spring 会根据 Mapper 的名字从 BeanFactory 中获取它的 BeanDefination,再从 BeanDefination 中 获 取 BeanClass , demoMapper 对 应 的 BeanClass 是 MapperFactoryBean

因为实现了 FactoryBean 接口,同样是调 用 getObject()方法也就是说,我们注入到 Service 层的接口,实际上还是一个 MapperProxy 代理对象。 所以最后调用 Mapper 接口的方法,也是执行 MapperProxy 的 invoke()方法,后面的 流程就跟编程式的工程里面一模一样了

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值