오늘은 spring의 bean속성 중 autowire라는 기능에 대해 정리해보려고 합니다.
새로운 프로젝트부터 만들러 가볼까요?
(프로젝트는 그냥 큰 구분을 위한 것일 뿐 굳이 새로 안 만들어도 상관없습니다.)
Spring04로 자바프로젝트 만들고 convert to maven project 해주시고 평소와 같이 spring-core와 spring-context를 pom.xml에 붙여줍니다.
그다음 패키지 만들러 가봅시다!
Food.java
package com.test02;
public class Food {
private String name;
private int price;
public Food() {
}
public Food(String name, int price) {
this.name = name;
this.price = price;
}
public void setName(String name) {
this.name = name;
}
public void setPrice(int price) {
this.price = price;
}
@Override
public String toString() {
return "Food [name=" + name + ", price=" + price + "]";
}
}
MyFood.java
package com.test02;
public class MyFood {
private Food favoriteFood;
private Food unFavoriteFood;
public MyFood() {
}
public MyFood(Food favoriteFood, Food unFavoriteFood) {
this.favoriteFood = favoriteFood;
this.unFavoriteFood = unFavoriteFood;
}
public Food getFavoriteFood() {
return favoriteFood;
}
public void setFavoriteFood(Food favoriteFood) {
this.favoriteFood = favoriteFood;
}
public Food getUnFavoriteFood() {
return unFavoriteFood;
}
public void setUnFavoriteFood(Food unFavoriteFood) {
this.unFavoriteFood = unFavoriteFood;
}
@Override
public String toString() {
return "favorite : " + favoriteFood + "\nunFavorite : " + unFavoriteFood;
}
}
MTest.java
package com.test02;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MTest {
public static void main(String[] args) {
ApplicationContext factory = new ClassPathXmlApplicationContext("com/test02/applicationContext.xml");
MyFood my = factory.getBean("myFood", MyFood.class);
System.out.println(my);
}
}
applicationContext.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="favoriteFood" name="favoriteFood" class="com.test02.Food">
<property name="name" value="치킨" />
<property name="price" value="20000" />
</bean>
<bean id="unFavoriteFood" name="unFavoriteFood" class="com.test02.Food">
<constructor-arg value="해물찜" />
<constructor-arg value="40000" />
</bean>
<bean id="myFood" class="com.test02.MyFood">
<property name="favoriteFood" ref="favoriteFood" />
<property name="unFavoriteFood" ref="unFavoriteFood"></property>
</bean>
</beans>
코드 실행결과
autowire를 사용하기전엔 <property> 혹은 <constructor-arg>를 사용해야 객체를 가져와서 사용할 수 있었습니다.
먼저 autowire엔 4가지 속성이 있는데 하나하나 살펴보겠습니다.
(no를 포함하면 5가지지만 no는 안쓰는것과 같으므로 따로 정리하진 않습니다.)
1. byName : setter와 같은 이름의 bean (id/name) 이 있으면 자동 할당
현재 MyFood의 setter와 같은 이름인 favoriteFood와 unFavoriteFood가 있으므로 자동 할당됩니다.
그렇다면 favoriteFood에서 Food를 뺀다면 어떻게 될까요?
그렇게 된다면 setter와 같은 이름의 favoriteFood의 값이 없으므로 자동할당 할 수 없게 됩니다. 따라서
이런 결과가 나옵니다.
2. byType : setter의 parameterType과 같은 type의 bean이 있으면 자동 할당
현재 여기서 byType을 넣으면 error가 발생하는 것이 정상입니다.
이유는 applicationContext에 Food타입 객체의 값이 2개가 있기 때문인데요(favoriteFood, unFavoriteFood)
이렇게 2개 이상의 값이 있을 때 타입을 따로 지정해준 게 아니기 때문에 컴퓨터에서도 자동으로 어떤 값을 할당해야 할지 모르기 때문에 에러가 발생합니다.
3. constructor : 생성자와 같은 이름의 bean이 있으면 자동 할당
현재 MyFood의 생성자는 기본 생성자와 파라미터 2개짜리 생성자가 있다.
그냥 여기서 autowire="constructor"하게되면 값이 잘 나오는 것을 알 수 있는데 이때,
favoriteFood에서 Food를 지우게 되면 favorite와 unFavoriteFood가 되는데 2개 모두 일치하는 생성자가 없으므로 기본생성자가 출력됩니다. (현재는 기본생성자에 값이 없으므로 null이 나온다.)
4. default : 생성자에 할당할 수 있는지 확인 후 -> 없으면 setter에서 확인하여 할당
기본생성자가 있으면 기본생성자 호출!
'Java > Spring' 카테고리의 다른 글
[Spring] 10. Annotation - autowired (0) | 2021.06.25 |
---|---|
[Spring] 09. MessageSource (메시지 국제화) (0) | 2021.06.24 |
[Spring] 07. 객체의 생성 타이밍 ( + lazy-init) (0) | 2021.06.21 |
[Spring] 06. applicationContext의 내부구조(Factory 패턴) (0) | 2021.06.20 |
[Spring] Namespace가 안 나올 때 (0) | 2021.06.19 |