先看个例子:
接口
package example;
public interface Basic { public void hello(); } |
接口的实现类
package example;
public class BasicService implements Basic { public void hello() { Sysytem.out.println("Hello, world"); } } |
实现了InvocationHandler接口的类
package example;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.logging.Level; import java.util.logging.Logger;
public class LogHandler implements InvocationHandler { private Logger logger = Logger.getLogger(this.getClass().getName()); private Object delegate;
public Object bind(Object delegate) { this.delegate = delegate; return Proxy.newProxyInstance(delegate.getClass().getClassLoader(), delegate.getClass().getInterfaces(), this); }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = null;
try { log("method starts..." + method); result = method.invoke(delegate, args); log("method ends..." + method); } catch (Exception e) { log(e.toString()); } return result; }
private void log(String message) { logger.log(Level.INFO, message); } } |
运行类
package example;
public class ProxyDemo { public static void main(String[] args) { LogHandler logHandler = new LogHandler(); Basic helloProxy = (Basic) logHandler.bind(new BasicService()); helloProxy.hello(); } } |
Proxy.newProxyInstance的3个参数说明:
1. 根据传入的第二个参数interfaces动态生成一个类$Proxy0,该类
a) 实现interfaces中的接口;
b) 继承了Proxy类;
c) 重写了hashcode,toString,equals等三个方法;
2. 第一个参数classloder将刚生成的$Proxy0类加载到jvm中
3. 第三个参数,调用$Proxy0的构造函数 创建$Proxy0的对象
方法的调用过程:
InvocationHandler,调用一个方法时,不直接调用实现这个方法的真实类,而去调用它的代理,代理通过反射机制找到它的这个方法,然后代理自己去执行,所以invoke()会自动执行。如下例子中方法的调用过程为:
helloProxy.hello()->logHandler.invoke()->basicService.hello() |
Proxy动态代理的作用:
Proxy能够在核心业务方法前后做一些辅助工作,如log日志,安全机制等等。Spring中的事务控制就是用动态代理的机制来实现的.使得开发人员可以专住于逻辑的开发(所谓的切面),而其他的工作(如事务的提交和回滚)则交个容器"代"为处理.