報錯概述
背景
單體專案升級微服務時,在BeforeSave_2250042
中呼叫了一個公共模組CommonVerifyHandler
的verifySeal()
方法,但是執行時顯示空指標異常
程式碼
根據斷點和報錯資訊可以看到是這裡出錯
大致報錯內容
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2715c179] was not registered for synchronization because synchronization is not active
JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@bd1cd86] will not be managed by Spring
==> Preparing: select count(1) from 簽約主體對映組織檢視 where 簽約主體編號=? and 組織編號 = ?
==> Parameters: QYZT-0001(String), ORG100000(String)
<== Columns: COUNT(1)
<== Row: 1
<== Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2715c179]
[http-nio-8075-exec-1] 01/26 21:51:18.703 ERROR [c.d.s.beforesave.BeforeSave_2250042] - 不涉及金額合同 儲存前事件處理異常,功能編號:2250042,單據ID:624060420265480192,錯誤資訊:{}
java.lang.NullPointerException: null
at com.dhcc.sdg.beforeinsert.CommonVerifyHandler.verifySeal(CommonVerifyHandler.java:41)
at com.dhcc.sdg.beforesave.BeforeSave_2250042.doBefore(BeforeSave_2250042.java:46)
at
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@79a446c1] was not registered for synchronization because synchronization is not active
JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@bd1cd86] will not be managed by Spring
==> Preparing: SELECT 集團內外 FROM 簽約方資訊檢視 WHERE 簽約方編號= ? AND DELETED_MARK =0
==> Parameters: GYS-2022-013436(String)
<== Columns: 集團內外
<== Row: 0
<== Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@79a446c1]
CommonVerifyHandler
@Component
public class CommonVerifyHandler {
@Autowired
public CommonVerifyHandlerMapper commonVerifyHandlerMapper;
/**
* 驗證印章 xlm
*/
public boolean verifySeal(BillData billData){
boolean result = true;
String PHY_ID = billData.getMasterData().get("PHY_SEAL_ID").toString().trim();
String PHY_PARTY_ID = getSignPhyId( billData);
System.out.println("PHY_ID:"+PHY_ID+",PHY_PARTY_ID:"+PHY_PARTY_ID);
System.out.println("開始執行commonVerifyHandlerMapper.sealInfo");
List<String> maps = commonVerifyHandlerMapper.sealInfo(PHY_ID, PHY_PARTY_ID);
System.out.println("map:"+maps);
if (maps == null || maps.isEmpty()) {
result = false;
}
return result;
}
}
錯誤一:
commonVerifyHandler
沒有加入@Component
註解被Spring管理
錯誤二:
在BeforeSave_2250042
中commonVerifyHandler
沒有被注入,相當於於commonVerifyHandler
是new出來的
在Spring管理的類中直接透過new
關鍵字來建立一個物件(模組)時,Spring容器本身是不會自動識別和管理這個新建立的物件的。Spring容器負責管理和裝配的是那些被它自己建立和初始化的bean。
使用new
來建立一個物件時,這個物件是在Spring容器的控制之外的,也就是說,它不會享受到Spring容器的任何服務,比如依賴注入、事務管理、AOP等。
如果想要Spring容器能夠識別並管理一個物件,需要將這個物件宣告為一個Spring bean。這可以透過在類上新增@Component
、@Service
、@Repository
或@Controller
等註解來實現,或者在Spring的配置檔案中顯式地宣告這個bean。
如果確實需要在Spring管理的類中建立一個新的物件,並且希望這個物件能夠享受到Spring容器的某些服務,你可以考慮使用ApplicationContext.getBean()
方法來從Spring容器中獲取這個物件,而不是直接使用new
來建立它。但是,這要求這個物件必須已經被宣告為一個Spring bean,並且已經被Spring容器初始化和管理。
另外,如果想要Spring容器能夠管理透過new
關鍵字建立的物件的某些方面,可以考慮使用AspectJ等AOP框架來在執行時動態地為這些物件新增額外的行為。但是,這通常會增加系統的複雜性和維護成本,因此應該謹慎使用。
總之,直接在Spring管理的類中透過new
來建立一個物件通常不是一個好的做法,除非有特殊的理由需要這樣做,並且瞭解這樣做可能帶來的後果。更好的做法是讓Spring容器來負責物件的建立和管理,這樣可以確保物件能夠享受到Spring容器提供的所有服務,並且更容易地進行單元測試和整合測試。