问题
我需要一遍又一遍地对几种方法的结果进行逻辑。这些方法可以具有任意结果类型。简单的用例看起来像这样:
带有执行方法的包装类别:
/**
* Wrapper class which executes inner logic, processes the result of that logic and returns the processed result.
*
* @param <T>
*/
public abstract class Wrapper<T> {
/**
* Perform inner logic
*/
public abstract T run();
/**
* Invoke inner logic and process it.
*/
public T execute() {
T result = run();
// TODO: process result
return result;
}
}
和内部类中的逻辑,包装器的示例用法:
public class WrapperDemo {
/**
* Simple invocation of the inner logic and then the outer logic
*/
public static Boolean testMethod() {
// wrap around logic and execute
return new Wrapper<Boolean>() {
@Override
public Boolean run() {
// TODO: perform logic, simply returning true for now
return Boolean.TRUE;
}
}.execute();
}
public static void main(String[] args) {
// demo method invocation
Boolean result = WrapperDemo.testMethod();
// process result
System.out.println(result);
System.exit(0);
}
}
我必须将其应用于几种100秒的方法。
问题
有人知道一种更方便的方法来用更少的 testMethod
代码编码此编码(例如,注释(?
如果您有Java 8,则可以写下以下内容:
public static <T> T execute(Wrapper<T> wrapper) {
return wrapper.execute();
}
,然后按以下方式使用:
public static Boolean testMethod() {
return execute(()-> {
return Boolean.TRUE;
});
}
尽管我看不出比以下内容更好:
public static <T> T wrap(T result) {
// Process result
return result
}
并这样使用:
public static Boolean testMethod() {
return wrap(Boolean.TRUE);
}
如果要使用注释,则应使用允许使用这种反射的工具。无法使用基本反射,因为您不能"拦截"调用。Java的代理可能会有所帮助,但是您被限制使用界面,这并不总是人们想要的。
cglib是一个消除所有麻烦的库。因此,您可以尝试以下内容:
@Target(METHOD)
@Retention(RUNTIME)
public @interface Wrap {
}
class Demo {
@Wrap
public Boolean testMethod() {
return Boolean.TRUE;
}
}
class Wrapper {
public <T> T newInstance(Class<T> type) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(type);
enhancer.setCallback(new InvocationHandler(){
@Override public Object invoke(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
Object result = proxy.invokeSuper(obj, args);
if (method.isAnnotationPresent(Wrap.class)) {
execute(result);
}
return result;
}
});
return enhancer.create();
}
public void execute(Object result) {
// Add custom behavior to @Wrap-ped methods.
}
}
然后,您必须这样打电话给包装器:
Demo demo = new Wrapper().newInstance(Demo.class);
demo.testMethod();
其他库也存在,例如字节好友或Javassist。但是要小心,因为Java 9非常接近,并迫使这些图书馆非常非常快速地更改其核心业务,可能会使它们不稳定。
在java 8中,通过lambda和默认方法的组合,您可以实现类似的事情而无需更改API(除了您需要使Wrapper
成为接口而不是抽象类(
public interface Wrapper<T> {
public T run();
default public T execute() {
T result = run();
// TODO: process result
return result;
}
}
然后您可以通过
调用它public static Boolean testMethod() {
Wrapper<Boolean> w = ()-> {return Boolean.TRUE;};
return w.execute();
}
但我个人认为这没有多大意义。
如果您想围绕逻辑添加额外的逻辑,则可能需要有点扭曲:
public class ExtraAction<T> {
Supplier<T> supplier;
public ExtraAction(Supplier<T> supplier) {
this.supplier = supplier;
}
public T execute() {
T result = this.supplier.get();
// some extra processsing
return result;
}
}
因此,它将被称为
Boolean result = new ExtraAction<>(()->{return Boolean.TRUE}).execute();
更好,使您的逻辑在Wrapper
A Function<X,Y>
中,然后弥补您的Supplier
和Function
的链接,因此看起来像
result = Foo.forInput( ()-> { return logicToGetResult(); })
.doExtra(ExtraAction::whateverAction).result();