动态代理的两种实现方式
最近在阅读Spring源码,对于Spring AOP动态代理的两种实现方式--JDK动态代理以及Cglib动态代理的实现又重新回顾了一下。特此记录。
一、JDK动态代理
这是通过java反射机制来实现的,它所对应的类必须有接口。
Jdk动态代理主要有两个重要的地方:
InvocationHandler:每一个动态代理类都需要折现这样一个接口,每一个动态代理类都关联到这样一个 实例。当我们调用方法时候。转而由InvocationHandler.invoke执行相应的操作
Proxy:通过它的方法创建动态代理对象,常用方法就是newProxyInstance,
它三个参数的含义:ClassLoader loader:由哪个ClassLoader对象来对生成的代理对象进行加载
Class<?>[] interfaces:需要被代理的类实现的接口
InvocationHandler h 具体的InvocationHandler实例,通过它执行方法
具体代码:
先写一个接口:
public interface UserService {
public void show();
}
public class UserServiceImpl implements UserService {//接口实现类
@Override
public void show() {
System.out.println("I am a User");
}
}
public class JdkProxy implements InvocationHandler {//继承InvocationHandler并获得实例
private Object object;
public JdkProxy(){
}
public Object getProxy(Object object){
this.object=object;
return Proxy.newProxyInstance(getClass().getClassLoader(),object.getClass().getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理之前执行");
Object result=method.invoke(object,args);
System.out.println("代理之后执行");
return result;
}
}
输出:
代理之前执行
I am a User
代理之后执行
二、通过Cglib技术实现动态代理
Cglib技术底层通过字节码方式实现的动态代理。它与JDk动态代理不同的地方是它不需要一个类实现接口。它是通过动态生成被代理类的子类,当调用被代理类的方法时候,会被子类的方法拦截器拦截然后增强。
MethodInterceptor:方法拦截器,在调用目标方法的时候会调用它的实现类进行拦截。它最重要方法为intercept,进行拦截并执行。
intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy)
o表示被增强后的对象。method表示原始对象的方法,object表示执行方法所需参数,methodProxy表示被增强的方法。
其中,methodProxy需要注意,它有两个方法,invokeSuper(),表示执行超类的对应方法,invoke表示执行当前类的方法,这两者使用不当会造成无限递归调用。
Enhancer:是增强器,它对你想处理的类进行扩展
enhancer.setSuperclass:设置需要增强的类(相当于父类)
enhancer.setCallback:设置回调的拦截器
具体代码:
public class CglibProxy implements MethodInterceptor {
private Enhancer enhancer=new Enhancer();
public Object getProxy(Object object){
enhancer.setSuperclass(object.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("代理之前");
Object result=methodProxy.invokeSuper(o,objects);
System.out.println("代理之后");
return result;
}
@Test
public void test(){
CglibProxy cglibProxy=new CglibProxy();
User user= (User) cglibProxy.getProxy(new User());
user.show();
}
}
输出:
代理之前执行
I am a User
代理之后执行