我正在为命令创建路由控制器结构。
每个控制器都有一个@ControlController
批注:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Component // Because @Component all controllers will be spring managed.
public @interface ControlController {
}
控制器应包含带有
@CommandMapping
批注的方法:@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CommandMapping {
String value();
}
@CommandMapping
批注的值是命令。因此,当值与所调用的命令相同时,应调用该方法。在应用程序开始时,将调用以下代码以获取所有
@CommandMappings
:/**
* Load all controller mappings.
*/
private void fetchControllers() {
// Get all beans with the ControlController annotation.
Map<String, Object> controllers = this.applicationContext.getBeansWithAnnotation(ControlController.class);
for (Map.Entry<String, Object> entry : controllers.entrySet()) {
Class controller = entry.getValue().getClass();
for (Method method: controller.getMethods()) {
// Check every method in a controller for the CommandMapping annotation.
// When the annotation is present the method is a command mapping.
if (method.isAnnotationPresent(CommandMapping.class)) {
CommandMapping commandMapping = method.getAnnotation(CommandMapping.class);
// Add the command mapping to the controller list.
this.controllers.put(commandMapping.value(), method);
}
}
}
}
这段代码将找到所有带有
@ControlController
批注的bean,并循环通过所有方法来找到@CommandMapping
批注。所有方法将放在Map<String, Method>
中。到目前为止,一切正常。
以下方法用于执行属于命令的正确方法:
/**
* Execute a command for a client.
*
* @param client The client.
* @param command The command.
*/
public void executeCommand(Client client, String command) {
// Get the method that belongs to the command.
Method method = this.controllers.get(command);
Class<?> controllerClass = method.getDeclaringClass();
// The the controller that belongs to the method.
Object controller = this.applicationContext.getBean(controllerClass); // Here the code just stops.
System.out.println("Yeah"); // This isn't executed.
try {
List<Object> arguments = new ArrayList<>();
for (Parameter parameter: method.getParameters()) {
// Add arguments based on the parameter type.
}
method.invoke(controller, arguments.toArray(new Object[arguments.size()]));
} catch (Exception exception) {
exception.printStackTrace();
}
}
代码在
this.applicationContext.getBean(controllerClass);
处无任何停止我发现当我自动连接
controllerClass
时,出于某种原因它可以工作。我在什么类别的控制器上自动接线都没有关系。但是,当然,每个控制器的自动布线都是一个丑陋的修复。为什么ApplicationContext.getBean卡住了,我该如何解决?
更新:
我刚刚发现在
getBean
中使用bean名称也可以。例:
this.applicationContext.getBean(MainController.class); //Doesn't work
this.applicationContext.getBean("mainController"); // Works
更新:
我忘了提到一些非常重要的事情(我认为):
executeCommand
方法是从线程调用的,但是该线程是春季管理的。当我在没有线程的情况下运行它时,它确实有效,但是我确实需要线程。如何使beans
在线程中工作? 最佳答案
您可以尝试使用'name'搜索Controller
;此解决方案意味着通过获取注释来找到Controller
的名称。
即:
@Service
@Component(value = "statService")
public class Controller {...}
public class AnnotationFinder {
public static String findComponentName(Class cls) {
for (Annotation annotation : cls.getDeclaredAnnotations()) {
if (annotation.annotationType().equals(Component.class)) {
return annotation.value();
}
}
return null;
}
}
当您获得
@Component
时,您将获得value
成员和=>对象控制器= this.applicationContext.getBean(AnnotationFinder.findComponentName(controllerClass));