在Spring启动时注入一个bean

时间:2014-07-08 10:34:35

标签: spring dependency-injection

我有一个RunBackgroundServices类,它在启动时运行一些后台服务。我需要一个新的对象BackgroundServices。所以我使用WebApplicationContext来获取bean。但它没有用。

RunBackgroundServices.java

 @WebListener
public class RunBackgroundServices implements ServletContextListener {

    private ExecutorService executor;

    public void contextInitialized(ServletContextEvent event) {
        final WebApplicationContext springContext = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext());
        BackgroundServices backgroundServices = springContext.getBean(BackgroundServices.class);

        executor = Executors.newSingleThreadExecutor();
        executor.submit(backgroundServices); // Task should implement Runnable.
    }

    public void contextDestroyed(ServletContextEvent event) {
        executor.shutdown();
    }

}

BackgroundServices.java

@Service
public class BackgroundServices extends Thread {

    @Autowired
    ServerListener serverListener;

    @Autowired
    ClientListener clientListener;

    private static final Logger logger = LoggerFactory
            .getLogger(BackgroundServices.class);

    public void run() {
        logger.debug("BackgroundServices :: run");
        try {
            serverListener.start();
        } catch (InterruptedException e) {
            logger.error(e.getStackTrace().toString());
        }

        try { 
            clientListener.start();
        } catch (InterruptedException e) {
            logger.error(e.getStackTrace().toString());
        }

    }
}

我收到以下错误 -

Exception sending context initialized event to listener instance of class com.emc.hl7.common.RunBackgroundServices
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.emc.hl7.common.BackgroundServices] is defined
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:295)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1125)
    at com.emc.hl7.common.RunBackgroundServices.contextInitialized(RunBackgroundServices.java:20)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4961)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5455)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:634)
    at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:671)
    at org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:1840)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

1 个答案:

答案 0 :(得分:4)

使用Spring执行引导操作有一种更简单的方法。 您所要做的就是拥有实现ApplicationListener<ContextRefreshedEvent>

的Spring bean

您的代码如下:

@Component
public class ContextStartupListener implements ApplicationListener<ContextRefreshedEvent> {

    private final BackgroundServices backgroundServices;

    private ExecutorService executor;

    @Autowired
    public ContextStartupListener(BackgroundServices backgroundServices) {
        this.backgroundServices= backgroundServices;
    }

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        if(!isRootApplicationContext(event)) {
            return;
        }

        executor = Executors.newSingleThreadExecutor();
        executor.submit(backgroundServices);
    }

    private boolean isRootApplicationContext(ContextRefreshedEvent event) {
        return null == event.getApplicationContext().getParent();
    }
}

请注意isRootApplicationContext的使用。如果您有多个应用程序上下文并且不想在每个应用程序上下文上运行引导操作,则需要它。

使用上面的代码,您可以使用Spring的事件进行引导,而不是使用Servlet容器的事件。