Java动态代理技术广泛的应用于我们的项目之中,比如Spring AOP、分布式服务框架等。其主要实现方式有2种,一种是JDK动态代理,一种是cglib动态代理,两种方式各有优劣,本文在此做一个总结。
JDK动态代理
JDK自带的代理机制
实现原理:接口,反射。
运行时根据目标类动态创建代理类,代理类和目标类实现相同的接口。调用方调用代理类,代理类反射调用目标类。
优点:
- 创建代理性能比cglib好
- JDK自带,无需引用第三方包
缺点:
- 需要依赖共同的接口,如果目标类没有实现接口,就无法代理。
- 代理类执行速度较慢
创建代理流程
- 实现InvocationHandler接口,创建自己调用处理器,主要是实现invoke方法。invoke方法负责正真调用目标类的方法。
- 通Proxy.newProxyInstance()创建代理类,需要三个参数:目标类的ClassLoader、Interfaces和InvocationHandler。
实例
package com.javastudy.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @author fangyi.xfy 2016/8/23 11:29.
*/
public class ProxyFactory implements InvocationHandler {
/**
* 目标对象
*/
private Object target;
/**
* 创建代理类
**/
public Object newProxyInstance(Object target){
this.target = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
/**
* 重写调用方法,此处可以织入代码,比如AOP切面
**/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before invoke");
Object res = method.invoke(target, args);
System.out.println("after invoke");
return res;
}
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
ProxyFactory proxyFactory = new ProxyFactory();
UserService proxy = (UserService) proxyFactory.newProxyInstance(userService);
proxy.addUser("Andy");
}
}
cglib动态代理
cglib - Byte Code Generation Library is high level API to generate and transform Java byte code. It is used by AOP, testing, data access frameworks to generate dynamic proxy objects and intercept field access. https://github.com/cglib/cglib/wiki
实现原理:继承,反射。
运行时根据目标类动态创建代理类,代理类是目标类的子类。
优点:
- 执行性能优于JDK动态代理
缺点:
- 由于是继承,无法对final修饰的class代理
- 创建代理类性能较差
创建代理流程
- 实现MethodInterceptor接口,创建自己的方法拦截器,实现intercept方法。
- 通过Enhancer创建目标类的代理,需要目标类的class,MethodInterceptor。
实例
public class CglibProxy implements MethodInterceptor {
private Enhancer enhancer = new Enhancer();
public Object getProxy(Class clazz) {
//设置需要创建子类的类
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
//通过字节码技术动态创建子类实例
return enhancer.create();
}
//实现MethodInterceptor接口方法
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("前置代理");
//通过代理类调用父类中的方法
Object result = proxy.invokeSuper(obj, args);
System.out.println("后置代理");
return result;
}
}