前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >面试Mybatis之代理模式

面试Mybatis之代理模式

作者头像
小土豆Yuki
发布2020-06-15 17:39:12
4450
发布2020-06-15 17:39:12
举报
文章被收录于专栏:洁癖是一只狗洁癖是一只狗

Mybatis之代理模式

由于上一节我们使用了Mybatis的插件(如果忘记了可以看一下历史文章Mybatis拦截器那一节),他是基于代理模式实现的,因此我们在这一节,讲一下代理模式的原理以及实现.

代理模式又分为静态代理和动态代理,动态代理又有两种,一种是jdk动态代理,一种是CGLIB,我们这节只讲其中一种JDK动态代理,先说一下代理模式的作用.

一个类代表另一个类做事情,并且可以做一些额外的事情,在我们工作中经常使用代理模式,比如在不影响现有功能的查询中,我们在查询功能上做一些其他工作,打印执行时间,打印日志等等,代理模式大体意思就是代理对象在发现被监控的对象要执行被监控的行为要执行时,告知通知类,通知类就会拦截被监控对象的行为做一些额外的操作并执行被监控的行为.

照样看我们的是如何使用的,看代码之前介绍几个概念.

这个例子的场景就是,当洁癖老师想要找一个学生时,洁癖老师没有直接去找学生,而是拜托一个班长代理去找,但是班长没有立马去找而是去吃了个饭,吃完之后,再去找学生。

  1. 接口角色:需要监控的行为.(找学生)
  2. 接口实现类:需要被监控的对象.(找学生行为所属对象的具体实现)
  3. 通知类:告知当被监控的对象执行被监控的行为的时候,如何把现有功能(找学生)和额外功能(吃饭)进行绑定.(班长先吃饭在去找学生)
  4. 代理对象:就是班长.

第一步:接口角色(要监控的行为)

代码语言:javascript
复制
  /**
 * 要监控的行为  找学生
 */
public interface BaseExecutorService{

    List<Student> query();
}

第二步:接口的实现类

代码语言:javascript
复制
/**
 * 接口的实现类-->被监控的对象 StudentExecutorServiceImp
 */

public class StudentExecutorServiceImp implements BaseExecutorService {


    @Override
    public List<Student> query() {
        System.out.println("被监控的行为->找学生");
        List list = Arrays.asList(new Student(1,"洁癖",true,"深圳"),new Student(1,"洁癖",true,"深圳"));
        return list;
    }
}

第三步:通知类

代码语言:javascript
复制
package com.jiepi.adviser;

import com.jiepi.service.BaseExecutorService;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;


/**
 * 通知类-->通知被监控的对象要执行的行为做一些其他的业务逻辑
 */
public class Invocation implements InvocationHandler {

    private BaseExecutorService obj; //被监控的对象

    public Invocation(BaseExecutorService obj) {
        this.obj = obj;
    }


    /**
     * 被监控的对象要执行的时候,会被Jvm拦截,被监控的行为query和行为query的参数传入invoke
     * 然后通知类告知JVM,拦截的行为要做些什么样的操作,
     *
     * @param proxy  代理对象
     * @param method 被监控的行为也就是query
     * @param args   被监控的行为的参数 由于行为query没有参数 因此这里为 null
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = null;

        String name = method.getName();
        //根据不同的监控行为做不同的处理
        if (name.equals("query")) { //保证被监控的对象是在找学生,
            eat(); //如果是查询,班长先去吃饭
            result = method.invoke(this.obj, args);//然后再去找学生
        }
        return result;//班长找的学生
    }

    private void eat() {
        System.out.println("被监控的对象执行query的时候(找学生的时候),班长就先吃饭");
    }

}

第四步:代理类

代码语言:javascript
复制
package com.jiepi.util;


import com.jiepi.adviser.Invocation;
import com.jiepi.service.BaseExecutorService;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

/**
 * 代理工厂类
 */
public class ProxyFactory {

    public static BaseExecutorService builder(Class className) throws Exception {

        //被监控的对象
        BaseExecutorService obj = (BaseExecutorService) className.newInstance();
       //通知对象 --绑定要通知那个被监控的对象
        InvocationHandler adviser = new Invocation(obj);
        /**
         * 想Jvm申请监控对象 也就是代理对象
         * load 被监控对象的内存真实地址
         * interfaces 被监控对象的行为的实现接口
         * h 当被监控的对象执行的时候, 要通知哪一个通对象
         */
        BaseExecutorService proxy = (BaseExecutorService) Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), adviser);
        return proxy;
    }

}

第五步:运行结果

代码语言:javascript
复制
    @Test
    public void query() throws Exception {        //proxy其实就是代理,也就是班长
        BaseExecutorService proxy = ProxyFactory.builder(StudentExecutorServiceImp.class);
        List list = proxy.query();//班长去找学生之前,先去吃饭
        list.stream().map(it -> it.toString()).forEach(System.out::println);
    }

运行结果:
被监控的对象执行query的时候(找学生的时候),班长就先吃饭
被监控的行为->找学生
id: 1 name: 洁癖 pass: trueaddress: 深圳
id: 1 name: 洁癖 pass: trueaddress: 深圳

这样我们就把一个简单的代理模式实现了,这就和Mybatsi使用插件进行拦截查询的道理一样,把主要业务和次要业务进行的松耦合,在不影响主要业务的功能进行额外的操作。在Mybatis的mapper接口没有实现类,那他是如何执行对象的sql语句呢?其实他也是利用java的动态代理,去执行相应的sql语句.

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-08-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 洁癖是一只狗 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Mybatis之代理模式
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档