不修改源码的情况下,增强方法,在方法执行前后做任何你想做的事
### 什么是动态代理
代理类在程序运行前不存在、运行时由程序动态生成的代理方式称为动态代理。
动态代理好处是在不改变委托类的现有结构的基础上进行方法增强,在方法运行的前后增加方法,可以方便对代理类的函数做统一或特殊处理。
### 一个栗子
#### 首先是一个接口和实现了该接口的委托类。
接口
1 2 3 4 5 public interface Action { void jump(); void run(); void sahuan(); }
委托类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class Dog implements Action { @Override public void jump() { System.out.println("start Jump!"); } @Override public void run() { System.out.println("start Run!"); } @Override public void sahuan() { System.out.println("start sahuan"); } }
#### 实现InvocationHandler的连接类,在委托类方法前加上了判定。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public class DogActionHandler implements InvocationHandler { private Object target; public DogActionHandler(Object o) { this.target = o; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // proxy通过 Proxy.newProxyInstance() 生成的代理类对象 //method表示代理对象被调用的函数。 //args表示代理对象被调用的函数的参数。 if (method.getName().equals("jump")) { System.out.println("dog is out of control!"); } else if (method.getName().equals("run")) { System.out.println("dog crazy!"); } else if (method.getName().equals("sahuan")) { System.out.println("dog is the dog!"); } Object object = method.invoke(target,args); return object; } }
#### Main Test and Output
1 2 3 4 5 6 7 8 9 10 public class Main { public static void main(String[] args) { DogActionHandler handler = new DogActionHandler(new Dog()); Action action = (Action) Proxy.newProxyInstance(Dog.class.getClassLoader(),new Class[]{Action.class},handler); action.jump(); action.run(); action.sahuan(); } }
1 2 3 4 5 6 dog is out of control! start Jump! dog crazy! start Run! dog is the dog! start sahuan
### 动态代理原理
动态代理类是在调用Proxy.newProxyInstance(…)函数时动态生成的,代理类是以$Proxy为类名前缀,继承自Proxy,并且实现了Proxy.newProxyInstance(…)第二个参数传入的所有接口的类。
#### newProxyInstance(…)
其中 h 就是 protected InvocationHandler h;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException { if (h == null) { throw new NullPointerException(); } /* * Look up or generate the designated proxy class. */ Class cl = getProxyClass(loader, interfaces); /* * Invoke its constructor with the designated invocation handler. */ try { Constructor cons = cl.getConstructor(constructorParams); return (Object) cons.newInstance(new Object[] { h }); } catch (NoSuchMethodException e) { throw new InternalError(e.toString()); } catch (IllegalAccessException e) { throw new InternalError(e.toString()); } catch (InstantiationException e) { throw new InternalError(e.toString()); } catch (InvocationTargetException e) { throw new InternalError(e.toString()); } }
中间的生成过程略。