我有一个Android应用程序,但它不相关。
我有一个名为"前控制器"这将收到一些消息 通过它的构造函数。为了简洁起见,该消息可以是整数。
我想在其他地方创建一个将要执行的新控制器 基于上面定义的整数的方法
public class OtherController {
@MessageId("100")
public void doSomething(){
//execute this code
}
@MessageId("101")
public void doSomethingElse(){
//code
}
}
前置控制器可能是这样的:
public class FrontController {
private int id;
public FrontController(int id){
this.id=id;
executeProperControllerMethodBasedOnId();
}
public void executeProperControllerMethodBasedOnId(){
//code here
}
public int getId(){
return id;
}
}
因此,如果Front Controller将接收整数100,那么 将执行使用@MessageId(100)注释的方法。该 前控制器并不完全知道这种方法所在的类 是
我发现的问题是我需要以某种方式注册 每个控制器类。我春天我有@Component或@Controller 用于自动加载。每个控制器注册后,我需要 调用正确注释的方法。
如何完成这项任务?在Spring MVC中,我有这个系统 已实现,用于匹配HTTP路由。我怎么能实现 这是一个简单的java项目吗?
有什么建议吗?
答案 0 :(得分:2)
感谢Google Reflections(希望你能将它集成到你的android项目中。)
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections-maven</artifactId>
<version>0.9.8</version>
</dependency>
为了优化,我添加了使用MessageType注释来注释类的要求,并且这些类应该在同一个包中(在我的示例中为org.conffusion):
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MessageType {
}
OtherController看起来像:
@MessageType
public class OtherController {
@MessageId(id=101)
public void method1()
{
System.out.println("executing method1");
}
@MessageId(id=102)
public void method2()
{
System.out.println("executing method2");
}
}
实施将如下所示:
public void executeProperControllerMethodBasedOnId() {
Set<Class<?>> classes = new org.reflections.Reflections("org.conffusion")
.getTypesAnnotatedWith(MessageType.class);
System.out.println("found classes " + classes.size());
for (Class<?> c : classes) {
for (Method m : c.getMethods()) {
try {
if (m.isAnnotationPresent(MessageId.class)) {
MessageId mid = m.getAnnotation(MessageId.class);
Object o = c.newInstance();
if (mid.id() == id)
m.invoke(o);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
也许您可以优化并构建包含已扫描的消息ID的静态哈希映射。
答案 1 :(得分:1)
您需要使用反射自行实现一些工作,我建议在初始阶段就性能准备消息处理程序。您还可以考虑 Singleton / Per Request 控制器。实现解决方案的一些方法:
interface MessageProcessor {
void execute() throws Exception;
}
/* Holds single instance and method to invoke */
class SingletonProcessor implements MessageProcessor {
private final Object instance;
private final Method method;
SingletonProcessor(Object instance, Method method) {
this.instance = instance;
this.method = method;
}
public void execute() throws Exception {
method.invoke(instance);
}
}
/* Create instance and invoke the method on execute */
class PerRequestProcessor implements MessageProcessor {
private final Class clazz;
private final Method method;
PerRequestProcessor(Class clazz, Method method) {
this.clazz = clazz;
this.method = method;
}
public void execute() throws Exception {
Object instance = clazz.newInstance();
method.invoke(instance);
}
}
/* Dummy controllers */
class PerRequestController {
@MessageId(1)
public void handleMessage1(){System.out.println(this + " - Message1");}
}
class SingletonController {
@MessageId(2)
public void handleMessage2(){System.out.println(this + " - Message2");}
}
class FrontController {
private static final Map<Integer, MessageProcessor> processors = new HashMap<Integer, MessageProcessor>();
static {
try {
// register your controllers
// also you can scan for annotated controllers as suggested by Conffusion
registerPerRequestController(PerRequestController.class);
registerSingletonController(SingletonController.class);
} catch (Exception e) {
throw new ExceptionInInitializerError();
}
}
private static void registerPerRequestController(Class aClass) {
for (Method m : aClass.getMethods()) {
if (m.isAnnotationPresent(MessageId.class)) {
MessageId mid = m.getAnnotation(MessageId.class);
processors.put(mid.value(), new PerRequestProcessor(aClass, m));
}
}
}
private static void registerSingletonController(Class aClass) throws Exception {
for (Method m : aClass.getMethods()) {
if (m.isAnnotationPresent(MessageId.class)) {
MessageId mid = m.getAnnotation(MessageId.class);
Object instance = aClass.newInstance();
processors.put(mid.value(), new SingletonProcessor(instance, m));
}
}
}
/* To process the message you just need to look up processor and execute */
public void processMessage(int id) throws Exception {
if (processors.containsKey(id)) {
processors.get(id).execute();
} else {
System.err.print("Processor not found for message " + id);
}
}
}