@Autowired 빈은 다른 빈의 생성자에서 참조 될 때 null입니다.


90

아래는 ApplicationProperties bean을 참조하고 시도하는 코드 스 니펫입니다. 생성자에서 참조하면 null이지만 다른 메서드에서 참조하면 괜찮습니다. 지금까지 다른 클래스에서이 자동 연결 빈을 사용하는 데 아무런 문제가 없었습니다. 그러나 다른 클래스의 생성자에서 이것을 사용하려고 시도한 것은 이번이 처음입니다.

아래 코드 스 니펫에서 applicationProperties는 생성자에서 호출 될 때 null이지만 convert 메서드에서 참조 될 때는 그렇지 않습니다. 내가 뭘 놓치고 있니

@Component
public class DocumentManager implements IDocumentManager {

  private Log logger = LogFactory.getLog(this.getClass());
  private OfficeManager officeManager = null;
  private ConverterService converterService = null;

  @Autowired
  private IApplicationProperties applicationProperties;


  // If I try and use the Autowired applicationProperties bean in the constructor
  // it is null ?

  public DocumentManager() {
  startOOServer();
  }

  private void startOOServer() {
    if (applicationProperties != null) {
      if (applicationProperties.getStartOOServer()) {
        try {
          if (this.officeManager == null) {
            this.officeManager = new DefaultOfficeManagerConfiguration()
              .buildOfficeManager();
            this.officeManager.start();
            this.converterService = new ConverterService(this.officeManager);
          }
        } catch (Throwable e){
          logger.error(e);  
        }
      }
    }
  }

  public byte[] convert(byte[] inputData, String sourceExtension, String targetExtension) {
    byte[] result = null;

    startOOServer();
    ...

아래는 ApplicationProperties의 일부입니다 ...

@Component
public class ApplicationProperties implements IApplicationProperties {

  /* Use the appProperties bean defined in WEB-INF/applicationContext.xml
   * which in turn uses resources/server.properties
   */
  @Resource(name="appProperties")
  private Properties appProperties;

  public Boolean getStartOOServer() {
    String val = appProperties.getProperty("startOOServer", "false");
    if( val == null ) return false;
    val = val.trim();
    return val.equalsIgnoreCase("true") || val.equalsIgnoreCase("on") || val.equalsIgnoreCase("yes");
  }

답변:


181

Autowiring (Dunes 주석의 링크)은 객체 생성 후에 발생합니다. 따라서 생성자가 완료 될 때까지 설정되지 않습니다.

일부 초기화 코드를 실행해야하는 경우 생성자의 코드를 메서드로 가져 와서 해당 메서드에 @PostConstruct.



링크 주셔서 감사합니다. 쉽게 찾을 수 있도록 답변에 추가하겠습니다.
nicholas.hauschild

2
감사합니다. "필드는 빈 생성 직후에 주입됩니다."라는 중요한 문장을 아직 접하지 못했습니다. @PostConstruct 주석을 시도했으며 정확히 필요한 것입니다.
hairyone

@PostConstruct에 대한 링크를 게시하는 것이 좋을 것이다 static.springsource.org/spring/docs/3.0.0.M3/reference/html/...을
Timofey

@ 팀 감사합니다! Spring 3.2 버전에 대한 답변 링크를 업데이트했으며 링크의 Spring 3.2 버전도 추가했습니다.
nicholas.hauschild 2013

44

생성시에 의존성을 주입하려면 생성자에 @Autowired이와 같은 주석을 표시해야합니다 .

@Autowired
public DocumentManager(IApplicationProperties applicationProperties) {
  this.applicationProperties = applicationProperties;
  startOOServer();
}

2
사실 저는 이것이 선호하는 대답이어야한다고 생각합니다. 생성자 기반 종속성 주입 접근 방식은 필수 구성 요소에 매우 적합합니다. 이 접근 방식을 사용하면 스프링 프레임 워크는 구성 요소에 대한 주기적 종속성도 감지 할 수 있습니다 (A에서 B는 B에, B는 C에, C는 A에 따라). setter 또는 autowired 필드를 사용하는 주입 스타일은 완전히 초기화되지 않은 빈을 필드에 주입하여 상황을 좀 더 복잡하게 만들 수 있습니다.
Seakayone
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.