1. 什么是动态代理
动态代理利用Java的反射技术(Java Reflection)生成字节码,在运行时创建一个实现某些给定接口的新类(也称"动态代理类")及其实例。
2. 动态代理的优势
动态代理的优势是实现无侵入式的代码扩展,也就是方法的增强;让你可以在不用修改源码的情况下,增强一些方法;在方法的前后你可以做你任何想做的事情(甚至不去执行这个方法就可以)
spring中的AOP是动态代理使用的经典场景。
3. 基于JDK动态代理实现
在基于JDK的动态代理的实现中有两个重要的类:InvocationHandler, Proxy
InvocationHandler
是代理实例的调用处理程序实现的接口。每个代理实例都具有一个关联的调用处理程序。对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的 invoke 方法。
Proxy
JDK中动态生成代理类的工具类
一个动态代理的示例:
定义一个接口(基于JDK的动态代理只能使用接口)
public interface ISubject {
void hello(String param);
}
为接口定义实现类
public class SubjectImpl implements ISubject {
@Override
public void hello(String param) {
System.out.println("hello " + param);
}
}
实现一个代理类:
public class JDKProxy implements InvocationHandler {
private Object target;
public JDKProxy(Object target) {
this.target = target;
}
//创建代理
public Object newProxy() {
return (ISubject)Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("---------- 在业务方法调用之前可以进行前置增强 ------------");
//利用反射机制调用方法,invoke为返回值,如果没有返回null
Object invoke = method.invoke(target, args);
System.out.println("---------- 在业务方法调用之前可以进行后置增强 ------------");
return invoke;
}
}
编写代理类实际的调用,利用Proxy类创建代理之后的Subject类
public class JDKProxyDemo {
public static void main(String[] args) {
ISubject subject = new SubjectImpl();
JDKProxy subjectProxy = new JDKProxy(subject);
ISubject proxyInstance = (ISubject)subjectProxy.newProxy();
proxyInstance.hello("world");
}
}
运行结果:
---------- 在业务方法调用之前可以进行前置增强 ------------
hello world
---------- 在业务方法调用之前可以进行后置增强 ------------