你的位置:首页 > Java教程

[Java教程]线程中无法实例化spring注入的服务的解决办法


  问题描述

  在Java Web应用中采用多线程处理数据,发现Spring注入的服务一直报NullPointerException。使用注解式的声明@Resource和

 

  解决办法:

  (1)主动实例化对象(不推荐)

 private TestService testService = new TestServiceImpl();

    每次加载这个类,就会重新创建一次,会过多耗费资源。

  (2)把线程设置为主程序的内部类,或者是利用线程的构造方法把bean传递过去

    主程序在web容器加载时,肯定是可以注入Spring bean的,那么将线程的实现类放在主程序的类中便可以“共享”Spring的bean,将生成线程的线程池定义在主程序的类中,每个线程的实现类作为内部类也定义在主程序中。

 

 1 public class Test implements InitializingBean{ 2  3   @Resource 4   private TestService testService 5  6   public void close(){ 7   } 8  9   public void afterPropertiesSet() throws Exception {10     // 利用构造方法把bean传递过去11     new Thread(testService);12   }13 }

 

 

 

  (3)用静态方法直接取的容器中的spring对象

    写一个SpringContextUtil类,实现ApplicationContextAware

 1 package com.test.utils; 2  3 import java.util.Locale; 4 import java.util.Map; 5  6 import org.springframework.beans.BeansException; 7 import org.springframework.context.ApplicationContext; 8 import org.springframework.context.ApplicationContextAware; 9 10 public class SpringContextUtil implements ApplicationContextAware {11 12  private static ApplicationContext applicationContext = null;13 14 15  public void setApplicationContext(ApplicationContext context) throws BeansException {16   applicationContext = context;17  }18 19 20  /**21   * 获取applicationContext对象22   * @return23  */24  public static ApplicationContext getApplicationContext() {25   return applicationContext;26  }27 28 29  /**30   * 根据bean的id来查找对象31   * @param id32   * @return33  */34 35  public static <T> T getBeanById(String id) {36   return (T) applicationContext.getBean(id);37  }38 39 40  /**41   * 根据bean的class来查找对象42   * @param c43   * @return44  */45  public static <T> T getBeanByClass(Class c) {46   return (T) applicationContext.getBean(c);47  }48 49 50  /**51   * 根据bean的class来查找所有的对象(包括子类)52   * @param c53   * @return54  */55  public static Map getBeansByClass(Class c) {56   return applicationContext.getBeansOfType(c);57  }58 59  public static String getMessage(String key) {60   return applicationContext.getMessage(key, null, Locale.getDefault());61  }62 63 }

      在applicationContext.

<bean id="springContextUtil" class="com.test.utils.SpringContextUtil"/>

      在线程中或线程调用的其他服务中可以主动加载bean,然后可以直接使用(testService必须是spring中配置的bean)

1 public void run() {2   TestService testService = (TestService ) SpringContextUtil.getBean("testService");3   testService.queryData(); 
4 }

       (4)看到网上说还可以通过BeanFactory来加载bean,没有去实现过,上个代码做个参考

 1 public class SpringBeanFactoryUtils implements BeanFactoryAware {  2   3   private static BeanFactory beanFactory = null;  4   private static SpringBeanFactoryUtils factoryUtils = null;  5     6   public void setBeanFactory(BeanFactory beanFactory) throws BeansException {  7     SpringBeanFactoryUtils.beanFactory = beanFactory;  8   }  9   public static BeanFactory getBeanFactory() { 10     return beanFactory; 11   } 12   public static SpringBeanFactoryUtils getInstance(){ 13     if(factoryUtils==null){ 14       //factoryUtils = (SpringBeanFactoryUtils)beanFactory.getBean("springBeanFactoryUtils"); 15       factoryUtils = new SpringBeanFactoryUtils(); 16     } 17     return factoryUtils; 18   } 19   public static Object getBean(String name){ 20     return beanFactory.getBean(name); 21   } 22 }