Timer定时器在项目初始化的时候注入service为null

问题

在自定义的timer中需要注入业务类接口(service)完成相应的操作,但是在通过@Autowired注入后为null,导致在执行业务操作的时候报空指针错误。

源代码

需要做一个定时更新数据库的程序,因为比较简单,所以选择了Timer。
定义更新数据定时器UpdateDbTimerWorker

public class UpdateDbTimerWorker extends TimerTask {
   @Autowired
    private UpdateDbService updateDbService;
    
   @Override
    public void run() {
        if (TaskQueue.isBlock()) {
            UpdateDbTask task = null;
            try {
                task = TaskQueue.take();
                if (task != null) {
                    String type = task.getType();
                    if ("insert".equals(type)) {
                        updateDbService.insert(task);
                    } else {
                        updateDbService.update(task);
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
        }
    }
}

UpdateDbService

public interface UpdateDbService {

    /**
     * 插入
     * @param task
     */
    void insert(UpdateDbTask task) throws ClassNotFoundException, InvocationTargetException, IllegalAccessException, InstantiationException;

    /**
     * 更新
     * @param task
     */
    void update(UpdateDbTask task) throws ClassNotFoundException, InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchMethodException;
}

为了获取到这个注入对象,只能我们手动注入了,就是通过获取上下文对象,然后再对这个对象进行解析,然后取出自己所要的那个对像。

SpringContextUtil工具类

@Component
public class SpringContextUtil implements ApplicationContextAware {

    /**
     * Spring应用上下文环境
     */
    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringContextUtil.applicationContext = applicationContext;
    }

    /**
     * @return ApplicationContext
     */
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    /**
     * 获取对象
     *
     * @param beanName
     * @return Object 一个以所给名字注册的bean的实例
     */
    public static Object getBean(String beanName){
        return applicationContext.getBean(beanName);
    }

    /**
     * 获取类型为requiredType的对象
     *
     * @param clz
     * @return
     * @throws BeansException
     */
    public static <T> T getBean(Class<T> clz) throws BeansException {
        @SuppressWarnings("unchecked")
        T result = (T) applicationContext.getBean(clz);
        return result;
    }


    /**
     * @param name
     * @return Class 注册对象的类型
     * @throws NoSuchBeanDefinitionException
     */
    public static Class<?> getType(String name) throws NoSuchBeanDefinitionException {
        return applicationContext.getType(name);
    }

    /**
     * 如果给定的bean名字在bean定义中有别名,则返回这些别名
     *
     * @param name
     * @return
     * @throws NoSuchBeanDefinitionException
     */
    public static String[] getAliases(String name) throws NoSuchBeanDefinitionException {
        return applicationContext.getAliases(name);
    }
}

解决

在定时器中通过SpringContextUtil获取bean

public class UpdateDbTimerWorker extends TimerTask {

     private UpdateDbService updateDbService = SpringContextUtil.getBean(UpdateDbServiceImpl.class);
     后略...

}
posted @ 2022-09-29 14:20  leepandar  阅读(140)  评论(0编辑  收藏  举报