Java代理笔记
代理顾名思义,就是一个中间层,当我们要使用某个方法时,不直接调用,而是告诉代理,让代理替我们去请求方法,并返回结果。在这个过程中,我们只知道代理执行并返回给了我们操作结果,至于它有没有其他操作并不知道,但这个也无关紧要,因为不管代理在请求实际方法之前和之后做了什么,对我们都不会产生任何影响。由于代理的这个特性,可以用来进行记录日志等操作。
代理分为静态代理和动态代理。
静态代理
静态代理需要我们在调用者和具体的执行者之间创建一个代理类,其实现需要被代理的接口并持有一个此接口,具体代码如下:
接口类(被代理):
public interface Hello { void say(String name); }
代理类:
public class HelloProxy implements Hello { private Hello helloImpl; public HelloProxy() { this.helloImpl = new HelloImpl(); // HelloImpl为一个Hello接口的一个普通实现类 } @Override public void say(String name) { System.out.println("before say"); helloImpl.say(name); System.out.println("after say"); } }
使用的时候只需要new一个代理类赋值给接口即可:Hello hello = new HelloProxy()
,之后的执行会由代理类去负责。但是这么做有一个问题就是对每个需要代理的类,都需要创建一个对应的代理类,即使代理类的逻辑都是相似的,动态代理就是解决这个问题的。
动态代理
动态代理相当于在调用者和代理类之间又增加了一个中间层,在这个中间层中完成代理类的逻辑,达到复用代码的效果。这个中间层需要实现InvocationHandler
接口,并持有一个被代理的类,大致代码如下:
public class Myproxy implements InvocationHandler { private Object target; // 被代理的类 public Myproxy(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("before invoke"); // 执行代理的方法前进行的操作 Object invoke = method.invoke(target, args); // 调用执行被代理的方法 System.out.println("after invoke"); // 执行代理的方法后进行的操作 return invoke; // 返回方法执行结果 } }
使用时,使用Proxy的静态方法获取代理类,将其强转为对应的接口,之后可以同静态代理类同样使用。
Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
其中loader为类加载器,interfaces为要代理的接口,h为之前定义的实现InvocationHandler
接口的类的实例。
这个方法会返回一个代理类,其实现的要代理的接口,并持有一个实现InvocationHandler
接口的实例,代理类的代码大致如下:
public final class $Proxy0 extends Proxy implements Hello { public $Proxy0(InvocationHandler paramInvocationHandler) { super(paramInvocationHandler); } public final String say() { try { return ((String)this.h.invoke(this, m3, null)); } catch (RuntimeException localRuntimeException) { throw localRuntimeException; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } } }
如上代码我们可以将其强转为Hello接口,实际调用的时候会调用InvocationHandler
实现类中的invoke
方法,而其中就是我们实现的代理业务,当然,也包括实际的业务。