MyBatis - 代理

在不改变原有代码情况下,实现对原有代码的增强

案例

张三找律师打官司

静态代理

特点:代理类代码是写死的

优点:在不改变原有代码的情况下实现了对原有业务增强

缺点:一个目标类就需要一个代理类,不便于业务拓展

  1. 定义接口,规定核心业务(代理对象与目标对象做的是一样的事情)

    //规定代理对象与目标对象之间所做的核心业务
    public interface Speak {
        void say();
    }
  2. 编写目标类(实现核心的业务)

    public class 张三类 implements Speak{
        @Override
        public void say() {
            System.out.println("我每天吃一顿饭,挨三顿打。我请求离婚");
        }
    }
  3. 编写代理类(代理目标类--实现对目标的增强)

    public class 律师类 implements Speak {
        // 创建目标类
        private 张三类 张三;    
        public 律师类(张三类 张三) {
            this.张三 = 张三;
        }
        @Override
        public void say() {
            System.out.println("巴拉巴拉...接下来由原告述说");
            张三.say();// 真正做核心业务还是目标对象,代理对象只是在目的对象的基础上增强
        }
    }
  4. 测试

    public static void main(String[] args) {
        张三类 张三 = new 张三类();
        律师类 律师 = new 律师类(张三);
        // 真正的是代理类方法
        律师.say();
    }

动态代理

特点:代理类代码是动态生成

JDK动态代理

特点

  1. 基于接口实现(invocationhandler)

  2. 根据不同目标对象,生成不同代理对象

实现

  1. 定义接口,规定核心业务

    public interface Speak {
        void say();
    }
  2. 编写目标类

    public class 张三类 implements Speak{
        @Override
        public void say() {
            System.out.println("我每天吃一顿饭,挨三顿打。我请求离婚");
        }
    }
  3. 编写JDK动态代理

    public class JDKProxy implements InvocationHandler {
        // 目标对象
        private Object 客户;
        public JDKProxy(Object obj) {
            this.客户 = obj;
        }
        // 增强代码写在invoke方法
        // proxy:代理对象
        // method:待增强的方法(接口中定义的方法)
        // args:待增强方法的参数
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("巴拉巴拉...接下来由原告述说");
            // 用完目标对象方法时可能有返回
            Object result = method.invoke(客户, args);
            return result;
        }
    }
  4. 生成代理对象

    public static void main(String[] args) {
        张三类 张三 = new 张三类();
        // 调用Proxy类的newProxyInstance静态方法生成代理对象
        Speak speak = (Speak) Proxy.newProxyInstance(张三.getClass().getClassLoader(), 张三.getClass().getInterfaces(), new JDKProxy(张三));
        speak.say();
    }

CGLIB动态代理

特点

基于类的继承实现(MethodInterceptor)

需要导包(cglib、asm)

实现

  1. 编写目标对象

    public class 张三类{
        public void say() {
            System.out.println("我每天吃一顿饭,挨三顿打。我请求离婚");
        }
    }
  2. 编写代理类(实现MethodInterceptor)

    public class MyProxy implements MethodInterceptor {
        // 目标对象
        private Object target;
        public MyProxy(Object obj) {
            this.target = obj;
        }
        // intercept:编写增强的代码
        // method:待增强的方法
        // arg:待增强的方法需要的参数
        @Override
        public Object intercept(Object arg0, Method method, Object[] arg2, MethodProxy arg3) throws Throwable {
            System.out.println("巴拉巴拉...接下来由原告述说");
            Object result = method.invoke(target, arg2);//目标对象方法的返回值 如果为void 则为null
            return result;
        }
    }
  3. 获取代理对象

    public static void main(String[] args) {
        张三类 张三 = new 张三类();
        MyProxy myProxy = new MyProxy(张三);
        // 第一个参数:目标对象类型
        // 第二个参数:实现MethodInterceptor类的对象
        张三类 create = (张三类) Enhancer.create(张三.getClass(), myProxy);
        create.say();
    }

注意

代理类中默认将接口所有方法进行增强,若想对指定方法增强可自定义注解打标记,代理类中去判断标记

创建注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface NeedAdd {}

方法中添加注解

public interface Speak {
    @NeedAdd
    void say();
    int cry(int time);
}

根据方法是否存在注解进行使用

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    Object result = null;
    // 判断是否存在注解标记
    if(method.isAnnotationPresent(NeedAdd.class)) { 
        System.out.println("巴拉巴拉...接下来由原告述说");
        // 用完目标对象方法时可能有返回
        result = method.invoke(客户, args);
    }else {
        // 用完目标对象方法时可能有返回
        result = method.invoke(target, args);
    }   
    return result;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值