1 분 소요

Annotation

종류

image-20241021205900019

XML로 설정할 때의 모듈 변경

설정 파일을 XML로 따로 빼주는 이유는 소스코드를 바꾸지 않고 결합 상태를 바꾸기 위해서이다.

예를 들어 인터페이스 B를 구현하고 있는 객체 B2와 B를 사용하고 있는 객체 S를 xml 설정으로 빼면 다음과 같다.

<bean id="b" class="data.B2"/>
<bean id="console" class="service.S">
	<property name="b" ref="b"/>	
</bean>

B2를 새로운 객체 B3로 바꾸기 위해서는 XML 파일을 다음과 같이 고치면 된다.

<bean id="b" class="data.B3"/> // 바뀐 부분
<bean id="console" class="service.S">
	<property name="b" ref="b"/>	
</bean>

@Autowired

처음에는 설정 파일을 따로 빼는 형식에서 코드에 설정파일을 심는 어노테이션이 등장하게 된다.

<bean id="exam" class="spring.di.entity.NewlecExam" p:kor="10" p:eng="10"/>
<bean id="console" class="spring.di.ui.InlineExamConsole">
    // @Autowired
    // @private Exam exam;
	<property name="exam" ref="exam"/> // Autowired으로 뺄 라인
</bean>

image-20241021213132611

처음에 bean 객체 안에서

<property name="exam" ref="exam"/>

위와 같이 exam을 세팅했지만 해당 의존성을 @Autowired로 빼준다.

하지만 어떤 근거로 @Autowired가 exam을 찾는가?

  1. 자료형(Exam)

    id명이 모호하지 않을때는 자료형을 기준으로 세팅한다.

    // setter 메서드
    @Autowired
    @Override
    public void setExam(Exam exam) {
        this.exam = exam
    }
    
    <bean class="spring.di.entity.NewlecExam" p:kor=10 p:eng=10/> <!--id를 쓰지 않아도 클래스를 통해 찾음-->
    <bean id="exam" class="spring.di.entity.NewlecExam" p:kor=10 p:eng=10/>
    
    // main.java
    ExamConsole console = (ExamConsole) context.getBean("console");
    console.print();
    
  2. 변수 이름(exam)

    평소에는 id명을 통해 찾지만, id명을 지정해주는 @Qualifier라는 annotation이 있다.

    // setter.java
    @Autowired
    @Override
    @Qualifier("exam1")
    public void setExam(Exam exam) {
        this.exam = exam
    }
    
    <bean id="exam1" class="spring.di.entity.NewlecExam" p:kor=10 p:eng=10/>
    <bean id="exam2" class="spring.di.entity.NewlecExam" p:kor=10 p:eng=10/>
    
    // main.java
    ExamConsole console = (ExamConsole) context.getBean("console");
    console.print();
    
    # 출력결과
    total is 20, avg is 10.000000
    
    • 기본 생성자

      public class InlineExamConsole implements ExamConsole {
          @Autowired
          @Qualifier("exam1")
          private Exam exam;
           
          public InlineExamConsole() {
              System.out.println("constructor");
          }
      }
      

      두 Annotation을 기본생성자 위에 불러왔을 때는 기본생성자로 바인딩되며 결과는 다음과 같다.

      # 출력결과
      constructor
      total is 20, avg is 10.000000
      
    • 오버로드 생성자

      public class InlineExamConsole implements ExamConsole {
          @Autowired
          public InlineExamConsole(@Qualifier("exam1") Exam exam) {
              System.out.println("overloaded constructor");
              this.exam = exam;
          }
      }
      

      @Qualifier annotation은 생성자의 매개변수 자리에 와야 하며 결과는 다음과 같다.

      # 출력결과
      overloaded constructor
      total is 20, avg is 10.000000
      

required=false

만약 @Autowired에 required=false 옵션을 넣는다면 spring이 빈을 찾지 못하더라도 null값을 주입하고 프로그램이 정상적으로 실행된다.

// XML파일에 객체를 만들지 않았다고 가정
public class InlineExamConsole implements ExamConsole {
    @Autowired(required = false) // xml에 객체가 없어도 일단 null로 실행
    @Qualifier("exam1")
    private Exam exam;

    public InlineExamConsole() {
        System.out.println("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());
        }
    }
}
# 출력결과
constructor
total is 0, avg is 0.000000

댓글남기기