简单记录一下见到过的AOP在框架中的使用记录,一直更新。

  1. Bean声明周期中三级缓存时使用

  2. spring事物上

  3. 自定义Aspectj切面

  4. mybatis的mapper接口会生成代理对象

  5. mybatis的plugin会生成代理对象

  6. Mybatis的Mapper在注解扫描到实例化MapperFactoryBean时在父类SqlSessionDaoSupport中初始化sqlSessionTemplate. 在SqlSessionTemplate构造方法中创建具体执行的sqlsession代理对象属性叫sqlSessionProxy.

/**
   * 方法实现说明:真正会调该构造方法进行赋值初始化
   *
   * @author:xsls
   * @param sqlSessionFactory:工厂对象
   * @param executorType:执行器类型
   * @param exceptionTranslator:异常翻译器对象(MyBatisExceptionTranslator)
   * @return:
   * @exception:
   * @date:2019/9/8 19:49
   */
  public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType,
      PersistenceExceptionTranslator exceptionTranslator) {

    notNull(sqlSessionFactory, "Property 'sqlSessionFactory' is required");
    notNull(executorType, "Property 'executorType' is required");

    this.sqlSessionFactory = sqlSessionFactory;
    this.executorType = executorType;
    this.exceptionTranslator = exceptionTranslator;
    /**
     * sqlSession代理对象 来调用我们的目标方法
     */
    this.sqlSessionProxy = (SqlSession) newProxyInstance(SqlSessionFactory.class.getClassLoader(),
        new Class[] { SqlSession.class }, new SqlSessionInterceptor());
  }

private class SqlSessionInterceptor implements InvocationHandler {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      /**
       * 尝试从事务的线程变量中获取session,若没有获取到就直接新开一个session, 所以加事务可以缓存我们的sqlSession(也就是我们的SqlSessionTemplate对象)
       */
      SqlSession sqlSession = getSqlSession(SqlSessionTemplate.this.sqlSessionFactory,
          SqlSessionTemplate.this.executorType, SqlSessionTemplate.this.exceptionTranslator);
      try {
        /**
         * 调用我们的目标方法代理的就是我们的session接口的方法 因为上一步返回的session是我们DefaultSqlSession对象, 所以在这里直接调用到我们的DefaultSqlSession的方法中
         */
        Object result = method.invoke(sqlSession, args);
        if (!isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) {
          // force commit even on non-dirty sessions because some databases require
          // a commit/rollback before calling close()
          /**
           * 提交我们的session
           */
          sqlSession.commit(true);
        }
        return result;
      } catch (Throwable t) {
        Throwable unwrapped = unwrapThrowable(t);
        if (SqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) {
          // release the connection to avoid a deadlock if the translator is no loaded. See issue #22
          /**
           * 抛异常 关闭我们的session
           */
          closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
          sqlSession = null;
          Throwable translated = SqlSessionTemplate.this.exceptionTranslator
              .translateExceptionIfPossible((PersistenceException) unwrapped);
          if (translated != null) {
            unwrapped = translated;
          }
        }
        throw unwrapped;
      } finally {
        if (sqlSession != null) {
          closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
        }
      }
    }
  }

/**
   * 方法实现说明:获取我们的session对象
   * 
   * @author:xsls
   * @param sessionFactory:session工厂对象
   * @param executorType:执行器类型
   * @param exceptionTranslator
   *          :异常分析器
   * @exception:
   * @date:2019/9/8 21:21
   */
  public static SqlSession getSqlSession(SqlSessionFactory sessionFactory, ExecutorType executorType,
      PersistenceExceptionTranslator exceptionTranslator) {

    notNull(sessionFactory, NO_SQL_SESSION_FACTORY_SPECIFIED);
    notNull(executorType, NO_EXECUTOR_TYPE_SPECIFIED);
    /**
     * 首先就去我们事务同步管理器对象中获取我们的sessionHolder
     */
    SqlSessionHolder holder = (SqlSessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);

    /**
     * 从事务管理器中获取我们的sqlSession对象
     */
    SqlSession session = sessionHolder(executorType, holder);
    // session不为空直接返回
    if (session != null) {
      return session;
    }

    LOGGER.debug(() -> "Creating a new SqlSession");
    /**
     * 新开一个session
     */
    session = sessionFactory.openSession(executorType);

    /**
     * 把我们的session绑定到事务线程变量中
     */
    registerSessionHolder(sessionFactory, executorType, exceptionTranslator, session);

    return session;
  }

文章作者: 刘同学
本文链接:
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 刘同学的小站
编码大杂烩 Java SpringBoot
喜欢就支持一下吧