背景描述:項目使用技術比較老,請求直接通過繼承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 <T>T getBean(String beanName){
return (T) applicationContext.getBean(beanName);
}
}