转载至:https://my.oschina.net/ytliyang/blog/644533
最近在做一个Spring+MyBatis的一个项目,其中用到了Redis的存储,然后遇到问题是这样的:
RedisTask是通过定时器来每分钟像数据库里推送的,于是就有了
public class RedisTask extends Task {
public void execute(TaskExecutionContext executor) throws RuntimeException {
……
……
}
}
然后在定时器的任务中通过对Redis的调用,推送到本地数据库
OrderService orderService = new OrderService();
Order order = new Order();
int num = orderService.add(order);
System.out.println("插入条数为:" + num);
那么问题来了,tomcat开始没次调用定时器的RedisTask就开始报错,debug发现orderService为null,也就是说service根本就没有注入。
然后我就在Spring的配置文件里查看标注问题,发现根本没问题,再然后发现此方法继承了Task,于是乎恍然大悟
:定时器继承了Task之后,在定时器调用此方法后会直接执行execute方法,来不急执行标注进行注入。
@Resource
private OrderService orderService;
然后解决方案:
1、引入ApplicationContextUtil的工具类
- package com.wyy.snail.core.util;
-
- import org.springframework.beans.BeansException;
- import org.springframework.beans.factory.NoSuchBeanDefinitionException;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.ApplicationContextAware;
- import org.springframework.stereotype.Component;
-
- /**
- * Spring的工具类,用来获得配置文件中的bean
- *
- * @author penghy
- * @date 2014-04-08
- *
- */
- @Component
- public class SpringContextUtils implements ApplicationContextAware {
-
- private static ApplicationContext applicationContext = null;
-
- /***
- * 当继承了ApplicationContextAware类之后,那么程序在调用 getBean(String)的时候会自动调用该方法,
- * 不用自己操作
- */
- public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
- SpringContextUtils.applicationContext = applicationContext;
- }
-
- public static ApplicationContext getApplicationContext() {
- return applicationContext;
- }
-
- /***
- * 根据一个bean的id获取配置文件中相应的bean
- *
- * @param name
- * @return
- * @throws BeansException
- */
- public static Object getBean(String name) throws BeansException {
- return applicationContext.getBean(name);
- }
-
- /***
- * 类似于getBean(String name)只是在参数中提供了需要返回到的类型。
- *
- * @param name
- * @param requiredType
- * @return
- * @throws BeansException
- */
- public static <T> T getBean(String name, Class<T> requiredType) throws BeansException {
- return applicationContext.getBean(name, requiredType);
- }
-
- /**
- * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true
- *
- * @param name
- * @return boolean
- */
- public static boolean containsBean(String name) {
- return applicationContext.containsBean(name);
- }
-
- /**
- * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。
- * 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)
- *
- * @param name
- * @return boolean
- * @throws NoSuchBeanDefinitionException
- */
- public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
- return applicationContext.isSingleton(name);
- }
-
- /**
- * @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);
- }
- }
2、在execute方法中以这种方式进行对service进行注入
OrderService orderService = (OrderService)ApplicationContextUtil.getBean("orderService");
注:在service的接口的@Service标注中必须写明注入的名字。
@Service("orderService")
public class OrderServiceImpl implements OrderService {