1. 程式人生 > >不學無數——Spring注入後反射的空指標異常

不學無數——Spring注入後反射的空指標異常

Spring注入後反射的空指標異常

自動裝配是在spring環境下當使用該類的例項時由spring容器完成了類的例項化過程,包括對依賴物件的例項化過程。

而通過反射建立例項時,是根據你呼叫的建構函式完成的例項化過程,沒有容器的自動化建立例項了,所以需要自己對依賴物件進行注入。

所以依賴spring容器例項化和自己用反射例項化是兩種獨立的方式,不能相互滲透的。

1. 異常說明

在單元測試類中,要單獨測一個類中的private方法,所以想通過反射獲得此方法,解除私有限定,然後進行呼叫。此類為Service其中注入了許多的Mapper,因此在通過呼叫此私有方法的時候報了空指標異常的錯誤,錯誤如下:

java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.suixingpay.bap.service.impl.CheckAmsPmtAndPtsFlowServiceImplTest.testInvoke(CheckAmsPmtAndPtsFlowServiceImplTest.java:78)
	at com.suixingpay.bap.service.impl.CheckAmsPmtAndPtsFlowServiceImplTest.insertByList(CheckAmsPmtAndPtsFlowServiceImplTest.java:69)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
	at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
	at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
	at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
	at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.lang.NullPointerException
	at com.suixingpay.bap.service.impl.CheckAmsPmtAndPtsFlowServiceImpl.succesExitReove(CheckAmsPmtAndPtsFlowServiceImpl.java:247)
	... 36 more

注意最後面是由NullPointerException引起的。通過Debug進去以後發現是與資料庫互動的Mapper沒有注入進來。

單元測試程式碼如下:


    @Autowired
    private CheckAmsPmtAndPtsFlowServiceImpl checkAmsPmtAndPtsFlowServiceI;
    
    @Test
    public void insertByList()
            throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException,
            NoSuchFieldException {
        List<TBapCheckResultSave>  list = new ArrayList<>();
        Class cls = Class.forName("service.impl.CheckAmsPmtAndPtsFlowServiceImpl");
        Class[] cArg = new Class[5];
        cArg[0] = List.class;
        cArg[1] = boolean.class;
        cArg[2] = String.class;
        cArg[3] = String.class;
        cArg[4] = String.class;
        Method succesExitReove = cls.getDeclaredMethod("succesExitReove",cArg);
        succesExitReove.setAccessible(true);
        succesExitReove.invoke(checkAmsPmtAndPtsFlowServiceI,list,true,"1","1","2");
    }

此處有個知識點:在呼叫getDeclaredMethod()獲得指定的方法時,第二個引數是方法的傳參型別,包裝類和其基本型別是不一樣,例如下面方法為boolean,如果此時在上面 cArg[1] = Boolean.class;寫為其包裝型別的話,那麼就會報錯找不到此方法的錯誤

被反射的類中方法succesExitReove ()如下

	@Autowired
	private TMemAcPmtDtlPoMapper tMemAcPmtDtlPoMapper;
	
	private void succesExitReove(List<TBapCheckResultSave> result, boolean isFen, String sourceType, String opId, String batchId) {
		Iterator<TBapCheckResultSave> iteDownPtsNoCodeSuccces = result.iterator();
		while (iteDownPtsNoCodeSuccces.hasNext()) {
			int count;
			if (isFen) {
				count = tMemAcPmtDtlPoMapper.queryCheckFlow(bapCheckResult.getOutTransId());
			} else {
				count = tMemAcPmtDtlPoMapper.queryCheckFlow(bapCheckResult.getTransId());
			}
			bapCheckResult.setPmtCount(count);
			if (count > 0) {
				iteDownPtsNoCodeSuccces.remove();
			}
		}
	}

此處在Debug時發現tMemAcPmtDtlPoMapper為空。

2. 解決辦法

在單元測試類中@Autowired要用的Mapper,然後通過反射獲得上面方法要用到Mapper的變數,為其賦值即可

