2017-10-02 8 views
0

コマンドのルートコントローラ構造を作成しています。コントローラは@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をスレッドで動作させるにはどうすればよいですか?

+0

https://stackoverflow.com/questions/4914012/how-to-inject-applicationcontext-itself – Zorglube

+0

@Zorglube ApplicationContextは既に正しく注入されています。 –

+0

'this.applicationContext.getBean(MainController.class); //動作しません this.applicationContext.getBean( "mainController"); // Works'これは異常です... @Component(value = "MyControllerSpecificName") 'を使用してコントローラ名を設定しようとしましたか? – Zorglube

答えて

1

「名前」を使用して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))をゲット。

+1

この解決法はうまくいくが、私は奇妙な動作を引き起こした部分をすでに見つけた。 –

0

Webアプリケーションが動作していないことが判明しました。

問題は、接続を受け付けていたループが別のスレッドではなくコンポーネントの@PostConstructで実行されていたため、アプリケーションが完全に起動されずにサーバー(My SocketServer)が実行されていたことです。

アプリケーションが完全に起動していないため、Beanは期待どおりに動作しませんでした。だから、私が投稿したコードとは関係がありませんでした。

私は他の人がまだ私の答えを知りたいと思っています。

関連する問題