zoukankan      html  css  js  c++  java
  • java动态代理

    今天在读mybatis-spring的源码时,看到下面一段代码(红色部分),其中 this.sqlSessionProxy 是SqlSession接口类型 ,通过动态代理的方式产生了实例对象

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

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

            this.sqlSessionFactory = sqlSessionFactory;
            this.executorType = executorType;
            this.exceptionTranslator = exceptionTranslator;
            this.sqlSessionProxy = (SqlSession) Proxy.newProxyInstance(
                    SqlSessionFactory.class.getClassLoader(),
                    new Class[] { SqlSession.class },
                    new SqlSessionInterceptor());
        通过跟踪代码发现其产生的代理实例对象是 org.apache.ibatis.session.defaults.DefaultSqlSession,查看了一下,SqlSession是一个接口,其实现类有好几个,当时很奇怪为什么动态代理这段代码产生的实例类型会是DefaultSqlSession呢,

    经过分析发现,是由Proxy这个动态代码类的
     public static Object newProxyInstance(ClassLoader loader,
           Class<?>[] interfaces,
           InvocationHandler h)     方法中最后一个参数InvocationHandler决定的,创建动态代理对象时必须要传入
    InvocationHandler类型的参数,动态代理对象产生后,对后续调用时,其时调的是InvocationHandler接口实例的
     public Object invoke(Object proxy, Method method, Object[] args)  throws Throwable;方法,通过该方法的传参,可以得到当前要调用的方法参数method,和方法的传参args,下面看一下
     mybatis-spring的代码是如何实现这个InvocationHandler接口的
      private class SqlSessionInterceptor implements InvocationHandler {
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                final SqlSession sqlSession = SqlSessionUtils.getSqlSession(
                        SqlSessionTemplate.this.sqlSessionFactory,
                        SqlSessionTemplate.this.executorType,
                        SqlSessionTemplate.this.exceptionTranslator);
                try {
                    Object result = method.invoke(sqlSession, args);
                    if (!SqlSessionUtils.isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) {
                        sqlSession.commit();
                    }
                    return result;
                } catch (Throwable t) {
                    Throwable unwrapped = ExceptionUtil.unwrapThrowable(t);
                    if (SqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) {
                        unwrapped = SqlSessionTemplate.this.exceptionTranslator.translateExceptionIfPossible((PersistenceException) unwrapped);
                    }
                    throw unwrapped;
                } finally {
                    SqlSessionUtils.closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
                }
            }
        }

  • 相关阅读:
    Java应用中的SQL依赖注入攻击和防范
    强大的 Jquery图表绘制插件 —— jqPlot
    jqPlot的Option配置对象详解
    也谈Java值传递到底传递了什么?
    Use Case 中 include 与 extend 的区别
    STAR UML 简述1
    在Hibernate中使用 HibernateTemplate的三种方法
    jquery ui tabs详解(中文)
    高性能网页开发规则
    如何绘制 UML 活动图(Activity Diagram)
  • 原文地址:https://www.cnblogs.com/hzhuxin/p/2670874.html
Copyright © 2011-2022 走看看