代理 参考core java 但感觉作者这部分写得不好 以后再回来修改
使用代理可以在运行时创建一个实现了某个接口的类。如果在编译时无法确定要实现哪个接口,才使用代理,这也是代理产生的原因。这个在应用开发中不是一个普遍的情况,对于系统级应用,代理会带来许多好处。
1 什么时候使用代理
加入我们想要构造一个对象,并且这个对象实现了一个或多个接口,但是在编译时还无法确定这个类该有什么特征。这是一个复杂的问题,为了创建一个实际的对象,我们可以简单的使用newInstance方法来使用反射找到一个构造器。但是我们并不能实例化一个接口,我们需要在运行时通过实现该接口定义一个类。
为了战胜这个困难,许多程序生成代码,把它们放在一个文件中,启动编译程序,并且加载结果类文件。很自然,这是缓慢的,也要求编译程序和我们的程序一起部署。代理机制是一个更好的解决方案。代理类在运行时创建了崭新的类。这样的一个代理类实现了我们所定义的接口。特别的,这个代理类有如下的方法:
1 实现了接口所要求的所有方法
2 继承了Objcet的方法
然而,我们不能在运行时为这些方法添加代码.取而代之的是我们需要提供一个调用处理器(invoke handler).调用处理器是实现了Invocation Handler接口的实例对象.该接口只有一个方法:
每当这个代理对象的方法被调用,那么调用处理器的invoke方法也会被调用 我们需要在内部调用method.invoke(实际对象,参数),确定返回值。 每一次调用都共享一个invoke 所在要在内部作逻辑判断
来看一个例子
package aa;
interface ISomeService {
String doFirst();
void doSecond();
}
class SomeServiceImpl implements ISomeService{
@Override
public String doFirst() {
System.out.println("do First");
return "result";
}
@Override
public void doSecond() {
System.out.println("do Second");
}
}
package aa; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class MyTest { public static void main(String[] args) { ISomeService target=new SomeServiceImpl(); //使用JDK的Proxy动态代理,要求目标类必须实现接口 // 因为其底层的执行原理,与静态代理相同 ISomeService service=(ISomeService) Proxy.newProxyInstance(target.getClass().getClassLoader()//目标类的类加载器 , target.getClass().getInterfaces() //目标类所实现的所有接口 ,new InvocationHandler() { //匿名内部类 //proxy:代理对象 //method:目标方法 //args:目标方法的参数列表 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //调用目标方法 System.out.println("hei"); Object result=method.invoke(target, args); if(result!=null) { result=((String)result).toUpperCase(); } return result; } }); String result=service.doFirst(); System.out.println("result="+result); service.doSecond(); } } 结果:
2 创建代理对象
为了创建代理对象,使用Proxy类的newProxyInstance方法,这个方法有三个参数
1 ClassLoader:作为java安全机制的一部分,不同的类加载器可以用于系统类,从网络下载下来的类,等等。
2 代理类需要实现的接口(一般为被代理类所实现接口的方法)
3 调用处理器
有两个问题:我们如何定义这个处理器?我们可以使用代理对象干什么?
代理可以用于许多目的,比如:
1 路由选择远程服务器的方法
2 在运行的程序中与动作相关的用户接口事件联系起来。
3 跟踪方法执行处于调式的目的。