组团学

动态代理

阅读 (838437)

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、创建接口(火箭助推器接口)

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、通过这个生成的字节码对象创建增强对象 --> 再去调用方法,该方法就被增强了

image20191220085826462.png

4.4、CGLIB代码增强演示

1、导包

image20191220090211397.png

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();//调用代理对象中代理的方法,该方法以被增强 }

运行结果

image20191220091153546.png

需要 登录 才可以提问哦