上接:
介绍
cglib是动态在内存中构建一个 子类对象,从而实现对目标对象功能的扩展
Cglib包的底层是通过使用一个小而快的 字节码处理框架 ASM 来转换字节码并生成新的类
不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉
结构
只需要实现 目标类 即可
优点
目标类不需要实现接口
注意
- 目标类不能是
final类
- debug运行时,会产生一些问题,方法前后的代码会执行好几次,而且方法后面的代码会先执行。正常运行时不会发生
生成代理对象的api
Enhancer.create
Object Enhancer.create(Class type, Callback callback)
参数说明:
Class type:设置目标类,在内存中动态生成其子类Callback callback:提供增强的方法,一般为MethodInterceptor接口实现类
MethodInterceptor
方法拦截
MethodInterceptor.intercept(Object o, Method m, Object[] args, MethodProxy mp)
参数说明:
Object o: cglib动态生成的代理类对象Method m::当前执行的方法Object[] args:当前执行的方法的参数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
演员类(目标类)
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运行时,会产生一些问题,方法前后的代码会执行好几次,而且方法后面的代码会先执行。正常运行时不会发生