我创建了两个InvocationHandler,一个用于记录目的,另一个用于测量时间。每个都在工作,但我不知道如何创建这两个链,以便两者都将被执行。我认为只要LoggingInvocationHandler扩展TimerInvocationHandler就足够了
public class DynamicProxyMain {
public static void main(String[] args) {
System.out.println("Starting dynamic proxy sample");
SubjectInterface timerProxy = (SubjectInterface) Proxy.newProxyInstance(SubjectInterface.class.getClassLoader(),
new Class<?>[]{SubjectInterface.class},
new TimerInvocationHandler(new SubjectInterfaceImpl()));
SubjectInterface logginProxy = (SubjectInterface) Proxy.newProxyInstance(SubjectInterface.class.getClassLoader(),
new Class<?>[]{SubjectInterface.class},
new LoggingInvocationHandler(new SubjectInterfaceImpl()));
timerProxy.methodA("a");
timerProxy.methodB("test b");
timerProxy.methodC(1, "test c");
}
}
public class LoggingInvocationHandler implements InvocationHandler {
Object impl;
String CLASSNAME = this.getClass().getCanonicalName();
public LoggingInvocationHandler(Object impl){
this.impl = impl;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object retVal;
System.out.println("LoggingHandler:" + this.getClass().getName() + " has been called");
retVal = method.invoke(impl, args);
System.out.println("LoggingHandler:" + this.getClass().getName() + " has ended");
return retVal;
}
}
public class TimerInvocationHandler extends LoggingInvocationHandler implements InvocationHandler{
private Object impl;
public TimerInvocationHandler(Object impl) {
super(impl);
this.impl = impl;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object retVal = null;
System.out.println("getting duration time for method " + method.getName());
long duration = -System.currentTimeMillis();
retVal = super.invoke(proxy,method,args);
duration += System.currentTimeMillis();
System.out.println("it took " + duration + " milliseconds");
System.out.println("duration time handler has ended");
return retVal;
}
}
实际上我解决了它,因此将调用两个InvocationHandler。我使用当前正在运行的代码编辑了我的帖子
答案 0 :(得分:2)
这个想法与Intercepting Filter
有相似之处,我会给你一个实现它,如果你有兴趣和想要,我会稍加修改以便与DynamicProxyHandler
一起使用更多细节,您应该彻底阅读link。
<强>参与者强>:
InvocationChain
- 负责调度调用。Invocation
- 你应该放置logging
和timer
之类的内容。DynamicProxyHanlder
- 只需将请求委托给InvocationChain
。<强> Implementaiton 强>:
DynamicProxyHandler.java
public class DynamicProxyHandler implements InvocationHandler {
private Object proxied;
InvocationChain chain = new InvocationChainImp();
DynamicProxyHandler(Object proxied) {
this.proxied = proxied;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return chain.invoke(proxied, method, args);
}
}
Invocation.java
public interface Invocation {
Object invoke(Object callee, Method method, Object[] args, InvocationChain chain);
}
InvocationChain.java
public interface InvocationChain {
public Object invoke(Object callee, Method method, Object[] args);
}
InvocationChainImp.java
public class InvocationChainImp implements InvocationChain {
List<Invocation> list = new ArrayList<>();
Object result;
Iterator<Invocation> tasks;
InvocationChainImp() {
list.add(new LoggingInvocation());
list.add(new TimerInvocation());
list.add(new FinalInvocation());
tasks = list.iterator();
}
@Override
public Object invoke(Object callee, Method method, Object[] args) {
if (tasks.hasNext()) {
Object result = tasks.next().invoke(callee, method, args, this);
this.result = (this.result == null ? result : this.result);
}
return this.result;
}
最后,我们要定义一些必须限制在Invocation
接口的自定义类,以便记录,计时器等。
LoggingInvocation.java
public class LoggingInvocation implements Invocation {
@Override
public Object invoke(Object callee, Method method, Object[] args, InvocationChain chain) {
chain.invoke(callee, method, args);
Logger.getLogger(this.getClass().getCanonicalName()).info(method.getName() + "() execution logged!");
return null;
}
}
TimerInvocation.java
public class TimerInvocation implements Invocation {
@Override
public Object invoke(Object callee, Method method, Object[] args, InvocationChain chain) {
long start_time = System.nanoTime();
chain.invoke(callee, method, args);
long end_time = System.nanoTime();
System.out.println("Timer: excution took " + (end_time - start_time) / 1e6 + "ms");
return null;
}
}
FinalInvocation.java ,最后在代理实例上调用请求。
public class FinalInvocation implements Invocation {
@Override
public Object invoke(Object callee, Method method, Object[] args, InvocationChain chain) {
try {
return method.invoke(callee, args);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
}
其余的代码是微不足道的,因为它只是用于证明实现的有效性 如果您想自己编写,可以立即停止阅读。
SubjectInterface.java
public interface SubjectInterface {
String hello();
}
SubjectInterfaceImp.java
public class SubjectInterfaceImp implements SubjectInterface {
@Override
public String hello() {
System.out.println("in SubjectInterfaceImp: Greeting!");
return "hello";
}
}
Main.java
public class Main {
public static void main(String[] args) throws Exception {
SubjectInterface subject = (SubjectInterface) Proxy.newProxyInstance(
SubjectInterface.class.getClassLoader(),
new Class[] { SubjectInterface.class }, new DynamicProxyHandler(new SubjectInterfaceImp()));
System.out.println("in Main: subject.hello() = " + subject.hello());
}
}
好的,我们有足够的代码,它的演出时间,让我们看看, voila !
in SubjectInterfaceImp: Greeting!
Timer: excution took 0.532198ms
九月 02, 2016 12:37:36 下午 LoggingInvocation invoke
信息: hello() execution logged!
in Main: subject.hello() = hello
答案 1 :(得分:0)
这不是实现它的自然方式.TimerInvocationHandler与LoggingInvocationHandler无关。 定义一个装饰器,它是一个InvocationHandler并包装另一个InovovationHandler
https://en.wikipedia.org/wiki/Decorator_pattern
编辑:由于一条评论要求我提供一个示例实现,添加了以下部分,但这不是精确的装饰模式,但我认为其他人可以理解解决方案。在这种情况下,TimeInvocationHandler不限于测量登录时间public class TimerInvocationHandler implements InvocationHandler
{
protected InvocationHandler invocationHandler;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
//do whatever you want
Object result = invocationHandler.invoke(proxy, method, args);
// do what ever you want
return result;
}
}