https://hahagogo.tistory.com/157
Spring DI
1. 다형성 Car car = (Car) getObject("car"); Engine engine = (Engine) getObject("engine"); static Object getObject(String key) throws Exception { Properties p = new Properties(); p.load( new FileRead..
hahagogo.tistory.com
config.txt 를 대신해서 resources > config.xml 가 역할을 대신한다.
빈의 기본 scope 는 싱글톤 이다.
싱글톤 scope이란 어플리케이션 전반에 걸쳐 해당 빈의 인스턴스를 오직 하나만 생성해서 사용하는 것이다.
prototype scope으로 설정하려면 @Scope("prototype")과 같이 문자열로 지정해주며, 실행할때마다 객체를 생성한다.
싱글톤의 경우 해시값이 같은것을 볼 수있다.
prototype 타입으로 적용시 해시값이 다른것을 볼 수 있다.
직접 Setter 를 이용하여 값을 할당
config.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 으로 사용할 클래스 등록 -->
<bean id="car" class="com.test.ch3.Car" />
<bean id="engine" class="com.test.ch3.Engine" />
<bean id="door" class="com.test.ch3.Door" scope="prototype" />
</beans>
class Car{
String color;
int oil;
Engine engine;
Door[] doors;
public void setColor(String clolr) {
this.color = clolr;
}
public void setOil(int oil) {
this.oil = oil;
}
public void setEngine(Engine engine) {
this.engine = engine;
}
public void setDoors(Door[] doors) {
this.doors = doors;
}
@Override
public String toString() {
return "Car{" +
"color ='" + color + '\'' +
", oil =" + oil +
", engine =" + engine +
", doors =" + Arrays.toString(doors) +
'}';
}
}
class Engine{}
class Door{}
public class SpringDiTest {
public static void main(String[] args) {
ApplicationContext ac = new GenericXmlApplicationContext("config.xml");
Car car = ac.getBean("car", Car.class); // by name :: 타입정보 주면 형변환 필요 없다.
Engine engine = (Engine) ac.getBean("engine"); // by name
car.setColor("red");
car.setOil(100);
car.setEngine(engine);
car.setDoors( new Door[]{ ac.getBean("door",Door.class) , (Door) ac.getBean("door") });
System.out.println("car = " + car);
}
}
config.xml 이 setter를 이용하여 자동으로 값을 할당 <property ~~
<?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 으로 사용할 클래스 등록 -->
<bean id="car" class="com.test.ch3.Car" >
<property name="color" value="red" /> <!-- 기본형이나 String 일때만 value -->
<property name="oil" value="100" />
<property name="engine" ref="engine" /><!-- 참조형 인경우 ref -->
<property name="doors"> <!-- 배열인 경우 -->
<array value-type="com.test.ch3.Door" >
<ref bean="door" />
<ref bean="door" />
</array>
</property>
</bean>
<bean id="engine" class="com.test.ch3.Engine" />
<bean id="door" class="com.test.ch3.Door" scope="prototype" />
</beans>
class Car{
String color;
int oil;
Engine engine;
Door[] doors;
public void setColor(String clolr) {
this.color = clolr;
}
public void setOil(int oil) {
this.oil = oil;
}
public void setEngine(Engine engine) {
this.engine = engine;
}
public void setDoors(Door[] doors) {
this.doors = doors;
}
@Override
public String toString() {
return "Car{" +
" color ='" + color + '\'' +
", oil =" + oil +
", engine =" + engine +
", doors =" + Arrays.toString(doors) +
'}';
}
}
class Engine{}
class Door{}
public class SpringDiTest {
public static void main(String[] args) {
ApplicationContext ac = new GenericXmlApplicationContext("config.xml");
Car car = ac.getBean("car", Car.class); // by name :: 타입정보 주면 형변환 필요 없다.
System.out.println("car = " + car);
}
}
config.xml 이 생성자 를 이용하여 자동으로 값을 초기화/할당
1. 기본 생성자 이용
<?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 으로 사용할 클래스 등록 -->
<bean id="car" class="com.test.ch3.Car" />
<bean id="engine" class="com.test.ch3.Engine" />
<bean id="door" class="com.test.ch3.Door" scope="prototype" />
</beans>
class Car{
String color;
int oil;
Engine engine;
Door[] doors;
public Car(){}
@Override
public String toString() {
return "Car{" +
" color ='" + color + '\'' +
", oil =" + oil +
", engine =" + engine +
", doors =" + Arrays.toString(doors) +
'}';
}
}
class Engine{}
class Door{}
public class SpringDiTest {
public static void main(String[] args) {
ApplicationContext ac = new GenericXmlApplicationContext("config.xml");
Car car = ac.getBean("car", Car.class); // by name :: 타입정보 주면 형변환 필요 없다.
System.out.println("car = " + car);
}
}
2. 생성자 만들어서(기본 생성자 아님) <constructor-arg ~
<?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 으로 사용할 클래스 등록 -->
<bean id="car" class="com.test.ch3.Car" >
<constructor-arg name="color" value="red" /> <!-- 기본형이나 String 일때만 value -->
<constructor-arg name="oil" value="100" />
<constructor-arg name="engine" ref="engine" /><!-- 참조형 인경우 ref -->
<constructor-arg name="doors"> <!-- 배열인 경우 -->
<array value-type="com.test.ch3.Door" >
<ref bean="door" />
<ref bean="door" />
</array>
</constructor-arg>
</bean>
<bean id="engine" class="com.test.ch3.Engine" />
<bean id="door" class="com.test.ch3.Door" scope="prototype" />
</beans>
class Car{
String color;
int oil;
Engine engine;
Door[] doors;
public Car(String color, int oil, Engine engine, Door[] doors) {
this.color = color;
this.oil = oil;
this.engine = engine;
this.doors = doors;
}
@Override
public String toString() {
return "Car{" +
" color ='" + color + '\'' +
", oil =" + oil +
", engine =" + engine +
", doors =" + Arrays.toString(doors) +
'}';
}
}
class Engine{}
class Door{}
public class SpringDiTest {
public static void main(String[] args) {
ApplicationContext ac = new GenericXmlApplicationContext("config.xml");
Car car = ac.getBean("car", Car.class); // by name :: 타입정보 주면 형변환 필요 없다.
System.out.println("car = " + car);
}
}
config.xml 에 패키지 지정하고 @Component 로 빈 등록하기.
<?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: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.xsd">
<!-- @Autowired 사용하려면 필수 -->
<!-- 단 여기에서는 component-scan 이 빈을 등록 해주기 때문에 없어도 된다 -->
<context:annotation-config />
<!-- com ( component-scan ) -->
<!-- 패키지 안에 있는 클래스 중에서 @Component 붙은것을 찾아서 Bean 으로 등록 -->
<context:component-scan base-package="com.test.ch3" >
<!-- ex 입력시 빠른 입력 가능 -->
<!-- 제외 할 것들 -->
<context:exclude-filter type="regex" expression="com.test.ch3.dpCopy*.*"/>
</context:component-scan>
</beans>
@Component("engine") class Engine{} // <bean id="engine" class="com.test.ch3.Engine" / >
@Component class SuperEngine extends Engine{}
@Component class TurboEngine extends Engine{}
@Component class Door{}
@Component
class Car{
@Value("red") String color;
@Value("100") int oil;
@Autowired Engine engine; // 타입으로 먼저 검색 , 여러개인 경우 이름으로 찾음..
@Autowired Door[] doors;
public Car(){}
public Car(String color, int oil, Engine engine, Door[] doors) {
this.color = color;
this.oil = oil;
this.engine = engine;
this.doors = doors;
}
public void setColor(String color) {
this.color = color;
}
public void setOil(int oil) {
this.oil = oil;
}
public void setEngine(Engine engine) {
this.engine = engine;
}
public void setDoors(Door[] doors) {
this.doors = doors;
}
@Override
public String toString() {
return "Car{" +
" color ='" + color + '\'' +
", oil =" + oil +
", engine =" + engine +
", doors =" + Arrays.toString(doors) +
'}';
}
}
public class SpringDiTest {
public static void main(String[] args) {
ApplicationContext ac = new GenericXmlApplicationContext("config.xml");
Car car = ac.getBean("car", Car.class); // by name :: 타입정보 주면 형변환 필요 없다.
System.out.println("car = " + car);
//Engine engine = ac.getBean(Engine.class); // 엔진 타입이 3개라 에러가 난다.
Engine engine = ac.getBean("superEngine" , Engine.class);
System.out.println("engine = " + engine);
}
}
하나만 나와야 되는데 두개 이상 검색되어 뭐를 선택해야 하는지 모를경우 나오는 에러
Exception in thread "main" org.springframework.beans.factory.
UnsatisfiedDependencyException: Error creating bean with name 'car':
Unsatisfied dependency expressed through field 'engine'; nested exception is org.
springframework.beans.factory.NoUniqueBeanDefinitionException:
No qualifying bean of type 'com.test.ch3.Engine' available:
expected single matching bean but found 2: superEngine,turboEngine
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException:
No qualifying bean of type 'com.test.ch3.Engine' available: expected
single matching bean but found 2: superEngine,turboEngine
class Engine{} 에 @Component (빈 등록) 이 되어 있지 않은 상태에서
@Autowired Engine engine; 여기서 타입 검색을 먼저 하는데 빈으로 등록된 superEngine , turboEngine 둘중에
무엇을 선택해야 될지 모르겠고 이름으로 조회해도 engine이 빈에 등록되어 있지 않아서 에러를 발생함.
이런 경우 @Autowired 아래에 @Qualifier("superEngine") 를 이용하여
빈으로 등록된 후보 중에서 하나를 지정해 주어야 한다.
아니면 주입받을 의존객체가 필수적이지 않을 경우 @Autowired(required = false)로 설정해서
의존객체를 주입받지 못하더라도 빈을 생성하도록 할 수 있다.
또는 @Resource(name="superEngine") 이렇게 이름검색을 이용해도 된다.
class Engine{} // <bean id="engine" class="com.test.ch3.Engine" / >
@Component class SuperEngine extends Engine{}
@Component class TurboEngine extends Engine{}
@Component class Door{}
@Component
class Car{
@Value("red") String color;
@Value("100") int oil;
// @Autowired
// @Qualifier("superEngine")
@Resource(name="superEngine")
Engine engine; // engine , superEngine , TurboEngine
@Autowired Door[] doors;
public Car(){}
public Car(String color, int oil, Engine engine, Door[] doors) {
this.color = color;
this.oil = oil;
this.engine = engine;
this.doors = doors;
}
public void setColor(String color) {
this.color = color;
}
public void setOil(int oil) {
this.oil = oil;
}
public void setEngine(Engine engine) {
this.engine = engine;
}
public void setDoors(Door[] doors) {
this.doors = doors;
}
@Override
public String toString() {
return "Car{" +
" color ='" + color + '\'' +
", oil =" + oil +
", engine =" + engine +
", doors =" + Arrays.toString(doors) +
'}';
}
}
public class SpringDiTest {
public static void main(String[] args) {
ApplicationContext ac = new GenericXmlApplicationContext("config.xml");
Car car = ac.getBean("car", Car.class); // by name :: 타입정보 주면 형변환 필요 없다.
System.out.println("car = " + car);
}
}