@Autowired의 기본적인 위치는 3가지가 있다. 필드 위, 생성자 위, 세터 위가 후보군이 되겠다.
우선 지난 번에 사용했던 세터위에서는 직관적으로 DI를 위해 사용이 되는것을 알아볼 수 있다.
하지만 필드 위는 해석하기가 난해하다. 이는 기본 생성자를 호출함으로 연결이 된다고 한다.
다음은 오버로딩된 생성자 위가 되는데 이 또한 Constructor DI에 관련된 것으로 해석할 수 있다.
실제로 해당 생성자 혹은 세터를 통하는지 확인을 위해 콘솔에 출력되도록 작성하고 시험해본다.
package spring.di.ui;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import spring.di.entity.Exam;
public class InlineExamConsole implements ExamConsole {
private Exam exam;
public InlineExamConsole() {
System.out.println("constructor");
}
public InlineExamConsole(Exam exam) {
this.exam = exam;
System.out.println("overload constructor");
}
@Override
public void print() {
System.out.printf("total is %d, avg is %f\n", exam.total(), exam.avg());
}
@Autowired
@Qualifier("exam1")
@Override
public void setExam(Exam exam) {
this.exam = exam;
System.out.println("setter");
}
}
@Autowired위치에 따라 호출이되는 생성자 및 세터가 달라짐을 확인할 수 있다. 또한 오버로드 생성자의 경우 @Qualifier의 의미가 모호하다며 경고하는데 이는 다음과 같이 사용하면 된다.
@Autowired
public InlineExamConsole(@Qualifier("exam1") Exam exam) {
this.exam = exam;
System.out.println("overload constructor");
}
위의 @Autowired 기능은 xml에서 객체 생성이 이루어 진 뒤에 실행이 되어야 하는데 만약 생성이 되지 않은 상황에서 실행하게되면 NullPointerException이 발생하겠다. 따라서 이를 방지하기 위해 required 옵션을 사용해본다.
우선 xml에서 객체 생성 빈즈를 주석처리하고 다음과 같이 @Autowired의 required 옵션을 false
로 두고 원하는 함수에 분기점(null일 경우 처리)를 작성하면 된다.
package spring.di.ui;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import spring.di.entity.Exam;
public class InlineExamConsole implements ExamConsole {
@Autowired(required = false)
@Qualifier("exam1")
private Exam exam;
public InlineExamConsole() {
System.out.println("constructor");
}
public InlineExamConsole(Exam exam) {
this.exam = exam;
System.out.println("overload constructor");
}
@Override
public void print() {
if(exam == null)
System.out.printf("total is %d, avg is %f\n", 0, 0.0);
else
System.out.printf("total is %d, avg is %f\n", exam.total(), exam.avg());
}
@Override
public void setExam(Exam exam) {
this.exam = exam;
System.out.println("setter");
}
}