1. 什么动态代理
动态代理是一种设计模式,是给目标对象提供一个代理对象,并由代理对象控制对目标对象的引用,在不改变目标对象方法的情况下对方法进行增强。Spring框架中的核心功能AOP就是基于动态代理模式,还有mybatis等等。Java中动态代理分为2种,一种是JDK动态代理,一种是CGLIB动态代理
2. 动态代理实现原理
2. 1 JDK动态代理
JDK动态代理是JDK类库自带的代理模式,可以直接使用,但是必须要先定义接口,实现起来略显局限性。代理类与目标类都会实现接口,同时代理类会持有目标类对象并通过拦截方法调用实现功能增强。
public interface UserDao {
void save();
}
public class UserDaoImpl implements UserDao {
public void save() {
System.out.println("save......");
}
}
public class JdkProxy implements InvocationHandler {
private UserDao object;
public JdkProxy(UserDao object) {
this.object = object;
}
public UserDao createProxy() {
return (UserDao) Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ("save".equals(method.getName())) {
System.out.println("校验数据......");
return method.invoke(object, args);
}
return method.invoke(object, args);
}
}
public class ProxyTest {
@Test
public void jdkTest() {
new JdkProxy(new UserDaoImpl()).createProxy().save();
}
}
2. 2 CGLIB动态代理
CGLIB动态代理是针对类来实现代理的,原理是对指定的业务类生成一个子类,并覆盖其中业务方法实现代理。因为采用的是继承,所以不能对final修饰的类进行代理。CGLIB动态代理接口定义不是必须的,且执行速度比JDK原生动态代理速度更快。
public class CustomerDao {
public void save() {
System.out.println("save......");
}
}
public class CGlibProxy implements MethodInterceptor {
public <T> T createProxy(Class<T> tClass) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(tClass);
enhancer.setCallback(this);
return (T) enhancer.create();
}
@Override
public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
if ("save".equals(method.getName())) {
System.out.println("校验数据......");
return methodProxy.invokeSuper(object, args);
}
return methodProxy.invokeSuper(object, args);
}
}
public class ProxyTest {
@Test
public void cglibTest() {
new CGlibProxy().createProxy(CustomerDao.class).save();
}
}