1、动态代理概述
代理:本来应该自己做的事情,却请了别人来做,被请的人就是代理对象。 举例:春季回家买票让人代买,租房找中介 动态代理:在程序运行过程中产生的这个对象 如何让程序在运行过程中帮我们动态地产生这个对象呢?可以通过Java的反射实现。
为什么要用动态代理
动态代理的目的是在不更改原有对象(目标对象)的基础上实现功能代码的增强
2、动态代理的种类
(1) JDK动态代理
(2)CGLIB动态代理
3、JDK动态代理
3.1、概述
JDK的动态代理是JDK自带的动态代理技术,所以使用JDK动态代理的时候不需要额外引入第三方的jar包!
JDK动态代理是对对象本身进行代理的一种技术!他是通过java.lang.reflect包下提供的一个Proxy类的newProxyInstance方法和一个InvocationHandler接口来实现动态代理对象的!
但JDK提供的代理只能针对实现接口的对象做代理!如果要对没有接口实现的类做代理的话就要用cglib了。
3.2、实现步骤
需求:给钢铁侠添加火箭助推器
1、创建接口(火箭助推器接口)
代码语言:javascript复制public interface Rocket {
public void takeOff();
}
2、创建目标对象钢铁侠并实现火箭助推器接口
代码语言:javascript复制public class IronMan implements Rocket {
@Override
public void takeOff() {
System.out.println("i can fly!!!");
}
}
3、创建动态代理启用控制类,该类功能是对方法功能进行增强,该类实现InvocationHandler接口
代码语言:javascript复制 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方法为其生成代理对象
代码语言:javascript复制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、创建目标对象(无序实现接口)
代码语言:javascript复制//目标对象(要增强的类)
public class SuperMan {
public void fly(){
System.out.println("i can fly!!!");
}
}
3、创建用于回调增强的方法类
代码语言:javascript复制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、创建子类字节码对象,设置回调,实现增强
代码语言:javascript复制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();//调用代理对象中代理的方法,该方法以被增强
}
运行结果