Annotation 사용 이유
XML로 설정할 때 모듈 변경 방법에서
새로운 객체를 생성해서 결합되게 하기 위해서는 xml을 사용했을 경우에는 xml를 수정해야 하는 불편함이 있었다.
객체를 바꾸면 설정을 바로 바꾸기 위해서 코드에다가 메타데이터를 포함했다.
인터페이스에 연결할때 새로 생성한 객체에 @Component Annotation를 붙여주면 알아서 설정 파일 없이 객체화한다.
xml에서 Annotation으로 변경
객체와 객체를 injection 해주는 작업
DI 방식을 아래와 같이 변경
setter injection
@Autowired
xml로 객체를 만들어주면 자동으로 세팅을 해준다.
객체를 생성했을 때 Autowired설정을 확인하고 있으면 객체 참조시키는 키워드 만들어주기
Namespaces context 선택
<context:annotation-config /> 추가
xml에서 설정이 빠져있는지 확인하게 된다.
GridExamConsole.java
package spring.di.ui;
import org.springframework.beans.factory.annotation.Autowired;
import spring.di.entity.Exam;
public class GridExamConsole implements ExamConsole {
private Exam exam;
public GridExamConsole() {
// TODO Auto-generated constructor stub
}
public GridExamConsole(Exam exam) {
this.exam = exam;
}
@Override
public void print() {
System.out.println("--------------");
System.out.println("total | avg");
System.out.println("------------");
System.out.printf("%3d | %3.2f \n" , exam.total(), exam.avg());
System.out.println("--------------");
}
@Autowired
@Override
public void setExam(Exam exam) {
this.exam = exam;
}
}
setting.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd">
<context:annotation-config />
<!-- Exam exam = new NewIecExam(); -->
<bean id="exam" class="spring.di.entity.NewIecExam" p:kor="10" p:eng="10" />
<!--
<bean id="exam" class="spring.di.entity.NewIecExam" >
<constructor-arg name="kor" value="10" />
<constructor-arg name="math" value="10" />
<constructor-arg name="com" value="10" />
<constructor-arg name="eng" value="10" />
</bean>
-->
<!-- ExamConsole console = new GridExamConsole(); -->
<bean id="console" class="spring.di.ui.GridExamConsole" >
<!-- console.setExam(exam); -->
<!-- <property name="exam" ref="exam" /> -->
</bean>
<!-- 컬랙션 실제로 객체를 만드는 능력 -->
<util:list id="exams" list-class="java.util.ArrayList">
<bean class="spring.di.entity.NewIecExam" p:kor="1" p:eng="1" /> <!-- 직접생성 -->
<ref bean="exam" /> <!-- 위에 참조 -->
</util:list>
<!-- ArrayList를 생성자로 넘기는 방식 -->
<!-- <bean id="exams" class="java.util.ArrayList">
<constructor-arg>
<list>
<bean class="spring.di.entity.NewIecExam" p:kor="10" p:eng="10" /> 직접생성
<ref bean="exam" /> 위에 참조
</list>
</constructor-arg>
</bean> -->
</beans>
@Autowired와 @Qualifier
객체 생성과 Autowired
세팅 할때 id의 이름하고는 상관이 없다. => 변경하거나 삭제해도 바인딩이 잘 된다.
잠 조할 때는 인터페이스 명을 참조한다. (Exam)
사용할 수 있는 Exam 객체가 하나가 아니고 두 개 있으면 에러가 발생한다. => 이때 id 이름으로 하면 바인딩이 된다.
@Qualifier
@Qualifier를 이용하면 ()에 해당되는 이름을 xml에서 찾아서 연결해준다.
GridExamConsole.java
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 GridExamConsole implements ExamConsole {
private Exam exam;
public GridExamConsole() {
// TODO Auto-generated constructor stub
}
public GridExamConsole(Exam exam) {
this.exam = exam;
}
@Override
public void print() {
System.out.println("--------------");
System.out.println("total | avg");
System.out.println("------------");
System.out.printf("%3d | %3.2f \n" , exam.total(), exam.avg());
System.out.println("--------------");
}
@Autowired
@Qualifier("exam2")
@Override
public void setExam(Exam exam) {
this.exam = exam;
}
}
setting.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd">
<context:annotation-config />
<!-- Exam exam = new NewIecExam(); -->
<bean id="exam1" class="spring.di.entity.NewIecExam" p:kor="10" p:eng="10" />
<bean id="exam2" class="spring.di.entity.NewIecExam" p:kor="20" p:eng="20" />
<!--
<bean id="exam" class="spring.di.entity.NewIecExam" >
<constructor-arg name="kor" value="10" />
<constructor-arg name="math" value="10" />
<constructor-arg name="com" value="10" />
<constructor-arg name="eng" value="10" />
</bean>
-->
<!-- ExamConsole console = new GridExamConsole(); -->
<bean id="console" class="spring.di.ui.GridExamConsole" >
<!-- console.setExam(exam); -->
<!-- <property name="exam" ref="exam" /> -->
</bean>
<!-- 컬랙션 실제로 객체를 만드는 능력 -->
<!-- <util:list id="exams" list-class="java.util.ArrayList">
<bean class="spring.di.entity.NewIecExam" p:kor="1" p:eng="1" /> 직접생성
<ref bean="exam" /> 위에 참조
</util:list> -->
<!-- ArrayList를 생성자로 넘기는 방식 -->
<!-- <bean id="exams" class="java.util.ArrayList">
<constructor-arg>
<list>
<bean class="spring.di.entity.NewIecExam" p:kor="10" p:eng="10" /> 직접생성
<ref bean="exam" /> 위에 참조
</list>
</constructor-arg>
</bean> -->
</beans>
@Autowired의 위치와 Required 옵션
@Autowired는 필드(기본 생성자), 오버로드 생성자, setter에 사용할 수 있다.
필드는 기본 생성자를 호출하면서 injection 된다.
오버로드 생성자는 파라미터에 설정 => 생성자가 실행되지 않고 오버로드 생성자가 실행된다,.
@Autowired(required = false) 하면 객체가 없어도 실행됨
InlineExamConsole.java
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("exam2")
private Exam exam;
public InlineExamConsole() {
System.out.println("constructor");
}
public InlineExamConsole(Exam exam) {
System.out.println("overloaded constructor");
this.exam = exam;
}
@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) {
System.out.println("setter");
this.exam = exam;
}
}
setting.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd">
<context:annotation-config />
<!-- Exam exam = new NewIecExam(); -->
<!-- <bean id="exam1" class="spring.di.entity.NewIecExam" p:kor="10" p:eng="10" />
<bean id="exam2" class="spring.di.entity.NewIecExam" p:kor="20" p:eng="20" /> -->
<!--
<bean id="exam" class="spring.di.entity.NewIecExam" >
<constructor-arg name="kor" value="10" />
<constructor-arg name="math" value="10" />
<constructor-arg name="com" value="10" />
<constructor-arg name="eng" value="10" />
</bean>
-->
<!-- ExamConsole console = new InlineExamConsole(); -->
<bean id="console" class="spring.di.ui.InlineExamConsole" >
<!-- console.setExam(exam); -->
<!-- <property name="exam" ref="exam" /> -->
</bean>
<!-- 컬랙션 실제로 객체를 만드는 능력 -->
<!-- <util:list id="exams" list-class="java.util.ArrayList">
<bean class="spring.di.entity.NewIecExam" p:kor="1" p:eng="1" /> 직접생성
<ref bean="exam" /> 위에 참조
</util:list> -->
<!-- ArrayList를 생성자로 넘기는 방식 -->
<!-- <bean id="exams" class="java.util.ArrayList">
<constructor-arg>
<list>
<bean class="spring.di.entity.NewIecExam" p:kor="10" p:eng="10" /> 직접생성
<ref bean="exam" /> 위에 참조
</list>
</constructor-arg>
</bean> -->
</beans>