zoukankan      html  css  js  c++  java
  • mybatis的plugin

    1.Mybatis-Plugin的设计思路

    听起来一个挺神奇的单词,插件。说白了就是使用了Jdk自带的动态代理.在需要的时候进行代理。AOP怎么用,他就怎么用。

    Plugin类等价于InvocationHandler.Mybatis在调用Jdk代码如下:

    1 Proxy.newProxyInstance(
    2           type.getClassLoader(),
    3           interfaces,
    4           new Plugin(target, interceptor, signatureMap));

    Plugin类继承InvocationHandler接口

    public class Plugin implements InvocationHandler {
    
      private final Object target;
      private final Interceptor interceptor;
      private final Map<Class<?>, Set<Method>> signatureMap;
    
      private Plugin(Object target, Interceptor interceptor, Map<Class<?>, Set<Method>> signatureMap) {
        this.target = target;
        this.interceptor = interceptor;
        this.signatureMap = signatureMap;
      }
    
      @Override
      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

    invoke方法执行的时候,也就是intercept被调用的时候.

    用一句成语来讲,借鸡下蛋。借尸还魂(这个词还有点吓人)

    2.写一个例子.使用Intecept接口,但不应用在Mybatis框架内。

    思路:① 写一个接口+一个类②写一个Inteceptor对该接口进行增强。

    --------------------接口----------------------------------

    package org.mybatis.example.plugin;
    
    public interface HelloWorld {
    
        void sayHello(Integer v);
    }

    -------------------实现类---------------------------------

    package org.mybatis.example.plugin;
    
    public class HelloWorldImpl implements HelloWorld {
    
        public void sayHello(Integer v){
            System.out.println("Hello World!");
        }
    
        public static void main(String[] args) {
    
            PluginUsedWithoutMyBatis plugin = new PluginUsedWithoutMyBatis();
    
            HelloWorld helloWorld = (HelloWorld) plugin.plugin(new HelloWorldImpl());
    
            helloWorld.sayHello(1);
        }
    }

    --------------------Interceptor-----------------------------------

    @Intercepts(@Signature(type= HelloWorld.class,method="sayHello",args={Integer.class}))
    public class PluginUsedWithoutMyBatis implements Interceptor {
        @Override
        public Object intercept(Invocation invocation) throws Throwable {
    
            String methodName =invocation.getMethod().getName();
    
            Object result =null;
            if(methodName.equals("sayHello")){
    
                System.out.println("method Begin:");
    
                result =invocation.proceed();
                System.out.println("method Begin:");
            }else{
                result =invocation.proceed();
            }
    
            return result;
        }
    
        @Override
        public Object plugin(Object target) {
            return Plugin.wrap(target,this);
        }
    
        @Override
        public void setProperties(Properties properties) {
    
        }
    
        public static void main(String[] args) {
    
        }
    }

    执行HelloWorldImpl中的Main方法,得到一段朴素的代码增强结果。

    method Begin:
    Hello World!
    method Begin:

    PluginUsedWithoutMyBatis类中需要注意的:

    @Intercepts、@Signature这两个注解,限定了可以增强的接口,以及方法名称以及参数。
    理解成过滤器。在Mybatis的Plugins配置中,所有的Plugin都配置在一起。根据Signature决定Interceptor对谁增强。

    问题:

    如果两个Interceptor都对同一个对象增强,结果如何?

    写了另外一个代理类,对HelloWorldImpl进行二次增强,结果如下:

    enhance Second Begin:
    enhance First Begin:
    Hello World!
    enhance First end:
    enhance Second end:

    可以看到两次增强的结果。

    3、回到Mybatis,是否可以对所有的MyBatis接口增强?

    Mybatis的Configruation类,只在几个对象的创建时做了增强

    StatementHandler 、ResultSetHandler 、ParameterHandler 、Executor 
      public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
        StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
        statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
        return statementHandler;
      }
    
        public ResultSetHandler newResultSetHandler(Executor executor, MappedStatement mappedStatement, RowBounds rowBounds, ParameterHandler parameterHandler,
          ResultHandler resultHandler, BoundSql boundSql) {
        ResultSetHandler resultSetHandler = new DefaultResultSetHandler(executor, mappedStatement, parameterHandler, resultHandler, boundSql, rowBounds);
        resultSetHandler = (ResultSetHandler) interceptorChain.pluginAll(resultSetHandler);
        return resultSetHandler;
      }
    
      public ParameterHandler newParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
        ParameterHandler parameterHandler = mappedStatement.getLang().createParameterHandler(mappedStatement, parameterObject, boundSql);
        parameterHandler = (ParameterHandler) interceptorChain.pluginAll(parameterHandler);
        return parameterHandler;
      }
    
      public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
        executorType = executorType == null ? defaultExecutorType : executorType;
        executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
        Executor executor;
        if (ExecutorType.BATCH == executorType) {
          executor = new BatchExecutor(this, transaction);
        } else if (ExecutorType.REUSE == executorType) {
          executor = new ReuseExecutor(this, transaction);
        } else {
          executor = new SimpleExecutor(this, transaction);
        }
        if (cacheEnabled) {
          executor = new CachingExecutor(executor);
        }
        executor = (Executor) interceptorChain.pluginAll(executor);
        return executor;
      }

    4、现有增强插件的实现:

    Executor的query、update时候可以监控sql执行时间。监控慢SQL
    Executor的query、update catch异常,当发生异常时,可以打印sql以及执行参数。以及具体错误消息。
  • 相关阅读:
    HDU 6071
    HDU 6073
    HDU 2124 Repair the Wall(贪心)
    HDU 2037 今年暑假不AC(贪心)
    HDU 1257 最少拦截系统(贪心)
    HDU 1789 Doing Homework again(贪心)
    HDU 1009 FatMouse' Trade(贪心)
    HDU 2216 Game III(BFS)
    HDU 1509 Windows Message Queue(队列)
    HDU 1081 To The Max(动态规划)
  • 原文地址:https://www.cnblogs.com/marioS/p/10367289.html
Copyright © 2011-2022 走看看