简体   繁体   English

在春季启动时注入Bean

[英]Injecting a bean at startup in Spring

I have a class RunBackgroundServices which runs some background services at startup. 我有一个RunBackgroundServices类,它在启动时运行一些后台服务。 I need a new object BackgroundServices in it. 我需要一个新的对象BackgroundServices。 So I am using WebApplicationContext to get the bean. 所以我正在使用WebApplicationContext来获取bean。 But it's not working. 但这不起作用。

RunBackgroundServices.java 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 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());
        }

    }
}

I am getting the following error - 我收到以下错误-

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)

There is an easier way to perform bootstraping operations using Spring. 有一种使用Spring执行引导操作的简便方法。 All you have to do is have Spring bean that implements ApplicationListener<ContextRefreshedEvent> 您所要做的就是拥有实现ApplicationListener<ContextRefreshedEvent> Spring bean。

Your code would look like: 您的代码如下所示:

@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();
    }
}

Note the use of isRootApplicationContext . 注意isRootApplicationContext的使用。 It is needed if you have multiple application contexts and do no want to run the bootstrapping operation on each one. 如果您有多个应用程序上下文并且不想在每个应用程序上下文上运行引导操作,则需要它。

Using the above code you are bootstrapping using Spring's events, not the Servlet container's events. 使用以上代码,您将使用Spring的事件而不是Servlet容器的事件进行引导。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM