Burninghering's Blog
article thumbnail

resource > xml 파일 만들어주기

config.xml

<java />
<?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="car" class="com.fastcampus.ch3.Car"/> <bean id="engine" class="com.fastcampus.ch3.Engine"/> <bean id="door" class="com.fastcampus.ch3.Door"/> </beans>

 

SpringDiTest.java

<java />
package com.fastcampus.ch3; import org.springframework.context.ApplicationContext; import org.springframework.context.support.GenericXmlApplicationContext; class Car{} class Engine{} class Door{} public class SpringDiTest { public static void main(String[] args) { ApplicationContext ac = new GenericXmlApplicationContext("config.xml"); Car car = (Car) ac.getBean("car"); Engine engine = (Engine)ac.getBean("engine"); Door door = (Door)ac.getBean("door"); System.out.println("car = " + car); System.out.println("engine = " + engine); System.out.println("door = " + door); } }

config.xml에 클래스 정보를 설정해주고 

그것을 읽어와서 객체 저장소에 객체가 만들어진다.

getBean으로(byNamed으로) 객체들을 가져와 사용했다.

 

<java />
ApplicationContext ac = new GenericXmlApplicationContext("config.xml"); // Car car = (Car) ac.getBean("car"); //byName 아래와 같은 문장 Car car = ac.getBean("car",Car.class); //byName Car car2 = (Car) ac.getBean(Car.class); //byType

byName 또는 byType으로 찾기 

 

byName으로 찾을 때,

그냥 이름만 쓰고, 앞에 형변환을 하던지

뒤에 타입 정보를 주고 형변환을 생략하던지 

어느 방법이든 상관없다!

 

<java />
public static void main(String[] args) { ApplicationContext ac = new GenericXmlApplicationContext("config.xml"); // Car car = (Car) ac.getBean("car"); //byName 아래와 같은 문장 Car car = ac.getBean("car",Car.class); //byName Car car2 = (Car) ac.getBean(Car.class); //byType Engine engine = (Engine)ac.getBean("engine"); Door door = (Door)ac.getBean("door"); System.out.println("car = " + car); System.out.println("engine = " + engine); System.out.println("door = " + door); System.out.println("car2 = " + car2); } }

car와 car2 해쉬코드 값이 같은데, 같은 객체라서 그렇다.

getBean을 할 때마다 같은 값을 반환한다.


getBean을 할 때마다 매번 같은 객체가 만들어지는 singleton이지만,

때로는 getBean을 할 때마다 매번 다른 객체를 생성하고 싶을 때는

<java />
<?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="car" class="com.fastcampus.ch3.Car" scope="prototype"/> <bean id="engine" class="com.fastcampus.ch3.Engine" scope="singleton"/> <bean id="door" class="com.fastcampus.ch3.Door" scope="singleton"/> </beans>

기본이 singleton이지만

scope로 prototype을 지정해주면 된다.

 

클래스의 객체를 하나만 생성하는 것이 싱글톤이다.


Car에 iv를 몇개 추가한다.

<java />
class Car{ String color; int oil; Engine engine; Door[] 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) + '}'; } }

 

Setter를 이용해서

자동차에 엔진과 도어를 주입한다.

<java />
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);

Door가 2개인데 두 해쉬값이 같다..

그러므로

<java />
<?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="car" class="com.fastcampus.ch3.Car" /> <bean id="engine" class="com.fastcampus.ch3.Engine" /> <bean id="door" class="com.fastcampus.ch3.Door" scope="prototype"/> </beans>

prototype으로 바꾸어주면

Door가 서로 다른 값이 나온다


Setter를 호출하는 것이 아닌

xml에서 property 태그로 해결할 수 있다.

property태그를 이용해 iv를 초기화했다.

<java />
<?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="car" class="com.fastcampus.ch3.Car"> <property name="color" value="red"/> <property name="oil" value="100"/> <property name="engine" ref="engine"/> <property name="doors"> <array value-type="com.fastcampus.ch3.Door"> <ref bean="door"/> <ref bean="door"/> </array> </property> </bean> <bean id="engine" class="com.fastcampus.ch3.Engine" /> <bean id="door" class="com.fastcampus.ch3.Door" scope="prototype"/> </beans>

 

만약 변경 사항이 생기면

config.xml파일만 고쳐주면 되기 때문에 

고칠 코드가 줄어든다.

