背景描述:项目使用技术比较老,请求直接通过继承HttpServlet 接收,用spring,jdbcTemplate管理交互数据。
在servlet层,想要直接注入一个 TenantInfoService
例如:
TenantInfoService :
@Service public class TenantInfoService { private final static Logger log = LoggerFactory.getLogger(TenantInfoService.class); @Autowired private TenantInfoDao tenantInfoDao; public void updateDeviceIpByUuid(String uuid,String deviceIp){ log.error("进入TenantInfoService"); tenantInfoDao.updateDeviceIpByUuid(uuid,deviceIp); } }
TenantInfoDao :
@Repository public class TenantInfoDao {
@Autowired private JdbcTemplate jdbcTemplate;
public void updateDeviceIpByUuid(String uuid , String ip){ logger.error("开始执行更新"); jdbcTemplate.update("update t_device set D_DEV_IP=? where UUID = ?",new Object[]{ip,uuid}); logger.error("结束执行更新"); }
}
servlet层:
@Autowired private TenantInfoService tenantInfoService;
tenantInfoService.updateDeviceIpByUuid(uuid,ip);
问题:在使用是,一直抛出:空指针异常。
原因:由于servlet这个类并没有被spring容器管理,导致如果想使用注解注入属性失败。
于是,在调试时尝试使用判断:
if(tenantInfoService ==null){
tenantInfoService = new TenantInfoService();
}
以为new 一个对象,就可以使用里面的方法,报空出现在tenantInfoService类中。
于是在tenantInfoService再加判断:
if(tenantInfoDao ==null){
tenantInfoDao = new TenantInfoDao()
}
一直这样,最后连jdbcTemplate都判断了,用new JdbcTemplate(),这次不报空,报 NO DataSource;整个人直接崩溃,心态爆炸。
最后发现,如果想要用注解的方式在一个类中注入属性对象,该类也必须先被Spring容器管理。如在该类上加@Compent注解。而我的servlet类没有被spring管理,后面想要通过判断方式,自己new 属性对象。但是,自己new的对象仍然没有被Spring管理,所以即使自己new的对象中使用了注解注入属性,也仍然报空。
解决:可以使用ApplicationContext对象的getBean() 方法获取被spring管理的类。
可以参考工具类:
@Compent//被spring管理
public class BaseHolder implements ApplicationContextAware {
private static ApplicationContext applicationContext;
/**
* 服务器启动,Spring容器初始化时,当加载了当前类为bean组件后,
* 将会调用下面方法注入ApplicationContext实例
*/
@Override
public void setApplicationContext(ApplicationContext arg0) throws BeansException {
System.out.println("初始化了");
BaseHolder.applicationContext = arg0;
}
public static ApplicationContext getApplicationContext(){
return applicationContext;
}
/**
* 外部调用这个getBean方法就可以手动获取到bean
* 用bean组件的name来获取bean
* @param beanName
* @return
*/
@SuppressWarnings("unchecked")
public static
return (T) applicationContext.getBean(beanName);
}
}