spring的bean在多线程中注入的问题

问题描述

在spring中,如果需要在异步线程中注入bean,会发现bean是空的情况。原因据说是spring bean 出于线程安全考虑,不得注入bean至线程类(Runnable)。
代码如下:

public class DealThreadTask implements Runnable{



    @Autowired
    private DealService dealService;


    @Override
    public void run() {

    //  DealService dealService=holder.getBean("dealService");
        System.out.println("dealService-->"+dealService);
        dealService.deal("andy", "李琳", 100d);


    }

}

说明spring在DealThreadTask中未能将dealService注入进去。

解决方法

Spring API 中有ApplicationContextAware 这个接口,实现了这个接口的类,可以在容器初始化完成中获得容器,从而可以获得容器中所有的bean。

public class ApplicationContextHolder implements ApplicationContextAware {

     private static ApplicationContext applicationContext;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ApplicationContextHolder.applicationContext=applicationContext;
        System.out.println("applicationContext---->"+applicationContext);
    }

     public static <T> T getBean(Class<T> clazz){
         return applicationContext.getBean(clazz);
   }

     public static Object getBean(String name) {

         if (applicationContext==null) {
             System.out.println("applicationContext为空");
        }
            return  applicationContext.getBean(name);

     }
}

然后,在xml配置文件中,需要将这个类配置进去。

<bean id="applicationContextHolder"  class="com.test.spring.tx.multi.ApplicationContextHolder"></bean>

这样,在异步线程中的DealThreadTask 中,通过手动的applicationContextHolder的getBean方法,就可以获取所需要的bean。

public class DealThreadTask implements Runnable{



    @Autowired
    private ApplicationContextHolder holder;



    @Override
    public void run() {

        DealService dealService=holder.getBean("dealService");
        System.out.println("dealService-->"+dealService);
        dealService.deal("andy", "李琳", 100d);


    }

}

补充:Spring中出现:No bean named ‘XXX’ available问题解决

注解如果没有指定bean的名字,默认为小写开头的类名。例如类名是ProvincialServiceImpl,则spring返回provincialServiceImpl的bean名。