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以及执行参数。以及具体错误消息。
  • 相关阅读:
    一步步介绍网页之--> intro.js的使用
    使用 intro.js 使项目介绍更加完美
    完整版中国省市县数据 存储到数据库中
    java 使用openoffice 转换文档,成.pdf,实现在线预览效果
    jsp 页面传多个id 到java后台的处理方式
    CCF推荐国际刊物会议列表2015
    百度ABCOP团队校招提前Offer等你来挑战
    高性能计算中心汇总
    Linux SSH 远程登录后显示-bash-4.1$的解决办法
    Coolpad Y1刷机方法
  • 原文地址:https://www.cnblogs.com/marioS/p/10367289.html
Copyright © 2011-2022 走看看