动态代理
Spring AOP是基于动态代理的,spring默认是使用JDK代理。如果实现了接口就是使用的JDK动态代理,如果没有实现接口那就是cglib动态代理
JDK动态代理
1:通过实现InvocationHandler接口创建调用处理器实现类;
InvocationHandler接口只有一个方法invoke
public Object invoke(Object proxy, Method method, Object[] args)
第一个参数为代理类,第二个参数为被代理的方法,第三个参数为方法的参数数组
2:在invoke方法中method.invoke(subject, args);将需要被代理的接口与参数传入并返回被代理方法的执行结果
3:Subject subject2 = (Subject) Proxy.newProxyInstance(loader, interfaces, handler);通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类
4:通过subject2调用方法就是调用我们定义的InvocationHandlerImpl的 invoke方法
代理接口
package com.itcast;
//需要动态代理的接口
public interface Subject {
public String SayHello(String name);
public String SayGoodBye();
}
代理类
package com.itcast;
//需要被代理的类
public class SubjectImpl implements Subject {
@Override
public String SayHello(String name) {
return "hello " + name;
}
@Override
public String SayGoodBye() {
return "good bye";
}
}
调用处理器实现类
package com.itcast;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class InvocationHandlerImpl implements InvocationHandler {
private Object subject;
public InvocationHandlerImpl(Object subject){
this.subject=subject;
}
// 第一个参数obj一般是指代理类,method是被代理的方法,args为该方法的参数数组
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//在代理真实对象前我们可以添加一些自己的操作
System.out.println("在调用之前,我要干点啥呢?");
System.out.println("Method:" + method);
//当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
// invoke方法会执行指定对象的方法并返回方法执行结果
Object returnValue = method.invoke(subject, args);
//在代理真实对象后我们也可以添加一些自己的操作
System.out.println("在调用之后,我要干点啥呢?");
return returnValue;
}
}
测试
package com.itcast;
import java.lang.reflect.Proxy;
public class Demo {
public static void main(String[] args) {
//获取被代理类对象
Subject subject=new SubjectImpl();
//创建处理器实现类对象,并将代理类对象传入
//处理器实现类,也就是实现了InvocationHandler接口的那个类
InvocationHandlerImpl handler=new InvocationHandlerImpl(subject);
//获取被代理类对象的类加载器
ClassLoader loader = subject.getClass().getClassLoader();
// 获取被代理类对象所实现的接口
Class[] interfaces = subject.getClass().getInterfaces();
// Proxy:该类即为动态代理类
// newProxyInstance返回Proxy代理类的一个实例
Subject subject2 = (Subject) Proxy.newProxyInstance(loader, interfaces, handler);
System.out.println("动态代理对象的类型:"+subject.getClass().getName());
// 调用这个方法就是调用我们定义的InvocationHandlerImpl的 invoke方法
String hello = subject2.SayHello("jiankunking");
System.out.println(hello);
}
}
CGLIB动态代理
若目标对象没有实现任何接口,spring使用CGLIB库生成目标对象的子类。