我正在为命令创建路由控制器结构。
每个控制器都有一个db3.massagerTimes.aggregate({
$unwind: "$times"
}, {
$group: {
_id: "$times.email", // group all items with the same email together
doc: {$first: "$$ROOT"} // keep only the first document for each email address
}
}, {
$replaceRoot: {
newRoot: "$doc" // move the element we remembered during the grouping stage to the top of our document
}
});
注释:
@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);
}
}
}
}
注释的所有bean,并将循环遍历所有方法以查找@ControlController
注释。所有方法都将放在@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);
时出于某种原因可行。在我自动控制控制器的类中,这并不重要。但当然,AutoWiring每个控制器都是一个难看的解决方案。
为什么ApplicationContext.getBean会卡住,我该如何解决?
更新
我刚刚发现在controllerClass
中使用bean名称也有效。
例如:
getBean
更新
我忘了提到一些非常重要的东西(我认为):从一个线程调用this.applicationContext.getBean(MainController.class); //Doesn't work
this.applicationContext.getBean("mainController"); // Works
方法,但该线程是弹簧管理的。当我在没有线程的情况下运行它时,它可以工作,但我真的需要线程。如何让executeCommand
在线程中工作?
答案 0 :(得分:1)
您可以尝试使用&#39;名称&#39;来搜索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
成员并且=&gt;
Object controller = this.applicationContext.getBean(AnnotationFinder.findComponentName(controllerClass));
答案 1 :(得分:0)
我发现网络应用程序也没有工作。
问题是接受连接的循环没有在单独的线程中运行,而只是在组件的@PostConstruct
中运行,因此应用程序从未完全启动,但服务器(My SocketServer)正在运行。
因为应用程序没有完全启动,所以bean没有像预期的那样工作。所以它与我发布的代码无关......
我希望其他人仍能了解我的答案。