上篇文章讲解了什么是静态代理,但是静态代理有一个问题就是需要建立很多的代理类,这样我们需要修改代理的方法的时候,需要在每个类中都要修改,这对于我们来说:当代理类很多的时候工作量就会成倍的增加。
于是针对上述问题,人们就提出了解决方案,我们在运行中来实现代理类的创建,也就是今天要讲解的主题——动态代理,首先先说的是JDK自带的动态代理的实现。
JDK自带的代理实现中最重要的两个内容:一是Proxy类,另一个是InvocationHandler接口。这两个是实现动态代理必须要用到的类和接口。
1)对于InvocationHandler接口,API给出了这样的定义:
InvocationHandler
是代理实例的调用处理程序 实现的接口。
每个代理实例都具有一个关联的调用处理程序。对代理实例调用方法时,
将对方法调用进行编码并将其指派到它的调用处理程序的 invoke
方法
Object invoke(Object proxy, Method method, Object[] args) throws Throwable
proxy:指代理的那个真实对象
method:指调用真是对象的某个方法Method对象
args:指调用真实对象某个方法时接受的参数
2)Proxy类:
提供用于创建动态代理类和实例的静态方法,它还是由newProxyInstance方法创建的所有动态代理类的超类。
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
loader:定义代理类的类加载器
interface:代理类要实现的接口列表
h:指派方法调用处理程序
返回值:一个带有代理类的指定调用处理程序的代理实例,它由指定的类加载器定义,并实现指定的接口
也就是(返回一个由类加载器指定的代理类,它具有代理类Proxy中方法)这是我个人的理解
以上已经对于JDK中用到的内容进行了简单的了解,接下来我们来看如何在代码中实现动态代理,
1、定义一个接口
public interface Hello { void say(String name); }
2、定义一个类来实现这个接口,这个类就是我们的真实对象,HelloImpl
public class HelloImpl implements Hello { @Override public void say(String name) { System.out.println("Hello!"+name); } }
3、定义一个动态代理,每个动态代理类都必须实现InvocationHandler这个接口
public class DynamicProxy implements InvocationHandler { private Object target; public DynamicProxy(Object target){ this.target=target; } @SuppressWarnings("unchecked") public <T> T getProxy(){ return (T) Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), this ); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { before(); Object result =method.invoke(target,args); after(); return result; } private void before(){ System.out.println("Before"); } private void after(){ System.out.println("After"); } }
4、接下来就是在客户端调用
public class Test { public static void main(String[] args){ Hello hello =new HelloImpl(); DynamicProxy dynamicProxy = new DynamicProxy(hello); Hello helloProxy=(Hello) Proxy.newProxyInstance( hello.getClass().getClassLoader(), hello.getClass().getInterfaces(), dynamicProxy ); helloProxy.say("Jack"); } }
问题:由于上述在客户端调用过程中,每次动态创建代理类都会使用newProxyInstance这个方法,我们对其进行一层封装,如下:
1、封装一个类,HelloProxy
public class HelloProxy implements Hello { private Hello hello; public HelloProxy(){ hello=new HelloImpl(); } @Override public void say(String name) { before(); hello.say(name); after(); } private void before(){ System.out.println("Before"); } private void after(){ System.out.println("After"); } }
2、客户端调用
public class Test { public static void main(String[] args){ DynamicProxy dynamicProxy=new DynamicProxy(new HelloImpl()); Hello helloProxy =dynamicProxy.getProxy(); helloProxy.say("Jack"); } }