解决方案1:
你也可以做这样的事情:
enum EventType {
MESSAGE {
@Override
public void handleMessage(Service service, Message message) {
service.onMessage(message);
}
},
STAR_ADDED {
@Override
public void handleMessage(Service service, Message message) {
service.onStarAdded(message);
}
public abstract void handleMessage(Service service, Message message);
}
}
在你的其他类,你知道什么是 “激活” 事件:
yourEvent.handleMessage(service, message);
解决方案2:
我不知道春天是否有任何正确的东西,否则你也可以使用反射。下面是一个使用反射的例子(我更喜欢没有反映上述=>枚举的解决方案):
for(Method method: Service.class.getDeclaredMethods()){
Controller annotation = m.getAnnotation(Controller.class);
for(EventType event: annotation.events()){
if(event.equals(yourActiveEventType)){
method.invoke(service, message);
}
return ...
}
}
提示(而不是解决方案)3:
我真的不觉得有以下适用于你的场景,但我想我会提到它...... Spring AOP让你在调用带注释的方法时触发一些代码(它与你的场景相反),检查这个答案,但它可能值得阅读你:aspectj-pointcut-for-all-methods-of-a-class-with-specific-annotation
@Around("execution(@Controller * com.exemple.YourService.*(..))")
public Object aroundServiceMethodAdvice(final ProceedingJoinPoint pjp)
throws Throwable {
// perform actions before
return pjp.proceed();
// perform actions after
}
解决方案4:(评论后加入)
使用org.reflections
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.9.10</version>
</dependency>
例如:
Service service = ...;
Message message = ...;
Set<Method> methods =
ReflectionUtils.getMethods(Service.class, ReflectionUtils.withAnnotation(Controller.class),ReflectionUtils.withParametersAssignableTo(Message.class));
for(Method m: methods){
Controller controller = m.getAnnotation(Controller.class);
for(EventType eventType: controller.value()){
if(EventType.MESSAGE.equals(eventType)){
m.invoke(service, message);
}
}
}
这是假设你已经持有的参考服务对象(其中你的方法是)。因为你使用的是Spring,如果你的'Services'是spring管理的,你可能会从spring的上下文中得到实例,你必须亲自尝试一下,因为这有点与你的设计绑定:
@Autowired
private ApplicationContext appContext;
Reflections r = new Reflections(new MethodAnnotationsScanner(), "com.your.package");
Set<Method> methods = r.getMethodsAnnotatedWith(Controller.class);
for(Method m: methods){
Controller controller = m.getAnnotation(Controller.class);
for(EventType eventType: controller.value()){
if(EventType.MESSAGE.equals(eventType)){
String className = m.getDeclaringClass().getSimpleName();
className = className.replaceFirst(className.substring(0,1), className.substring(0,1).toLowerCase());
Object service = appContext.getBean(className);
m.invoke(service, message);
}
}
}
如果您的类是弹簧托管的并且使用其默认camelcase名称添加到上下文中,则此方法有效。
您可以简化逻辑,但我相信主要元素在那里。
是的,你的第一个方法很好,但我没有任何控制B类中的方法名称的方法。你可能会认为我想创建类似于Spring框架中的'@ Controller'注释。所以你的第一个方法需要为每个我不想要的事件类型分别设置方法。其次,当对两个不同的事件采取同样的行动时,代码将被重复。 –
我明白了,然后反射(第二个代码示例)可能是您的首选武器! – alexbt
,或者可能是AroundInvoke/aspectJ这里有一个链接(用一个例子编辑我的答案):http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html – alexbt