在 Spring 启动时注入 bean

Abh*_*odi 0 spring dependency-injection

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

运行后台服务.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();
    }

}
Run Code Online (Sandbox Code Playgroud)

后台服务.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());
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

我收到以下错误 -

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)
Run Code Online (Sandbox Code Playgroud)

geo*_*and 5

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

您的代码如下所示:

@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();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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