兩個原因導致Spring @Autowired注入的組件為空



@

原文作者:Steve Claridge   原文鏈接:https://www.moreofless.co.uk/spring-mvc-java-autowired-component-null-repository-service/


譯文


Spring框架大量使用了控制反轉(IoC),讓你可以進行類的注入,而不必擔心它們的作用域,生存周期或者回收。

大家遇到的一個常見錯誤是,當自動裝配一個類,嘗試調用該類的方法時,發現該類的實例為null而導致空指針異常。那么,為什么Spring沒有自動注入類呢?有兩個可能的原因:


你手動實例化了一個類

@Controller
public class Controller {

  @GetMapping("/example")
  public String example() {
    MyService my = new MyService();
    my.doStuff();
  }
}

@Service
public class MyService() {

  @Autowired
  MyRepository repo;

  public void doStuff() {
    repo.findByName( "steve" );
  }
}

 

@Repository
public interface MyRepository extends CrudRepository<My, Long> {

  List<My> findByName( String name );
}

你好,2005呼叫並要求返回他們的代碼。好吧,IoC就像是街上的帥小伙子一樣,如果你使用的是Spring(自動注入),則需要一直使用它。這是Controller, Service 和 Repository的代碼片段,它們將導致NullPointerException。

@Controller
public class Controller {

  @GetMapping("/example")
  public String example() {
    MyService my = new MyService();
    my.doStuff();
  }
}

@Service
public class MyService() {

  @Autowired
  MyRepository repo;

  public void doStuff() {
    repo.findByName( "steve" );
  }
}

當它嘗試訪問MyRepository自動連接的存儲庫時,這將在Service中引發NullPointerException,這不是因為Repository的連接有任何問題,而是因為你使用MyService my = new MyService()手動實例化了MyService。要解決此問題,需要自動注入MyService:

@Controller
public class Controller {

  @Autowired
  MyService service;

  @GetMapping("/example")
  public String example() {
    service.doStuff();
  }
}

@Service
public class MyService() {

  @Autowired
  MyRepository repo;

  public void doStuff() {
    repo.findByName( "steve" );
  }
}

@Repository
public interface MyRepository extends CrudRepository<My, Long> {

  List<My> findByName( String name );
}

你忘記在某個類使用組件注解或者它的擴展注解

Spring使用組件掃描來查找需要自動注入並放入到IoC容器中的類。基本上,Spring將掃描項目的類路徑(或你指定的路徑),找到所有@Component注解的類並將其用於自動裝配。因此,如果你忘記注解一個類,則該類將不能自動注入,當你嘗試使用它時,將得到一個空的實例,從而導致NullPointerException。

@ Service,@ Repository和@Controller都是@Component特殊情景下的子注解,因此要自動注入的任何類都必須使用其中之一進行注釋。否則,自動注入將導致實例為空:

public class MyService {

  public void doStuff() {
  }
}

這樣的是沒有問題的:

@Service
public class MyService {

  public void doStuff() {
  }
}



本文僅是閱讀英文文檔練手,原文如下:


原文

Two reasons why your Spring @Autowired component is null

The Spring framework makes heavy use of Inversion of Control (IoC) to let you inject classes without having to worry about their scope, lifetime or cleanup.

A common error people hit is when they autowire a class and when they try to call a method on it find that it is null and they get a NullPointerException. So why didn’t Spring auto-wire your class for you? Here’s two possible reasons:


YOU INSTANTIATED THE A CLASS MANUALLY

Hi, 2005 called and asked for their code back. Yeah, OK, IoC is like the cool kid on the block and if you are using Spring then you need to be using it all the time. Here’s a code snippet of a Controller, Service and Repository that will result in a NullPointerException.

@Controller
public class Controller {

  @GetMapping("/example")
  public String example() {
    MyService my = new MyService();
    my.doStuff();
  }
}

@Service
public class MyService() {

  @Autowired
  MyRepository repo;

  public void doStuff() {
    repo.findByName( "steve" );
  }
}

 

@Repository
public interface MyRepository extends CrudRepository<My, Long> {

  List<My> findByName( String name );
}

This will throw a NullPointerException in the service class when it tries to access the MyRepository auto-wired Repository, not because there is anything wrong with the wiring of the Repository but because you instantiated MyService() manually with MyService my = new MyService(). To fix this auto-wire the Service as well:

@Controller
public class Controller {

  @Autowired
  MyService service;

  @GetMapping("/example")
  public String example() {
    service.doStuff();
  }
}

@Service
public class MyService() {

  @Autowired
  MyRepository repo;

  public void doStuff() {
    repo.findByName( "steve" );
  }
}

@Repository
public interface MyRepository extends CrudRepository<My, Long> {

  List<My> findByName( String name );
}

YOU FORGOT TO ANNOTATE A CLASS AS A COMPONENT OR ONE OF ITS DESCENDANTS

Spring uses component scanning to find the classes that it needs to auto-wire and insert into classes for IoC. Basically, Spring is going to scan the project’s classpath (or paths you specified), find all of the @Component classes and make them available for auto-wiring. So if you forget to annotate a class it will not be auto-wired and when you try and use it you will get a null and a NullPointerException.

@Service, @Repository and @Controller are all specializations of @Component, so any class you want to auto-wire needs to be annotated with one of them. So auto-wiring this will cause a null:


public class MyService {

  public void doStuff() {
  }
}

but this will work fine

@Service
public class MyService {

  public void doStuff() {
  }
}

------------恢復內容結束------------


免責聲明!

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



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