动态代理
上篇随笔讲到的静态代理(https://www.cnblogs.com/great-r/p/17758310.html),这篇随笔就讲一讲动态代理吧。
一、动态代理
首先动态代理用来做什么?比如说项目中的其他人开发了某一块功能,你也想要使用此功能,但是可能需求不满足,需要增加点代码对功能做一些增强,这时候就可以使用代理,做到不修改其他人的代码。
动态代理分为了两个主要的实现方式,一个是JDK动态代理,一个是cglib动态代理。那么这两种实现方式有什么区别呢?
1、JDK动态代理
JDK动态代理是基于反射机制实现的,JDK动态代理主要有两个核心类分别是InvocationHandler和Proxy,通过实现InvocationHandler接口,然后重写invoke方法,invoke方法中的主要参数就是(被代理对象、被代理方法名、具体的参数),在invoke方法中去做一个增强方法的过程。然后通过Proxy使用newProxyInstance()方法去创建一个代理类,然后执行代理方法完成动态代理的这么一个过程。
代码示例:
1)创建一个接口
public interface Calculate {
int add(int num1, int num2);
}
2)创建一个委托类(被代理的类),实现接口
public class Calculator implements Calculate {
@Override
public int add(int num1, int num2) {
System.out.println(num1 + "+" + num2 + "=" + num1 + num2);
return num1 + num2;
}
}
3)创建InvocationHandler接口的实现类
public class MyInvocationHandler implements InvocationHandler {
private Object target;
//动态代理,目标对象是活动的,不是固定的,需要传入进来
public MyInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理对象前进行真强活动");
Object invoke = method.invoke(target, args);
System.out.println("代理对象后进行真强活动");
return invoke;
}
}
4)使用newProxyInstance()方法创建代理对象
public class TestProxy {
public static void main(String[] args) {
//创建被代理对象
Calculator calculator = new Calculator();
//创建invocationHandler对象,传入被代理对象
InvocationHandler invocationHandler = new MyInvocationHandler(calculator);
//通过newProxyInstance()方法创建代理对象
Calculate calculate = (Calculate) Proxy.newProxyInstance(calculator.getClass().getClassLoader(), calculator.getClass().getInterfaces(), invocationHandler);
//代理对象执行add方法
calculate.add(2, 3);
}
}
5)运行结果
可以看到JDK动态代理比较关键的一点就是需要实现接口。那我们有些类没有实现接口,然而方法也需要使用到代理这时候怎么办呢?于是就有了cglib动态代理
2、cglib动态代理
cglib动态代理主要的原理就是通过继承目标类,创建它的子类,在子类中重写父类的方法,实现增强活动的这么一个过程。首先类似于JDK动态代理,cglib动态代理也有两个核心类,一个是MethodInterceptor,一个是enhancer类。MethodInterceptor类似于InvocationHandler,它是通过重写intercept方法,在intercept方法内做一个增强活动的过程,enhancer就类似于Proxy类,作用就是创建代理类,它是通过设置父类对象以及回调对象,然后通过enhancer.create()的方法创建代理对象的。
代码示例:
1)创建委托类,实现具体方法
public class SumNumber {
public int add(int num1, int num2) {
System.out.println(num1 + "+" + num2 + "=" + num1 + num2);
return num1 + num2;
}
}
2)创建MethodInterceptor接口的实现类
public class MyMethodInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("代理对象前进行真强活动");
Object o1 = methodProxy.invokeSuper(o, objects);
System.out.println("代理对象后进行真强活动");
return o1;
}
}
3)创建代理类
public static void main(String[] args) {
//创建代理对象
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(SumNumber.class);//设置父类对象
enhancer.setCallback(new MyMethodInterceptor());//设置回调对象,增强类
//通过enhancer.create()方法创建代理对象
SumNumber sumNumber = (SumNumber)enhancer.create();
sumNumber.add(2, 3);
}
4)执行结果