问题
我需要对几种方法的结果反复执行逻辑。方法可以具有任意结果类型。简单的用例如下所示:
带有execute方法的包装类:
/**
* 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;
}
}
内部类中的逻辑,Wrapper的示例用法:
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);
}
}
我必须将其应用于几百种方法。
问题
有没有人知道使用testMethod
(例如可能是注释)的代码更少的代码来更方便地编码?
答案 0 :(得分:1)
如果你有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);
}
答案 1 :(得分:1)
在Java 8中,通过组合lambda和default方法,您可以在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
Function<X,Y>
中制作你的逻辑,然后组合起来将你的Supplier
和Function
组合在一起,这样看起来就像
result = Foo.forInput( ()-> { return logicToGetResult(); })
.doExtra(ExtraAction::whateverAction).result();
答案 2 :(得分:1)
如果要使用注释,则应使用允许使用此类反射的工具。不能使用基本反射因为那样你就不能拦截&#34;电话。 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();
其他库也存在,如Byte Buddy或Javassist。但要小心,因为Java 9非常接近并迫使这些库非常快速地改变它们的核心业务,可能使它们不稳定。