概述
Spring AOP使用两种代理机制,JDK的动态代理便是其中之一,它主要涉及java.lang.reflect包中的两个类:Proxy和InvocationHandler。其中InvocationHandler是一个接口,可以通过实现该接口定义横切逻辑,并通过反射机制调用目标的代码,动态的将横切逻辑和业务逻辑编织在一起。
优点
对方法进行增强,可以在方法前后进行补充。
源码解析
1.通过调用Proxy类的newProxyInstance()方法创建代理对象:
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
参数:
ClassLoader:类加载器。用于加载代理对象的字节码的。和被代理对象使用相同的类加载器。固定写法。
Class[]:字节码数组。用于给代理对象提供方法。和被代理对象具有相同的方法。和被代理对象实现相同的接口,就会具有相同的方法。固定写法
InvocationHanlder:要增强的方法。此处是一个接口,我们需要提供它的实现类。通常写的是匿名内部类(也可编写实现类,这里两种方法都尝试的写一下)。
2. InvocationHandler接口定义invoke方法
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
参数:
proxy:是最终生成的代理实例,一般不会用到。
method:是被代理目标示例的某个具体方法,通过他可以发起目标实例方法的反射调用。
args:是被代理实例某个方法的参数,在方法反射调用时使用。
案例
结构:
Sale接口:
public interface Sale {
public void sale(Float money);
}
Sale接口的实现类:
public class SaleImpl implements Sale {
@Override
public void sale(Float money) {
System.out.println("以"+money+"的价格销售了一件产品");
}
}
InvocationHandler的实现类:
public class InvocationHandlerImpl implements InvocationHandler {
private Sale sale;
//目标类对象
public InvocationHandlerImpl(Sale sale) {
this.sale = sale;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//将目标对象传给method.invoke方法,并调用实例的方法
Object invoke = method.invoke(sale, args);
if ((Float) args[0] > 1500) {
System.out.println("赚了");
} else {
System.out.println("亏了");
}
//没用被调用,不必理会
return invoke;
}
}
测试类:
public class SaleTest {
@Test
//1.通过编写InvocationHandler的实现类
public void testJDK01() {
//创建目标对象
SaleImpl sale01 = new SaleImpl();
//调用Proxy的newProxyInstance方法创建代理对象对象
InvocationHandler invocationHandlerImpl = new InvocationHandlerImpl(sale01);
Sale proxySale = (Sale)Proxy.newProxyInstance(sale01.getClass().getClassLoader(), sale01.getClass().getInterfaces(), invocationHandlerImpl);
proxySale.sale(2000f);
}
@Test
//2.通过编写InvocationHandler匿名内部类
public void testJDK02(){
//创建目标对象
SaleImpl sale01 = new SaleImpl();
//调用Proxy的newProxyInstance方法创建代理对象对象
Sale proxySale = (Sale)Proxy.newProxyInstance(sale01.getClass().getClassLoader(), sale01.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//将目标对象传给method.invoke方法,并调用实例的方法
Object invoke = method.invoke(sale01, args);
if ((Float) args[0] > 1500) {
System.out.println("赚了");
} else {
System.out.println("亏了");
}
//没用被调用,不必理会
return invoke;
}
});
proxySale.sale(2000f);
}
}
输出:
以2000.0的价格销售了一件产品
赚了