9

i hava aclass InitApp

@Component
public class InitApp implements ServletContextListener {

@Autowired
ConfigrationService weatherConfService;

/** Creates a new instance of InitApp */
public InitApp() {
   }

public void contextInitialized(ServletContextEvent servletContextEvent) {
    System.out.println(weatherConfService);
   }
public void contextDestroyed(ServletContextEvent servletContextEvent) {
   }
}

and listener in web.xml:

    <listener>
        <listener-class>com.web.Utils.InitApp</listener-class>
    </listener>

    <listener>
      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

the confService print --> null what the problem?

4

5 に答える 5

10

私は同じ問題を抱えていたので、いくつかのアイデアが思い浮かびました。

最初の 1 つは、Spring ユーティリティを使用して、リスナー内の Spring コンテキストから Bean を取得することです。

元:

@WebListener
public class CacheInitializationListener implements ServletContextListener {

    /**
     * Initialize the Cache Manager once the application has started
     */
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        CacheManager cacheManager = WebApplicationContextUtils.getRequiredWebApplicationContext(
                sce.getServletContext()).getBean(CacheManager.class);
        try {
            cacheManager.init();
        } catch (Exception e) {
            // rethrow as a runtime exception
            throw new IllegalStateException(e);
        }
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        // TODO Auto-generated method stub

    }
}

これは、Bean が 1 つまたは 2 つしかない場合にうまく機能します。そうしないと、退屈になる可能性があります。もう 1 つのオプションは、Spring の Autowire ユーティリティを明示的に呼び出すことです。

@WebListener
public class CacheInitializationListener implements ServletContextListener {

    @Autowired
    private CacheManager cacheManager;

    /**
     * Initialize the Cache once the application has started
     */
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
        try {
            cacheManager.init();
        } catch (Exception e) {
            // rethrow as a runtime exception
            throw new IllegalStateException(e);
        }
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        // TODO Auto-generated method stub

    }
}

これらの両方のソリューションの警告は、これらのいずれかが機能する前に、Spring コンテキストを最初にロードする必要があることです。を使用してリスナーの順序を定義する方法がないことを考えると@WebListener、Springが強制的に最初にロードされるように でContextLoaderListener定義されていることを確認してください (Web 記述子で定義されたリスナーは、アノテーションで定義されたリスナーの前にロードされます)。web.xml

于 2015-06-04T14:28:20.537 に答える
1

他の人が言っているように、このリスナーは Web サーブレット (Tomcat) コンテキスト (Spring コンテナーではない) によって観察され、サーブレットの起動/シャットダウンが通知されます。

Spring コンテナーの外部のサーブレットによって作成されるため、Spring によって管理されないため、@Autowire メンバーは使用できません。

Bean をマネージド @Component としてセットアップすると、Spring がインスタンスを作成し、リスナーは外部サーブレットに登録されません。

あなたはそれを両方の方法で持つことはできません..

1 つの解決策は、Spring アノテーションを削除し、Spring アプリケーション コンテキストからメンバーを手動で取得し、メンバーをそのように設定することです。

すなわち

    public class InitApp implements ServletContextListener {

        private ConfigrationService weatherConfService;

        private static ApplicationContext   applicationContext  = new ClassPathXmlApplicationContext("classpath:web-context.xml");

        @Override
        public void contextInitialized(ServletContextEvent servletContextEvent) {
            weatherConfService = applicationContext.getBean(ConfigrationService.class);
            System.out.println(weatherConfService);
        }

        @Override
        public void contextDestroyed(ServletContextEvent servletContextEvent) {
        }
    }
于 2014-12-17T11:18:18.570 に答える