<java />
public class SpringDiTest { public static void main(String[] args) { ApplicationContext ac = new GenericXmlApplicationContext("config.xml"); // Car car = (Car) ac.getBean("car"); //byName 아래와 같은 문장 Car car = ac.getBean("car",Car.class); //byName Car car2 = (Car) ac.getBean(Car.class); //byType Engine engine = (Engine)ac.getBean("engine"); Door door = (Door)ac.getBean("door"); // 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); } }

 

클래스 내에 Setter들이 있어야

property 태그를 사용할 수 있다.

(property가 Setter를 사용하는 것이다.)

 

Setter를 사용하는 대신에 생성자를 사용할 수도 있는데,

property를 constructor-arg로 바꿔주고

클래스에 생성자를 추가한다.

<java />
<?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="car" class="com.fastcampus.ch3.Car"> <constructor-arg name="color" value="red"/> <constructor-arg name="oil" value="100"/> <constructor-arg name="engine" ref="engine"/> <constructor-arg name="doors"> <array value-type="com.fastcampus.ch3.Door"> <ref bean="door"/> <ref bean="door"/> </array> </constructor-arg> </bean> <bean id="engine" class="com.fastcampus.ch3.Engine" /> <bean id="door" class="com.fastcampus.ch3.Door" scope="prototype"/> </beans>
<java />
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; }


패키지 안의 Componet 애노테이션이 붙은 클래스를 찾아서 bean으로 등록

<java />
<?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"> <context:component-scan base-package="com.fastcampus.ch3"/> </beans>

패키지 하위에 있는 것들까지 다 찾아버려서(Car 클래스가 diCopy3에도 있으므로) 에러가 나기 때문에

코드를 추가해줘서

SpringDiTest.java 클래스 내에만 있는 Component를 스캔하는 것으로 설정한다.

<java />
<?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"> <context:component-scan base-package="com.fastcampus.ch3"> <context:exclude-filter type="regex" expression="com.fastcampus.ch3.diCopy*.*"/> </context:component-scan> </beans>

Setter를 주석으로 해서 다 null값이 나온다

 

Setter 주석 해제~

<java />
public class SpringDiTest { public static void main(String[] args) { ApplicationContext ac = new GenericXmlApplicationContext("config.xml"); // Car car = (Car) ac.getBean("car"); //byName 아래와 같은 문장 Car car = ac.getBean("car",Car.class); //byName Car car2 = (Car) ac.getBean(Car.class); //byType Engine engine = (Engine)ac.getBean("engine"); Door door = (Door)ac.getBean("door"); 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); } }

getBean이 잘 되었다는 뜻

 

다시 Setter를 주석처리한다


@Autowired를 통해 Setter 대신 주입을 해본다

객체들 간의 관계를 맺어주는 것이다.

<java />
@Component class Car{ String color; int oil; @Autowired Engine engine; @Autowired Door[] doors;
<code />
public class SpringDiTest { public static void main(String[] args) { ApplicationContext ac = new GenericXmlApplicationContext("config.xml"); // Car car = (Car) ac.getBean("car"); //byName 아래와 같은 문장 Car car = ac.getBean("car",Car.class); //byName Car car2 = (Car) ac.getBean(Car.class); //byType Engine engine = (Engine)ac.getBean("engine"); Door door = (Door)ac.getBean("door"); // 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); } }

color와 oil에는 null값이 나온다

 

@Value 어노테이션을 사용해준다

<java />
@Component class Car{ @Value("red") String color; @Value("100") int oil;

door는 하나만 주입이 되었는데,

Autowired는 타입이 맞는 bean 하나만 넣기 때문에..


Engine을 추가한다

<code />
@Component("engine") //<bean id="engine" class Engine{} @Component class SuperEngine extends Engine{} @Component class TurboEngine extends Engine{}
<code />
public class SpringDiTest { public static void main(String[] args) { ApplicationContext ac = new GenericXmlApplicationContext("config.xml"); // Car car = (Car) ac.getBean("car"); //byName 아래와 같은 문장 Car car = ac.getBean("car",Car.class); //byName Car car2 = (Car) ac.getBean(Car.class); //byType // Engine engine = (Engine)ac.getBean("engine"); //ByName Engine engine = (Engine)ac.getBean(Engine.class); //ByType Door door = (Door)ac.getBean("door");

매칭되는 bean 1개를 예상했는데 3개가 발견되어 에러가 난 것이다.

타입이 여러 개일때는 타입이 아닌 이름으로 찾는다.

<code />
Engine engine = (Engine)ac.getBean("superEngine"); //ByType Door door = (Door)ac.getBean("door"); // 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); System.out.println("engine = " + engine);

같은 타입이 여러 개 있을 때 byType으로 찾으면 에러가 난다.

그럴 때에는 이름으로(key) 찾아야한다.

 

<code />
@Autowired //byType - 타입으로 먼저 검색, 여러개면 이름으로 검색. - engine, superEngine, turboEngine Engine engine;
<java />
public class SpringDiTest { public static void main(String[] args) { ApplicationContext ac = new GenericXmlApplicationContext("config.xml"); // Car car = (Car) ac.getBean("car"); //byName 아래와 같은 문장 Car car = ac.getBean("car",Car.class); //byName // Car car2 = (Car) ac.getBean(Car.class); //byType // Engine engine = (Engine)ac.getBean("engine"); //ByName // Engine engine = (Engine)ac.getBean("superEngine"); //ByType // Door door = (Door)ac.getBean("door"); // 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); } }

@Autowired는 byType인데 왜 에러가 나지 않을까?

그 이유는 타입으로 먼저 검색한 뒤, 후보가 여러 개라면 타입의 앞글자가 소문자인 것으로 이름을 검색한다.

<java />
//@Component("engine") //<bean id="engine" class="com.fastcampus.ch3.Engine"/> class Engine{}

Engine이 Component에 있어서 일치하는 것이 있었는데,

빼고 나면 

Autowired로 이름을 찾아야한다.

타입이 일치하는 SuperEngine과 TurboEngine 2개가 있는데 이름으로 비교해보니 판단이 서지않아 에러가 난다.

그럴때는 

@Qualifier로 판단을 해주어야한다.

<code />
@Autowired //byType - 타입으로 먼저 검색, 여러개면 이름으로 검색. - engine, superEngine, turboEngine @Qualifier("superEngine") Engine engine;

 

Autowired는 type으로 bean을 찾아서 주입을 하는데

만약에 같은 타입이 여러개라면,

@Qualifier를 사용한다.

 

Autowired가 아닌

Resource를 사용해도 제대로 결과가 나온다!

<code />
@Resource(name="superEngine") Engine engine;

 

 

profile

Burninghering's Blog

@개발자 김혜린

안녕하세요! 반갑습니다.