设计模式-代理模式-cglib动态代理

上接:

  1. 设计模式-代理模式-java

  2. 设计模式-代理模式-JDK动态代理(Proxy.newProxyInstance)

介绍

cglib是动态在内存中构建一个 子类对象,从而实现对目标对象功能的扩展

Cglib包的底层是通过使用一个小而快的 字节码处理框架 ASM 来转换字节码并生成新的类

不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉

结构

只需要实现 目标类 即可

优点

目标类不需要实现接口

注意

  • 目标类不能是 final 类
  • debug运行时,会产生一些问题,方法前后的代码会执行好几次,而且方法后面的代码会先执行。正常运行时不会发生

生成代理对象的api

Enhancer.create

Object Enhancer.create(Class type, Callback callback)

参数说明:

  1. Class type:设置目标类,在内存中动态生成其子类
  2. Callback callback:提供增强的方法,一般为 MethodInterceptor接口实现类

MethodInterceptor

方法拦截

MethodInterceptor.intercept(Object o, Method m, Object[] args, MethodProxy mp)

参数说明:

  1. Object o: cglib动态生成的代理类对象
  2. Method m::当前执行的方法
  3. Object[] args:当前执行的方法的参数
  4. MethodProxy mp:当前执行方法的代理对象。

例子

创建maven工程

略

修改pom.xml

添加依赖:

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>

需要jar包

  • asm-7.1.jar
  • cglib-3.3.0.jar

演员类(目标类)

同 设计模式-代理模式-java

public class Actor {
    public boolean deal(int money, int days) {
        System.out.println(String.format("Actor==收到合约,酬劳:%s万,合约期:%s天",money,days));
        System.out.println("Actor==演戏");
        return true;
    }
}

代理类(经纪人类)

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class CglibProxy {

    static class MethodInterceptorImpl implements MethodInterceptor{
        @Override
        public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
            //取出参数
            Integer money=(Integer) args[0];
            Integer days=(Integer) args[1];
            //代理类可以在目标对象的方法之前,增加额外的代码
            if( money/days<1){
                System.out.println("Agent==每天酬劳低于1万,不合作!");
                return false;
            }
            System.out.println(String.format("Agent==经纪人扣30%%劳务费:%s,实付70%%给演员",money*3/10));
            //代理类可以修改传入目标对象的参数,返回值
            args[0]=money*7/10;
            //调用目标类对象的方法
            Object res = methodProxy.invokeSuper(o, args);
            //代理类可以在目标对象的方法之后,增加额外的代码
            System.out.println("Agent==合作愉快,期待下次合作!");
            return res;
        }
    }
    public static Actor get(){
        Actor actor= (Actor) Enhancer.create(Actor.class, new MethodInterceptorImpl());

        return actor;
    }
}

导演类(主启动类)

public class Director {

    public static void main(String[] args) {

        Actor actor = CglibProxy.get();
        int money=350;
//        int money=280;
        int days=300;
        System.out.println(String.format("Director==谈合作:%s万,%s天,可以吗?",money,days));
        boolean b=actor.deal(money,days);
        if(b) {
            System.out.println("Director==开拍");
        }else{
            System.out.println("Director==演员没谈成,不能开拍");
        }
    }

}

注意: debug运行时,会产生一些问题,方法前后的代码会执行好几次,而且方法后面的代码会先执行。正常运行时不会发生


原文出处:/show_1IX2r18NZ3q.html