コマンドのルートコントローラ構造を作成しています。コントローラは@CommandMapping
注釈付きメソッドを含むべきであるSpring ApplicationContext getBeanは、AutoWiredの前にのみ動作します
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Component // Because @Component all controllers will be spring managed.
public @interface ControlController {
}
:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CommandMapping {
String value();
}
@CommandMapping
アノテーションの値がコマンドである すべてのコントローラが@ControlController
注釈を有します。したがって、このメソッドは、値が呼び出されたコマンドと同じ場合に呼び出される必要があります。次のコードは、すべての@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();
}
}
コードはちょうど私が私がcontrollerClass
をAutoWireときことが判明this.applicationContext.getBean(controllerClass);
で任意の例外なく停止しますそれは何らかの理由で動作します。どのクラスのコントローラでオートワイヤリングをしても問題ありません。もちろん、すべてのコントローラを自動配線するのは醜い修正です。
なぜApplicationContext.getBeanが停止するのですか?これをどのように修正できますか?
UPDATE: 私はちょうどgetBean
でBean名を使用しても動作することが分かりました。 例:
this.applicationContext.getBean(MainController.class); //Doesn't work
this.applicationContext.getBean("mainController"); // Works
UPDATE: 私は非常に重要な何か(と思う)言及するのを忘れてしまった:executeCommand
方法は、スレッドから呼び出されますが、スレッドは春管理されています。私はそれを動作させるとスレッドがなくても動作しますが、本当にスレッドが必要です。 beans
をスレッドで動作させるにはどうすればよいですか?
https://stackoverflow.com/questions/4914012/how-to-inject-applicationcontext-itself – Zorglube
@Zorglube ApplicationContextは既に正しく注入されています。 –
'this.applicationContext.getBean(MainController.class); //動作しません this.applicationContext.getBean( "mainController"); // Works'これは異常です... @Component(value = "MyControllerSpecificName") 'を使用してコントローラ名を設定しようとしましたか? – Zorglube