Spring ApplicationContext getBean仅在以前的AutoWired时有效

时间:2017-10-02 15:40:16

标签: java spring spring-boot reflection dependency-injection

我正在为命令创建路由控制器结构。 每个控制器都有一个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在线程中工作?

2 个答案:

答案 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没有像预期的那样工作。所以它与我发布的代码无关......

我希望其他人仍能了解我的答案。