본문 바로가기

공부 자료/Spring

[Spring Framework] 빈 등록 및 property/contructor-args를 이용한 의존성 주입(DI)

spring framework를 이용한 빈 등록 및 의존성 주입 방법

 

 

이전에 의존성 주입에 대한 글을 올린적이 있는데 이번에는 설명 뿐 아니라

Spring Framework를 이용해서 의존성 주입을 하고자 한다

의존성 주입 방법에는 4가지가 있는데, 해당 설명은 아래 블로깅 참고를 부탁드리며,

오늘은 이 중 2가지를 이야기 할 예정이다

https://kcode-recording.tistory.com/57

 

[Spring Core] DI 다양한 의존 관계 주입 방법

* 아래 4가지 방식 모두 의존 관계로 주입하려는 클래스가 스프링 컨테이너에 등록되어있는 Bean이어야 하며 Spring Bean이 아닌 클래스는 @Autowired가 불가능함 [생성자 주입] 생성자 주입) : 생성자를

kcode-recording.tistory.com

 

 

의존성 주입에 대해 알아보기 이전

spring framework에서 어떻게 빈이 등록되고 사용되는지에 대해 간단하게 알아보고자 한다

 


 

[DIApplication]

public class DiApplication {
    public static void main(String[] args) {
        // (1)
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans1.xml");
        // (2)
        MessageBean bean = context.getBean("messageBean", MessageBean.class);
        // (3)
        bean.sayHello("My Spring");
    }
}

 

(1) 빈 설정 로드

: ClassPathXmlApplicationContext는 xml 파일을 통해 애플리케이션 컨텍스트 초기화

: 빈 설정을 로드하고 필요한 빈을 가져올 수 있음

 

(2) 필요한 빈을 가져오기

스프링 컨테이너로부터 Message 빈을 가져와 빈을 MessageBean 클래스로 형변환하여 사용

 

(3) 빈에서 필요한 메서드 호출

: 빈에서 sayHello 메서드를 호출

 

* 스프링 컨테이너, 스프링 컨텍스트에 대한 이해가 어렵다면 아래 블로깅 참고

https://kcode-recording.tistory.com/49

 

[Spring Core] 스프링 컨테이너(Spring Container), 스프링 컨텍스트(Spring Context)

컨테이너 : 내부에 또 다른 컴포넌트를 가지고 있는 어떤 컴포넌트를 의미 : 객체를 생성하고 객체를 서로 연결함 : 객체를 설정하는 단계를 지나 마지막으로 생명주기 전반(생성~관리~소멸)을

kcode-recording.tistory.com

 

[beans1.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
               https://www.springframework.org/schema/beans/spring-beans.xsd">

	// (1)
    <bean id="messageBean" class="com.codingrecipe.springEx1.sample.MessageBeanEn"/>
</beans>

 

(1) 빈 생성

: bean 태그를 이용해 messageBean의 빈을 생성

 

 

정리해보자면, MessageBean을 beans1.xml 파일에서 빈으로 등록하고,

해당 xml 파일을 ClassPathXmlApplicationContext 클래스를 통해 스프링 컨텍스트를 초기화하고

MessageBean의 빈을 로드하게 된다(여러개의 빈이 존재한다면 각각의 빈 로드)

스프링 컨텍스트에 존재하는 빈 설정을 로드에 클래스 형으로 변환 후

해당 빈에서 내가 사용하고자 하는 메서드를 가져와 사용할 수 있게 되는 것이다

 


 

의존성 주입은 크게 4가지가 있지만 이 중 생성자를 통한 의존성 주입set 메서드를 통한 의존성 주입을 설명할 것이다

그럼 이제 의존성 주입은 어떻게 되는 것인지 코드를 통해 알아보고자 한다

 

 

[DIApplication.java]

public class DiApplication {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans3.xml");
        Employ employ = context.getBean("employ", Employ.class);
        employ.info();
    }
}

* 위에서 본 코드와 동일하지만, bean3.xml 파일을 빈으로 등록

 

 

 

[EmployImpl.java]

public class EmployImpl implements Employ {
    private Integer id;
    private String name;
    private Department department;

    public EmployImpl(){}

    public EmployImpl(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Department getDepartment() {
        return department;
    }

    public void setDepartment(Department department) {
        this.department = department;
    }

    @Override
    public void info() {
        System.out.printf("사원 번호 : %d, 이름 : %s, 부서명 : %s, 부서 위치 : %s%n",
                id, name, department.getName(), department.getLocation());
    }

}

 

* bean에서 어떻게 의존성 주입이 되는지를 설명하기 위해 생성자와 set 메서드를 모두 선언

* Employ interface는 추측 가능하기에 코드는 생략

 

 

[Department.java]

public class Department{
    private Integer id;
    private String name;
    private String location;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }

    public Department(){}

    public Department(String name, String location) {
        this.name = name;
        this.location = location;
    }
}

* bean에서 어떻게 의존성 주입이 되는지를 설명하기 위해 생성자와 set 메서드를 모두 선언

 

 

이제 기본 설정은 완료했기에 beans3.xml에서 빈 등록을 해주면서 의존성 주입을 해주어야 한다.

위에서 의존성 주입은 생성자를 이용한 주입과 set 메서드를 이용한 주입이 있다고 이야기 했는데,

이 두가지는 혼용해서도 사용이 가능하다

 

코드를 보기 전 constructor-args는 생성자를 이용하여 의존성을 주입할 때 사용하고,

property는 set 메서드를 이용하여 의존성을 주입할 때 사용한다는 것을 알고

 

<property name="method" value="값"/>되어 있다면 이는 setMethod("값")과 동일한 의미

<constructor-args index="0" value="값"/>이라고 되어 있다면 Constructor(값, ...)을 의미한다는 것을 알면

아래 코드를 이해하기 매우 수월할 것이다.

 

사용 가능한 방법을 모두 코드로 적어 놓았으니,

코드와 설명을 참고하며 이해하면 좋을 것이다

 

[beans3.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
               https://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 경우1 -->
    <bean id="department" class="com.codingrecipe.springEx1.sample3.Department">
        <property name="name" value="개발부"/>
        <property name="location" value="서울특별시"/>
    </bean>

    <bean id="employ" class="com.codingrecipe.springEx1.sample3.EmployImpl">
        <property name= "id" value="111"/>
        <property name= "name" value="길동이"/>
        <property name="department" ref="department"/>
    </bean>

    <!-- 경우2 -->
    <bean id="department" class="com.codingrecipe.springEx1.sample3.Department">
        <constructor-arg index="0" value="개발부"/>
        <constructor-arg index="1" value="서울특별시"/>
    </bean>

    <bean id="employ" class="com.codingrecipe.springEx1.sample3.EmployImpl">
        <property name= "id" value="111"/>
        <property name= "name" value="길동이"/>
        <property name="department" ref="department"/>
    </bean>

    <!-- 경우3 -->
    <bean id="department" class="com.codingrecipe.springEx1.sample3.Department">
        <constructor-arg index="0" value="개발부"/>
        <constructor-arg index="1" value="서울특별시"/>
    </bean>

    <bean id="employ" class="com.codingrecipe.springEx1.sample3.EmployImpl">
        <constructor-arg index="0" value="111"/>
        <constructor-arg index="1" value="길동이"/>
        <property name="department" ref="department"/>
    </bean>

    <!-- 경우4 -->
    <bean id="employ" class="com.codingrecipe.springEx1.sample3.EmployImpl">
        <property name= "id" value="222"/>
        <property name= "name" value="율동이"/>
        <property name="department">
            <bean id="department" class="com.codingrecipe.springEx1.sample3.Department">
                <property name="name" value="개발부서"/>
                <property name="location" value="서울특별시"/>
            </bean>
        </property>
    </bean>

</beans>

 

* 위 내용은 property와 constructor-args로 가능한 경우를 모두 보여준 것이기 때문에 경우1과 경우2만 설명하고자 한다

 

경우1)

: 이는 모두 property를 이용하여 의존성을 주입

 

: (1) department 빈에서 각 set 메서드를 이용해 setName("개발부"), setLocation("서울특별시")로 지정했다는 것을 의미

: emploey빈에서 각 set 메서드를 이용해 setId(111), setName("길동이"), setDepartment( (1)에서 지정한 department값)로 저정했다는 것을 의미

 

그렇기에 경우1은 모두 set 함수를 이용해 각 값을 지정해 준 것이 되는 것이다

 

 

경우2)

: department는 constuctor-args를 이용, employ는 employ를 이용하여 의존성 주입

: department 빈에서는 생성자를 이용했기 때문에 Department(String name, String Location)의 생성자를 사용했기에

첫번째 값에는 index="0"인 값을, 두번째 값에는 index="1"인 값을 주입하기에 Department("개발부", "서울특별시")로 지정했다는 것을 의미

: index의 값은 생성자에 들어가는 값이 여러개인 경우 지정하며, 한개인 경우에는 따로 지정하지 않아도 됨

* employ는 경우1과 동일하기 때문에 설명 생략

 

 

* xml에서 빈을 직접 설정했지만 @Autowired 애너테이션 통해서도 빈을 설정 및 의존성 주입이 가능하다. 이는 추후에 블로깅 할 에정이다.