單元測試程式碼如下


    @Autowired
    private CheckAmsPmtAndPtsFlowServiceImpl checkAmsPmtAndPtsFlowServiceI;
    --在單元測試類中進行依賴注入Mapper
    @Autowired
    private TMemAcPmtDtlPoMapper tMemAcPmtDtlPoMapper;
    
    @Test
    public void insertByList()
            throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException,
            NoSuchFieldException {
        List<TBapCheckResultSave>  list = new ArrayList<>();
        Class cls = Class.forName("service.impl.CheckAmsPmtAndPtsFlowServiceImpl");
        Class[] cArg = new Class[5];
        cArg[0] = List.class;
        cArg[1] = boolean.class;
        cArg[2] = String.class;
        cArg[3] = String.class;
        cArg[4] = String.class;
        Field a1 = cls.getDeclaredField("tMemAcPmtDtlPoMapper");
        Method succesExitReove = cls.getDeclaredMethod("succesExitReove",cArg);
        succesExitReove.setAccessible(true);
        --在此為反射的類進行賦值Mapper
        Field a1 = cls.getDeclaredField("tMemAcPmtDtlPoMapper");
        a1.setAccessible(true);
        a1.set(checkAmsPmtAndPtsFlowServiceI,tMemAcPmtDtlPoMapper);
        succesExitReove.invoke(checkAmsPmtAndPtsFlowServiceI,list,true,"1","1","2");
    }

相關推薦

無數——Spring注入反射指標異常

Spring注入後反射的空指標異常 自動裝配是在spring環境下當使用該類的例項時由spring容器完成了類的例項化過程,包括對依賴物件的例項化過程。 而通過反射建立例項時,是根據你呼叫的建構函式完成的例項化過程,沒有容器的自動化建立例項了,所以需要自己

Spring注入SessionFactory的指標異常

自己的錯誤在於,new的Dao例項,進行呼叫,以至於出現Dao中注入的Sessionfactory空指標。 在hibernate+spring配置過程中,應注意幾點: 1、不能直接new一個DAO的例項,而應該通過spring的配置檔案自動初始化session be

spring整合mybatis時報指標異常:service注入到Mapper介面的例項化物件(已解決)

解決方法在下邊↓↓問題一:    mabite中Mapper介面的例項化物件找不到,顯示為NULL這是我的配置,還有執行時報的錯這幾個檔案都是使用反向工程生成的,應該沒有錯。執行結果顯示tUserMapper為null問題二:還有,使用ssm框架寫web工程的時候還出過這麼一

Test測試:Spring 注入失敗,指標

問題描述 使用註解無法注入例項,出現空指標異常。若不用註解,直接new一個例項,可以正常執行 控制檯輸出 異常發生點 @Resource private UserService userService; priv

Spring自動裝配報指標異常

這幾天在學Spring的自動裝配,自己動手做一個小專案,但是被一個空指標異常卡住了。 啟動的時候彈出index.jsp,這是一個登陸頁面: <%@ page language="java" contentType="text/html; charset

eclipse 中Spring 使用@Autowired 報指標異常

最近在學生Spring框架,這算是一個很低階的錯誤,寫出來希望不要有人犯和我一樣的錯誤,執行下面的例子時,使用了@autowired註釋,但是報出了空指標異常,例子程式如下: TextEditor SpellChecker MainApp: 執行後報了一個空指

關於執行緒呼叫Spring註解物件報指標異常

本人剛接觸執行緒方面,今天在寫一個埠監控的時候遇到一個問題,就是線上程中,呼叫spring注入的物件時,報空指標異常. 而且只在這個類中報這個問題. 在controller類中,能正常執行,所以應該能排除注入失敗或者配置錯誤的因素. 百思不得其解,暫時先記下問題,以

Myeclipse啟動tomcat指標異常

今天早上吃完早餐來公司上班,開啟電腦,輸入密碼,123456。。。。。嗯……,再開啟myeclipse,duang。。。duang。。。duang。。。。tomcat空指標異常,tmd我這暴脾氣昨天還好好的今天就給我來這一套,擱我五年前那暴脾氣,早就卸了你,時間成就了我的成熟

無數——反射和內省的區別

