Burninghering's Blog
article thumbnail

resource > xml 파일 만들어주기

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 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

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으로) 객체들을 가져와 사용했다.

 

        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으로 찾을 때,

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

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

어느 방법이든 상관없다!

 

    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을 할 때마다 매번 다른 객체를 생성하고 싶을 때는

<?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를 몇개 추가한다.

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를 이용해서

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

       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개인데 두 해쉬값이 같다..

그러므로

<?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를 초기화했다.

<?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파일만 고쳐주면 되기 때문에 

고칠 코드가 줄어든다.

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로 바꿔주고

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

<?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>
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으로 등록

<?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를 스캔하는 것으로 설정한다.

<?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 주석 해제~

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 대신 주입을 해본다

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

@Component
class Car{
    String color;
    int oil;

    @Autowired
    Engine engine;
    @Autowired
    Door[] doors;
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 어노테이션을 사용해준다

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

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

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


Engine을 추가한다

@Component("engine") //<bean id="engine"
class Engine{}
@Component
class SuperEngine extends Engine{}
@Component
class TurboEngine extends Engine{}
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개가 발견되어 에러가 난 것이다.

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

        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) 찾아야한다.

 

@Autowired //byType - 타입으로 먼저 검색, 여러개면 이름으로 검색. - engine, superEngine, turboEngine
Engine engine;
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인데 왜 에러가 나지 않을까?

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

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

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

빼고 나면 

Autowired로 이름을 찾아야한다.

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

그럴때는 

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

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

 

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

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

@Qualifier를 사용한다.

 

Autowired가 아닌

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

@Resource(name="superEngine")
Engine engine;

 

 

profile

Burninghering's Blog

@개발자 김혜린

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