java动态代理主要有JDK和CGLIB两种方式。
- JDK:只能代理接口。
- CGLIB:可以代理类。
传说效率方面,CGLIB比JDK快10倍以上,但是有同学测试,在JDK7以后,JDK在效率上已经大踏步赶上了CGLIB,所以如果是代理接口,直接使用JDK即可,此处只介绍JDK方式。
//接口
public interface User {
void myName();
}
//实现类
public class UserImpl implements User {
@Override
public void myName() {
System.out.println("我的名字叫张三");
}
}
//处理器
public class ProxyInvocationHandler<T> implements InvocationHandler {
private T target;
public ProxyInvocationHandler(T target) {
this.target = target;
}
/**
*
* @param proxy 代理后的实例对象
* @param method 对象被调用的方法
* @param args 调用参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object result = method.invoke(target, args);
after();
return result;
}
//前置处理
public void before() {
System.out.println("我的名字之前...");
}
//后置处理
public void after() {
System.out.println("我的名字之后...");
}
}
//测试类
public class ProxyTest {
public static void main(String[] args) {
User user = new UserImpl();
User userProxy = (User) Proxy.newProxyInstance(user.getClass().getClassLoader(), user.getClass().getInterfaces(), new ProxyInvocationHandler(user));
userProxy.myName();
}
}
测试结果:
我的名字之前...
我的名字叫张三
我的名字之后...
public static Object newProxyInstance(
ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
参数说明:
loader:用哪个类加载器加载代理对象
interfaces:动态代理类需要实现的接口
h:动态代理执行时,会调用h里的invoke方法,我们主要的逻辑都在这个方法里
作为普通程序员,大多时候都在写业务,其实手写动态代理的场景不多,但我们平时用的却非常多,例如经常挂嘴边的AOP就是典型使用场景,SpringBoot中的@Transactional、@Async等都是代理模式。