反射和內省的區別 內省是基於反射實現的,主要用來操作JavaBean,通過內省可以很方便的動態獲得bean的set/get方法,屬性,方法名,他相當於是反射的工具類一樣 1. 反射 反射其實簡單來說就是通過類的名字獲得對於這個類的描述,這種描述包括方法、構造器、屬性的描述。

無數——初識反射

反射:執行時的類資訊 執行時型別資訊使得你可以在程式執行時發現和使用型別資訊 1. Class物件 通過Class物件可以在執行時發現一個物件完整的類繼承結構 類是程式的一部分,每一個類都會有一個Class物件。換句話說既每編寫一個新的類,就會產生一個Cl

無數——Java中IO和NIO

JAVA中的I/O和NIO I/O 問題是任何程式語言都無法迴避的問題,可以說 I/O 問題是整個人機互動的核心問題,因為 I/O 是機器獲取和交換資訊的主要渠道。在當今這個資料大爆炸時代,I/O 問題尤其突出,很容易成為一個性能瓶頸。 什麼是I/O I/O ? 或者輸入/輸出

無數——SpringBoot入門Ⅷ

SpringBoot--Actuator 1. 初識Actuator 在開發過程中,專案被放置到生產伺服器上執行時,有可能需要我們全方位的監控應用服務的執行情況。此時SpringBoot提供了Actuator模組進行監控和管理 2. 使用方法 在gradle中新增依賴 compi

無數——SpringBoot入門Ⅶ

SpringBoot 1.建立自己的Auto-configuration 無論是在公司中你想開發自己的一套框架,定製一些東西,或者是在開源網站中分享自己做的一些東西。你可能想要開發屬於自己的Auto-configuration。Auto-configuration的類能夠捆綁到外部的jar包

無數——SpringBoot入門VI

SpringBoot 1 連線資料庫 Spring框架為連線資料庫提供了許多的幫助,從JDBC連線到使用JdbcTemplate完成元素之間的對映技術。例如Hibernate、Spring Data提供了更高級別的功能,建立Repository的實現,用介面中的方法和xml檔案具體SQL的對

無數——SpringBoot入門V

SpringBoot 1.開發一個Web程式 SpringBoot是非常適合開發Web應用的,因為他內嵌有Tomcat、Jetty、Undertow或者Netty。大部分的應用可以通過載入spring-boot-starter-web模組能夠快速的建立並啟動一個Web應用。 1.1Spr

無數——SpringBoot入門IV

SpringBoot 1.Profiles Spring Profiles能夠在不同的環境中使不同的應用配置生效。@Component和@Configuration兩個註解都能夠通過@Profiles來標記。下面是例子: @Configuration @Profile("buxuewus

無數——SpringBoot入門Ⅲ

SpringBoot-外部資源的配置 1.外部資源的配置優先順序 為了能夠在不同的環境執行不同的配置檔案,或者有些程式碼的一些變數是跟隨著環境的改變而改變的,這時候就需要在外部做一些配置。SpringBoot允許這麼做,並且有一套配置規則。可以通過@Value註解進行將一些變數動態的取出來。

無數——SpringBoot入門Ⅱ

SpringBoot 1.Starters Starters是一套技術,是什麼技術呢?是SpringBoot整理出來,人們經常要用的技術。有了starters人們在想要使用這些技術的時候,就不用扒之前的老程式碼將那些依賴啊或者配置的都拷貝過來,只需要加上SpringBoot提供的依賴就行,它

無數——SpringBoot入門Ⅰ

SpringBoot 1.SpringBoot簡介 在剛接觸SSM框架的時候,想必都會被這個框架的配置檔案所煩擾,需要自己手動配置的東西非常多,哪怕有些東西自己不需要也是需要配置的。而SpringBoot此時就應運而生,減少了大家的配置過程。相信都聽過“約定優於配置”的這樣一句話,就是說系統

無數——裝飾模式

裝飾模式 在開始之前 我們可以用一個簡單的例子引出來裝飾模式,在小的時候,相信大家都有過這樣的經歷:小學每年會有好幾次的考試,如果有一次成績非常差,而且考完以後學校會有個很損的招,就是打印出來成績單,然後讓家長簽字。那麼拿著這個成績單,肯定是不會直接告訴家長成績什麼的,肯定是會加一些,例如,