1、代理简介
代理分为静态代理和动态代理,静态代理实现简单,动态代理功能更加强大。静态代理是AOP框架会在编译阶段生成AOP代理类,因此称为编译时增强。动态代理是运行时增强,AOP框架不会去修改字节码,而是在内存中临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。
动态代理有两种实现,jdk动态代理和cglib代理:
jdk动态代理的原理是实现被代理接口的实例,拦截定于接口中的目标方法,性能更优,是spring生成代理的优先选择。缺点是只能代理实现了接口的类,没有实现接口的类无法通过JDK动态代理实现。
cglib代理的原理是使用cglib库中的字节码动态生成技术,生成被代理类的子类实例,可以拦截代理类中的任一public方法的调用,无论目标方法是否定义与接口中,更通用,但性能相对jdk代理差一些。
2、JDK动态代理实现
// 动态代理类
public class DynamicProxy implements InvocationHandler {
// 这个就是我们要代理的真实对象
private Object subject;
// 构造方法,给我们要代理的真实对象赋初值
public DynamicProxy(Object subject) {
this.subject = subject;
}
@Override
public Object invoke(Object object, Method method, Object[] args) throws Throwable {
// 在代理真实对象前我们可以添加一些自己的操作
System.out.println("before do sth");
System.out.println("Method:" + method);
// 当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
method.invoke(object, args);
// 在代理真实对象后我们也可以添加一些自己的操作
System.out.println("after do sth");
return null;
}
}
// Client类
public class Client
{
public static void main(String[] args)
{
// 我们要代理的真实对象
Subject realSubject = new RealSubject();
// 我们要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象来调用其方法的
InvocationHandler handler = new DynamicProxy(realSubject);
/*
* 通过Proxy的newProxyInstance方法来创建我们的代理对象,我们来看看其三个参数
* 第一个参数 handler.getClass().getClassLoader() ,我们这里使用handler这个类的ClassLoader对象来加载我们的代理对象
* 第二个参数realSubject.getClass().getInterfaces(),我们这里为代理对象提供的接口是真实对象所实行的接口,表示我要代理的是该真实对象,这样我就能调用这组接口中的方法了
* 第三个参数handler, 我们这里将这个代理对象关联到了上方的 InvocationHandler 这个对象上
*/
Subject subject = (Subject)Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject
.getClass().getInterfaces(), handler);
System.out.println(subject.getClass().getName());
subject.doSth();
}
}
参考资料: