在Java中实现代理的方式主要有两种,一种是静态代理,另一种是动态代理。本文重点主要讲动态代理的方式。
动态代理分为两种:
- jdk动态代理
- cglib动态代理
首先先展示他们的实现代码再进行比较:
jdk动态代理:
要实现的接口:SmsService
public interface SmsService {
String send(String message);
}
实现的类:
public class SmsServiceImpl implements SmsService {
@Override
public String send(String message) {
System.out.println(message);
return message;
}
}
动态代理的核心:
public class JdkProxyFactory {
public static Object getProxy(Object target) {
return Proxy.newProxyInstance(
// 被代理类的类加载器
target.getClass().getClassLoader(),
// 被代理类的实现接口
target.getClass().getInterfaces(),
// 因为要对被代理类进行增强,因此采用handler,在handler中实现增强
new DebugInvocationHandler(target)
);
}
}
自己实现的handler接口:
public class DebugInvocationHandler implements InvocationHandler {
/**
* 代理类中的真实对象
*/
private final Object target;
public DebugInvocationHandler(Object target) {
this.target = target;
}
/**
* proxy :动态生成的代理类
* method : 与代理类对象调用的方法相对应
* args : 当前 method 方法的参数
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//调用方法之前,我们可以添加自己的操作
System.out.println("before method " + method.getName());
Object result = method.invoke(target, args);
//调用方法之后,我们同样可以添加自己的操作
System.out.println("after method " + method.getName());
return result;
}
}
以上就是JDK动态代理的全部代码,接下来我们看cglib的代码。
cglib的动态代理:
要代理的类:
public class AliSmsService {
public String send(String message) {
System.out.println("send message:" + message);
return message;
}
}
cglib的核心:
public class CglibProxyFactory {
public static Object getProxy(Class<?> clazz) {
// 创建动态代理增强类
Enhancer enhancer = new Enhancer();
// 设置类加载器
enhancer.setClassLoader(clazz.getClassLoader());
// 设置被代理类
enhancer.setSuperclass(clazz);
// 设置方法拦截器
enhancer.setCallback(new DebugMethodInterceptor());
// 创建代理类
return enhancer.create();
}
}
接下来我们去执行增强方法:
/**
* 自定义MethodInterceptor
*/
public class DebugMethodInterceptor implements MethodInterceptor {
/**
* @param o 代理对象(增强的对象)
* @param method 被拦截的方法(需要增强的方法)
* @param args 方法入参
* @param methodProxy 用于调用原始方法
*/
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
//调用方法之前,我们可以添加自己的操作
System.out.println("before method " + method.getName());
Object object = methodProxy.invokeSuper(o, args);
//调用方法之后,我们同样可以添加自己的操作
System.out.println("after method " + method.getName());
return object;
}
}
由此可见,jdk的动态代理和cglib的动态代理的区别就很明显了:
JDK代理是不需要依赖第三方的库,只要JDK环境就可以进行代理,需要满足以下要求:
1.实现InvocationHandler接口,重写invoke()
2.使用Proxy.newProxyInstance()产生代理对象
3.被代理的对象必须要实现接口
CGLib 必须依赖于CGLib的类库,需要满足以下要求:
1.实现MethodInterceptor接口,重写intercept()
2.使用Enhancer对象.create()产生代理对象
本文到此结束,如有不对,欢迎指正。
参考博客:http://t.csdn.cn/mUKWx