深入浅析java 中的JDK与cglib动态代理
什么是JDK动态代理?
JDK动态代理是Java语言自带的一种动态代理,它可以在运行期间动态生成代理类和代理对象,无需手动编写代理类的Java文件。要使用JDK动态代理,需要目标类实现一个接口,并且需要一个实现InvocationHandler接口的代理类来实现具体的代理逻辑。
以下是一个简单的使用JDK动态代理的例子。假设有一个接口UserService,代理类MyInvocationHandler和目标类UserServiceImpl,我们通过JDK动态代理创建一个代理对象实例。
public interface UserService {
void addUser();
}
public class UserServiceImpl implements UserService {
@Override
public void addUser() {
System.out.println("add user");
}
}
public class MyInvocationHandler implements InvocationHandler {
private Object target;
public MyInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before invoke");
Object result = method.invoke(target, args);
System.out.println("after invoke");
return result;
}
}
public class Test {
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
InvocationHandler invocationHandler = new MyInvocationHandler(userService);
UserService proxy = (UserService) Proxy.newProxyInstance(UserService.class.getClassLoader(), new Class[]{UserService.class}, invocationHandler);
proxy.addUser();
}
}
什么是cglib动态代理?
cglib动态代理是一个利用字节码技术生成代理类的库,它能够代理没有实现接口的类。与JDK动态代理不同的是,cglib动态代理会继承目标类,所以目标类的方法不能被声明为final。
以下是一个简单的使用cglib动态代理的例子。假设有一个目标类UserServiceImpl,我们通过cglib动态代理创建一个代理对象实例。
public class UserServiceImpl {
public void addUser() {
System.out.println("add user");
}
}
public class MyMethodInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("before invoke");
Object result = proxy.invokeSuper(obj, args);
System.out.println("after invoke");
return result;
}
}
public class Test {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(UserServiceImpl.class);
enhancer.setCallback(new MyMethodInterceptor());
UserServiceImpl proxy = (UserServiceImpl) enhancer.create();
proxy.addUser();
}
}
JDK动态代理和cglib动态代理的区别
1. JDK动态代理只能代理实现了接口的目标类,cglib动态代理可以代理没有实现接口的目标类。
public class NoInterfaceClass {
public void myMethod() {
System.out.println("my method");
}
}
public class MyMethodInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("before invoke");
Object result = proxy.invokeSuper(obj, args);
System.out.println("after invoke");
return result;
}
}
public class Test {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(NoInterfaceClass.class);
enhancer.setCallback(new MyMethodInterceptor());
NoInterfaceClass proxy = (NoInterfaceClass) enhancer.create();
proxy.myMethod();
}
}
2. JDK动态代理生成的代理类是目标类实现的接口,cglib动态代理生成的代理类是目标类的子类。
3. JDK动态代理比cglib动态代理速度更快,但JDK动态代理只能代理实现了接口的目标类。
使用场景
JDK动态代理和cglib动态代理在不同的情况下有不同的使用场景。
JDK动态代理适用于需要代理实现了接口的目标类的场景,比如Spring中的AOP。由于JDK动态代理生成的代理类是实现了接口的类,所以它可以和原始类一起直接放入JVM中运行,不需要通过类加载器进行特殊处理,因此JDK动态代理生成的对象运行速度较快。
cglib动态代理适用于需要代理没有实现接口的目标类的场景。cglib动态代理可以为目标类生成一个子类,在子类中拦截目标方法并进行增强。由于cglib动态代理需要生成一个子类,所以它对目标类的访问是通过方法拦截实现的,因此cglib动态代理生成的对象运行速度相对较慢。