我可以在Java中调用运行时决定的方法调用吗?
我知道有一个调用函数可以完成这些工作,我对使用这种行为的“正确性”非常感兴趣。 我的问题是: 我有一个服务对象,它包含了我考虑服务的方法。 我想做的是改变这些服务的行为,而不会在以后发生入侵。 例如:我可以在Java中调用运行时决定的方法调用吗?,java,reflection,service,soa,Java,Reflection,Service,Soa,我知道有一个调用函数可以完成这些工作,我对使用这种行为的“正确性”非常感兴趣。 我的问题是: 我有一个服务对象,它包含了我考虑服务的方法。 我想做的是改变这些服务的行为,而不会在以后发生入侵。 例如: class MyService { public ServiceResponse ServeMeDonuts() { do stuff... return new ServiceResponse(); } 两个月后,我发现我需要为一个新的客户端应用程序提供
class MyService {
public ServiceResponse ServeMeDonuts() {
do stuff...
return new ServiceResponse();
}
两个月后,我发现我需要为一个新的客户端应用程序提供相同的服务,我还需要做一些额外的事情,比如设置一个标志,或者制作或更新某些数据,或者对响应进行不同的编码。我能做的就是把它弹出并抛出一些假设。在我看来,这是不好的,因为这意味着与测试代码的交互,可能会导致以前的服务客户端出现不需要的行为
所以我来向我的注册表添加一些东西,告诉系统“新客户机”有不同的行为。所以我会这样做:
public interface Behavior {
public void preExecute();
public void postExecute();
}
public class BehaviorOfMyService implements Behavior{
String method;
String clientType;
public void BehaviorOfMyService(String method,String clientType) {
this.method = method;
this.clientType = clientType;
}
public void preExecute() {
Method preCall = this.getClass().getMethod("pre" + this.method + this.clientType);
if(preCall != null) {
return preCall.invoke();
}
return false;
}
...same for postExecute();
public void preServeMeDonutsNewClient() {
do the stuff...
}
}
系统何时会执行类似操作
if(registrySaysThereIs different behavior set for this ServiceObject) {
Class toBeCalled = Class.forName("BehaviorOf" + usedServiceObjectName);
Object instance = toBeCalled.getConstructor().newInstance(method,client);
instance.preExecute();
....call the service...
instance.postExecute();
....
}
我对代码的正确性不像对思维和方法的正确性那么感兴趣。实际上,我必须用PHP来做这件事,我把PHP看作是一种流行音乐,出于商业原因,我不得不“唱”,即使我演奏流行音乐,我真的很想按照书唱,所以抛开我或多或少的灵感类比,我真的想知道你对这件事的看法,因为它的实际必要性和技术方法
谢谢很好的申请案例。使用AOP,您可以将方面附加到事件或方法,以便在事件前后处理额外的逻辑
这里有AOP的好例子,也有Java的例子
这个例子与您的案例非常相似,基本上是围绕服务执行添加post和pre方法处理程序
我对PHP中的AOP不太熟悉,但是有一些项目可以使用,比如您需要的是一个代理,通过它,您可以独立于被代理的对象定义一些额外的行为。例如:
public class ServiceHandler implements InvocationHandler {
private final Object target;
public static Object createProxy(Object target) {
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), new ServiceHandler(target));
}
public ServiceHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// define preexecute behaviour
Object result = method.invoke(target, args);
// define postexecute behaviour
return result;
}
}
然后,您将按如下方式使用它:
public static void main(String[] args) {
Service serviceImpl = new ServiceImpl();
Service service = (Service) ServiceHandler.createProxy(serviceImpl);
// use service
}
在我看来,这并没有它那么好
意味着与测试代码和
可能会导致未被通缉的行为
以前的服务客户端
这就是为什么你有自动测试。你想要的东西可以用AOP来完成,但实际上不应该这样做,因为这会使代码很难维护(这是AOP的一个普遍问题,也是它没有流行的一个原因)
这只是另一个因害怕破坏某些有效的东西而使代码变得更糟的例子。最后,任何更改都可能会破坏东西,通过痛苦的扭曲将更改从“好”代码中分离出来并使其正常工作只会以痛苦告终。事实上,这正是我一开始所想的:“如果对象可以有方面,那么服务可以有行为”,所以现在我想知道为什么在发布之前我没有更深入地研究AOP,现在我想重新发现方向盘。谢谢你的简短而全面的回答。关于自动化测试,你是非常正确的,但是对于客户机是其他应用程序(可能是需要该服务的完全不同的应用程序)的服务来说,测试几乎是不可能的,有时需要很长时间,直到有人发现出了问题。我是接吻原则的最大粉丝(保持简单愚蠢),这就是为什么我在让事情变得“更好”之前花了很多时间思考的原因。无论如何,我重视你的意见。Thanks@Catalin:这就是为什么此类服务具有非常严格且明确定义的接口非常重要的原因。然后,您可以拥有一个涵盖接口契约的测试套件,如果客户机依赖于契约没有保证的行为,那就是他们自己的错。当然,如果您继承了一个从未签订过这样的合同并“有机地”增长的服务,那么这并没有多大帮助。