springboot的依賴注入報null的問題


最近使用springboot開發項目,使用到了依賴注入,頻繁的碰到注入的對象報空指針,錯誤如下

java.lang.NullPointerException: null
    at com.mayihc.audit.controller.MaterialNkDetailController.download(MaterialNkDetailController.java:72)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:877)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:783)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:974)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:866)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:851)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:61)
    at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
    at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
    at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
    at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
    at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449)
    at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365)
    at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
    at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
    at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:387)
    at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362)
    at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:123)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:109)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:496)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1468)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Unknown Source)

第一次碰見的情況是:在new出來的對象中使用@Autowired來獲取注入的對象

 DateCheckUtils dateCheckUtils = new DateCheckUtils();

我要在這個類中使用依賴注入,剛開始寫的是注入方式如下

public class DateCheckUtils {
     @Autowired
    private CompanyInfoService companyInfoService;
 @Autowired    
private MaterialNkDetailService materialNkDetailService;
    

.........
}

這是會報空指針異常,后倆修改代碼就解決了問題,修改后的代碼如下

1、創建一個類實現ApplicationContextAware,用來獲取applicationContext 和bean

package com.mayihc.audit.core.utils;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class SpringUtils implements ApplicationContextAware{

    private static ApplicationContext applicationContext = null; 

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if(SpringUtils.applicationContext == null){  
            SpringUtils.applicationContext  = applicationContext;  
        } 
        
    }
    //獲取applicationContext  
    public static ApplicationContext getApplicationContext() {  
        return applicationContext;  
    }  
 
    //通過name獲取 Bean.  
    public static Object getBean(String name){  
        return getApplicationContext().getBean(name);  
    }  
 
    //通過class獲取Bean.  
    public static <T> T getBean(Class<T> clazz){  
        return getApplicationContext().getBean(clazz);  
    }  
 
    //通過name,以及Clazz返回指定的Bean  
    public static <T> T getBean(String name,Class<T> clazz){  
        return getApplicationContext().getBean(name, clazz);  
    }  


}

2、在new出來的DateCheckUtils類中獲取ApplicationContext的實例

public class DateCheckUtils {
  //獲取ApplicationContext的實例
    private ApplicationContext applicationContext = SpringUtils.getApplicationContext();
  //通過applicationContext和反射機制來獲取對象
    private CompanyInfoService companyInfoService = applicationContext.getBean(CompanyInfoService.class);
    private MaterialNkDetailService materialNkDetailService = applicationContext.getBean(MaterialNkDetailService.class);
    private MaterialNkLogbookService materialNkLogbookService = applicationContext
            .getBean(MaterialNkLogbookService.class);
    private MaterialNkLedgerService materialNkLedgerService = applicationContext.getBean(MaterialNkLedgerService.class);
    private MaterialGjChangeDetailService materialGjChangeDetailService = applicationContext
            .getBean(MaterialGjChangeDetailService.class);
    private MaterialGjLedgerService materialGjLedgerService = applicationContext.getBean(MaterialGjLedgerService.class);
    .....

}

這樣就可以獲取到要注入的對象

報空指針的原因:當對象聲明為bean組件的時候,他是交給spring容器去管理的,容器會幫你進行初始化;但是如果使用new方法來調用對象是=時,會跳過spring容器生成的對象,這是就無法進行初始化,所以在調用的時候就會出現對象為null,並且對象里面以注入方式引用的對象也為null,被聲明為bean對象的組件必修使用注入的方式進行調用。

 

上述的問題也可以通過將  DataCheckUtils dataCheckUtils=new DataCheckUtils();改為:

@Autowired

private DataCheckUtils dataCheckUtils;來實現

 

第二種碰見null的情況:在同一個類中只有某個方法在被前端調用的時候報null,其余方法都正常。

錯誤代碼如下

 1  @RequestMapping("/download")
 2     private void download(HttpServletResponse response, MaterialNkDetail materialNkDetail) throws Exception {
 3         SysUser u = (SysUser) SecurityUtils.getSubject().getPrincipal();
 4         if(!"1".equals(u.getType())) {
 5             materialNkDetail.setCompanyId(u.getCompanyInfoId());
 6         } 
 7         CompanyInfo companyInfo = companyInfoService.selectByPrimaryKey(u.getCompanyInfoId());
 8         if(companyInfo == null) {
 9             companyInfo = new CompanyInfo();
10             companyInfo.setFullName("全部車輛");
11         }
12     .....
13 }    

當運行這個方法時,注入的對象總是報null,經排查后,此方法是用private修飾的,改為public修飾后就OK了。

原因:容器掃描bean生成代理類的時候,public和protected方法可以被正常代理,而private方法不會被正常代理,屬性的注入是在代理類中完成的,所以public和protected方法獲取的注入屬相是完成注入的屬性,private方法獲取的是為完成注入的屬性,所以是null

 
       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM