JDK中的描述:
java.lang.reflect
接口 InvocationHandler
所有已知实现类:
EventHandler, MBeanServerInvocationHandler, RemoteObjectInvocationHandler public interface InvocationHandlerInvocationHandler 是代理实例的调用处理程序 实现的接口。 每个代码实例都具有一个关联的调用处理程序。对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的 invoke 方法。我对:“每个代码实例都具有一个关联的调用处理程序”这句不明白,什么是调用处理程序?每个代码实例都具有一个关联的调用处理程序,这样做有什么目的,会带来什么好处?InvocationHandler接口 只有一个invoke方法。JAVA中还有没有其他的类或接口具有invoke方法的呢?
invoke方法到底是怎么实现的呢?
java.lang.reflect
接口 InvocationHandler
所有已知实现类:
EventHandler, MBeanServerInvocationHandler, RemoteObjectInvocationHandler public interface InvocationHandlerInvocationHandler 是代理实例的调用处理程序 实现的接口。 每个代码实例都具有一个关联的调用处理程序。对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的 invoke 方法。我对:“每个代码实例都具有一个关联的调用处理程序”这句不明白,什么是调用处理程序?每个代码实例都具有一个关联的调用处理程序,这样做有什么目的,会带来什么好处?InvocationHandler接口 只有一个invoke方法。JAVA中还有没有其他的类或接口具有invoke方法的呢?
invoke方法到底是怎么实现的呢?
定义一个接口:interface Greet
{
void sayHello(String name); void goodBye();
}
实现这个接口:class GreetImpl implements Greet
{
public void sayHello(String name)
{
System.out.println("Hello " + name);
} public void goodBye()
{
System.out.println("Good bye.");
}
}
实现一个代理类public class SimpleProxy implements Greet
{
private Greet greet = null; SimpleProxy(Greet greet)
{
this.greet = greet;
} public void sayHello(String name)
{
System.out.println("--before method sayHello");
greet.sayHello(name);
System.out.println("--after method sayHello");
} public void goodBye()
{
System.out.println("--before method goodBye");
greet.goodBye();
System.out.println("--after method goodBye");
} /**
* @param args
*/
public static void main(String[] args)
{
Greet greet = new SimpleProxy(new GreetImpl());//生成代理
greet.sayHello("walter");
greet.goodBye(); }
}代理其实没什么的,再看看如果实现了InvocationHandler接口,
我们怎样实现代理。
还是要实现原来的Greet接口。
接口的实现还是GreetImpl。import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;public class DebugProxy implements java.lang.reflect.InvocationHandler
{
private Object obj; public static Object newInstance(Object obj)
{
return java.lang.reflect.Proxy.newProxyInstance(obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(), new DebugProxy(obj));
} private DebugProxy(Object obj)
{
//Greet接口的實現:GreetImpl
this.obj = obj;
} //Method m:調用的方法
//Object[] args:方法要傳入的參數
public Object invoke(Object proxy, Method m, Object[] args) throws Throwable
{
Object result;
try
{
//自定義的處理
System.out.println("--before method " + m.getName());
//調用GreetImpl中方法
result = m.invoke(obj, args);
}
catch(InvocationTargetException e)
{
throw e.getTargetException();
}
catch(Exception e)
{
throw new RuntimeException("unexpected invocation exception: " + e.getMessage());
}
finally
{
System.out.println("--after method " + m.getName());
}
return result;
} /**
* @param args
*/
public static void main(String[] args)
{
Greet tmp = new GreetImpl();
Greet greet = (Greet) DebugProxy.newInstance(tmp);
//生成的greet和tmp有相同的hashCode
greet.sayHello("walter");
greet.goodBye();
}
}
你看些资料吧。
/**
* Returns an instance of a proxy class for the specified interfaces
* that dispatches method invocations to the specified invocation
* handler. This method is equivalent to:
* <pre>
* Proxy.getProxyClass(loader, interfaces).
* getConstructor(new Class[] { InvocationHandler.class }).
* newInstance(new Object[] { handler });
* </pre>
*
* <p><code>Proxy.newProxyInstance</code> throws
* <code>IllegalArgumentException</code> for the same reasons that
* <code>Proxy.getProxyClass</code> does.
*
* @param loader the class loader to define the proxy class
* @param interfaces the list of interfaces for the proxy class
* to implement
* @param h the invocation handler to dispatch method invocations to
* @return a proxy instance with the specified invocation handler of a
* proxy class that is defined by the specified class loader
* and that implements the specified interfaces
* @throws IllegalArgumentException if any of the restrictions on the
* parameters that may be passed to <code>getProxyClass</code>
* are violated
* @throws NullPointerException if the <code>interfaces</code> array
* argument or any of its elements are <code>null</code>, or
* if the invocation handler, <code>h</code>, is
* <code>null</code>
*/
public interface HelloWorld {
void sayHello() ;
}
业务接口实现:
public class HelloWorldImpl implements HelloWorld {
public void sayHello() {
System.out.println("Hello World!");
}
}
InvocationHandler实现,需要在接口方法调用前后加入一部份处理工作,这里仅仅在方法调用前后向后台输出两句字符串,其代码如下:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class HelloWorldHandler implements InvocationHandler {
//要代理的原始对象
private Object objOriginal;
/**
* 构造函数。
* @param obj Examda提示: 要代理的原始对象。
*/
public HelloWorldHandler(Object obj) {
this.objOriginal = obj ;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result ;
//方法调用之前
doBefore();
//调用原始对象的方法
result = method.invoke(this.objOriginal ,args);
//方法调用之后
doAfter();
return result ;
}
private void doBefore() {
System.out.println("before method invoke!");
}
private void doAfter() {
System.out.println("after method invoke!");
}
}
测试代码:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class Test {
public static void main(String[] args) {
HelloWorld hw = new HelloWorldImpl();
InvocationHandler handler = new HelloWorldHandler(hw);
HelloWorld proxy = (HelloWorld) Proxy.newProxyInstance(
hw.getClass().getClassLoader(),
hw.getClass().getInterfaces(),
handler);
proxy.sayHello();
}
}
首先获取一个业务接口的实现对象;
获取一个InvocationHandler实现,此处是HelloWorldHandler对象;
创建动态代理对象;
通过动态代理对象调用sayHello()方法,此时会在原始对象HelloWorldImpl. sayHello()方法前后输出两句字符串。
运行测试类输出如下:
before method invoke!
Hello World!
after method invoke!
此处Test类中的方法调用代码比较多,在我们的实际应用中可以通过配置文件来来简化客户端的调用实现。另外也可以通过动态代理来实现简单的AOP。
是不是这样呢:
1. InvocationHandler 总是和 Proxy.newProxyInstance(...)成对出现。
2. 实现了InvocationHandler 接口的类是个不确定的类,根据所传入的参数不同而不同。