代理的最大作用,就是在已知源代码的情况下,在不改变原来代码的条件下,增加自己的逻辑。
比如说控制权限,增加日志等。此例就以增加日志来说明动态代码的基本用法。
JDK的动态代码必须要基于接口,所以被代理的对象必须要实现某一个或多个接口。
1.接口
有一个动物接口,有两个方法吃和睡。很简单吧
interface Animal { void eat(); void sleep(); }
cat类,实现了animal接口
class Cat implements Animal { @Override public void eat() { // TODO Auto-generated method stub System.out.println("cat eating..."); } @Override public void sleep() { // TODO Auto-generated method stub System.out.println("cat sleeping..."); } }
现在有一个需求,系统要求在每一个方法执行和结束时都加上日志,简单点就是加上下面两句话:
System.out.println(new Date() + " xxx 方法开始执行!"); xxx方法执行中。。 System.out.println(new Date() + "xxx 方法结束!");
最简单的就是在每个方法中前后都加上这样一段代码,但是方法很多时显然是不现实的。或者是当你手里头没有方法的源代码时,也无法实现。
这是就用得上动态代理了。
3.处理方法,我们的处理逻辑
</pre><p></p><p></p><pre name="code" class="java">import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Date; class LogMethodHander implements InvocationHandler { //即将被代理的对象 private Object target; public LogMethodHander(Object target) { super(); this.target = target; } //创建代理对象的函数,即用此函数产生代理target的对象 public Object newProxy(Object obj) { return Proxy.newProxyInstance(getClass().getClassLoader(), getClass() .getInterfaces(), this); } //在这里加上我们自己的逻辑 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub System.out.println(new Date() + " : " + method.getName() + " 方法开始执行!"); //真实方法执行 method.invoke(targer, args); System.out.println(new Date() + " : " + method.getName() + " 方法结束!"); return null; } }
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Date; public class DynamicProxyTest { public static void main(String[] args) { //真实类 Animal cat = new Cat(); //处理函数,创建代理所用 LogMethodHander handler = new LogMethodHander(cat); //代理类,其中用上面的处理函数做了一个参数 Object proxy = Proxy.newProxyInstance(cat.getClass().getClassLoader(), cat.getClass().getInterfaces(), handler); if(proxy instanceof Animal){ Animal animalProxy = (Animal) proxy; animalProxy.eat(); animalProxy.sleep(); } } }
5.运行结果:
LOG: Sun Aug 03 21:14:38 CST 2014 : eat 方法开始执行! cat eating... LOG: Sun Aug 03 21:14:38 CST 2014 : eat 方法结束! LOG: Sun Aug 03 21:14:38 CST 2014 : sleep 方法开始执行! cat sleeping... LOG: Sun Aug 03 21:14:38 CST 2014 : sleep 方法结束!