共计 2458 个字符,预计需要花费 7 分钟才能阅读完成。
1、动态代理概述
代理:本来应该自己做的事情,却请了别人来做,被请的人就是代理对象。
举例:春季回家买票让人代买,租房找中介
动态代理:在程序运行过程中产生的这个对象
如何让程序在运行过程中帮我们动态地产生这个对象呢?可以通过 Java 的反射实现。
为什么要用动态代理
动态代理的目的是在不更改原有对象(目标对象)的基础上实现功能代码的 增强
2、动态代理的种类
(1) JDK 动态代理
(2)CGLIB 动态代理
3、JDK 动态代理
3.1、概述
JDK 的动态代理是 JDK 自带的动态代理技术,所以使用 JDK 动态代理的时候不需要额外引入第三方的 jar 包!
JDK 动态代理是对 对象 本身进行 代理 的一种技术!他是通过 java.lang.reflect 包下提供的一个 Proxy 类的 newProxyInstance 方法 和一个 I nvocationHandler接口来实现动态代理对象的!
但 JDK 提供的代理 只能针对实现接口 的对象做代理!如果要对没有接口实现的类做代理的话就要用 cglib 了。
3.2、实现步骤
需求:给钢铁侠添加火箭助推器
1、创建接口(火箭助推器接口)
public interface Rocket {public void takeOff();
}
2、创建目标对象钢铁侠并实现火箭助推器接口
public class IronMan implements Rocket {@Override
public void takeOff() {System.out.println("i can fly!!!");
}
}
3、创建动态代理启用控制类,该类功能是对方法功能进行增强,该类实现 InvocationHandler 接口
class MyInvocationHandler implements InvocationHandler{// 目标对象
Object obj;
public MyInvocationHandler(Object obj) {super();
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {System.out.println("火箭助推器被增强了");// 增强的功能代码
Object rst = method.invoke(obj, args);// 执行目标对象方法
return rst;
}
}
4、创建目标对象,并通过 Proxy 代理类的 newProxyInstance 方法为其生成代理对象
public static void main(String[] args) {IronMan ir = new IronMan();// 创建目标对象
InvocationHandler h = new MyInvocationHandler(ir);// 将目标对象传入控制器中等待被代理
// 生成代理对象
Rocket proxy = (Rocket) Proxy.newProxyInstance(ir.getClass().getClassLoader(), ir.getClass().getInterfaces(), h);
proxy.takeOff();}
4、CGLIB 动态代理
4.1、概述
cglib:code generator library, 代码生成库,他可以动态的生成字节码对象,可以凭空创建一个字节码对象。
4.2、CGLIB 原理
jdk 代理是对类的对象进行代理,而 CGLIB 代理是通过创建一个目标对象的子类的形式进行代理,也就是 CGLIB 在类的字节码阶段,就已经把增强的代码织入进去了,之后再用增强的字节码对象创建该类的子类对象,从而实现了动态代理,达到代码增强的目的!
所需 Jar 包
- asm-2.2.3.jar
- asm-commons-2.2.3.jar
- asm-util-2.2.3.jar
- cglib-nodep-2.1_3.jar
4.3、CGLIB 动态代理实现步骤
1、生成一个字节码对象 —-> 该对象就是 CGLIB 凭空造出的字节码对象
2、设置字节码对象的父类 —> 该父类就是要增强的目标对象
3、通过生成的子类去增程父类方方法—> 在重写的过程中调用父类的原方法(回调)
4、通过这个生成的字节码对象创建增强对象 –> 再去调用方法,该方法就被增强了
4.4、CGLIB 代码增强演示
1、导包
2、创建目标对象(无序实现接口)
// 目标对象(要增强的类)
public class SuperMan {public void fly(){System.out.println("i can fly!!!");
}
}
3、创建用于回调增强的方法类
public class MyCallback implements MethodInterceptor {/*
* target: 目标对象
* method: 目标对象中的方法
* args: 方法的实参列表
* met: 代理对象中的方法(子类中的方法)*
* */
@Override
public Object intercept(Object target, Method method, Object[] args,
MethodProxy met) throws Throwable {System.out.println("火箭助推器");
return met.invokeSuper(target, args);// 子类中的方法执行
}
}
4、创建子类字节码对象,设置回调,实现增强
public static void main(String[] args) {Enhancer en = new Enhancer();// 凭空创建字节码对象
en.setSuperclass(SuperMan.class);// 设置该字节码对象的父类是 SuperMan
Callback cb = new MyCallback();// 创建用于增强的回调对象
en.setCallback(cb);// 设置子类字节码对象的回调方法
SuperMan sm = (SuperMan) en.create();// 创建代理对象
sm.fly();// 调用代理对象中代理的方法,该方法以被增强
}
运行结果