JDK的动态代理类是指这样一种class,它是在运行时产生的class,在生成它时,你需要给它们提供一组接口,然后该class宣称它实现了这些接口。也因此你可以将该class的实例当做这些接口的任意实例来使用。当然这些动态代理类本质上还是Proxy,你需要为它指定InvocationHandler,由handler来接管实际的调用。在使用动态代理类时,我们为其实现handler。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
可见主要是来自于jdk的反射包中。
一般涉及到的主要是两个类,也就是上面的InvocationHandler,以及Proxy。
InvocationHandler
这个接口中主要有一个方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
//这里的三个参数,proxy是代理对象target,method是target的方法,args表示target方法的参数列表
Proxy
该类是动态代理类,它的方法如下:
//这是一个构造函数,用于指定InvocationHandler
protected Proxy(InvocationHandler h);
//获取一个代理类,loader就是类加载器,而interfaces则是target类的所有接口的数组
static Class getProxyClass(ClassLoader loader,Class[] interfaces);
以及
//这是用于生成一个代理类实例对象的方法,其参数:loader就是类加载器,而interfaces则是真实类的所有接口的数组。这里返回的代理类可以当做委托类的实例使用。
static Object newProxyInstance(Classloader loader,Class[] interfaces,InvocationHandler h);
动态代理的实现步骤
- 自定义InvocationHandler实现,完成其invoke方法;
- 创建target类及其接口;
- 通过Proxy的newInstanceProxy()方法来创建代理类实例;
- 通过调用代理实例实现目标增强。
示例
目标类接口
public interface MyService {
void doFirst();
void doSecond();
}
接口实现
public class MyServiceImpl implements MyService {
@Override
public void doFirst() {
System.out.println("this is first to do");
}
@Override
public void doSecond() {
System.out.println("this is first to do");
}
}
代理使用匿名类实现InvocationHandler
public class ProxyWork {
public static void main(String[] args){
MyService target=new MyServiceImpl();
MyService proxyService= (MyService) Proxy.newProxyInstance(MyService.class.getClassLoader(), target.getClass().getInterfaces(),
new InvocationHandler() {
//proxy:代理对象
//method:对象方法
//args:对象方法参数列表
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("do advice operation before");
Object result=method.invoke(target,args);
System.out.println("do advice operation after");
return result;
}
});
}
}
在上面的实例中我犯了一个错误,因为目标类的方法是没有返回值得,所以在执行到
Object result=method.invoke(target,args);
时会抛出空指针异常。
参考文献:Java jdk动态代理原理分析