본문 바로가기
프레임워크/Spring

의존성 주입(Dependency Injection)(의존성 주입_XML)

by 프로그래밍 공부 2023. 4. 11.

 지난 번에는 의존 관계에 대하여 알아보았다.

 

그렇다면 이번에는 스프링을 통한 의존성 주입에 대해 알아보자.

 

객체 간의 의존성을 가지는 관계는 객체 내부에서 직접 호출(new 클래스명)하는 대신,

 

스프링 컨테이너를 통해 외부에서 객체르 생성해서 넣어주는 방식이 바로 스프링의 의존성 주입이다.

 

public interface Computer{
	void coding();
}


public class Laptop implements Computer{
	@Override
    public void coding(){}
}

public class Desktop implements Computer{
	@Override 
    public void coding(){}
}


public class Programmer{
	private Computer computer = new Laptop();
    //private Computer computer = new Desktop();
    
    public void Build(){
    	computer.coding();
    }
}

 

지난 번에 작성했던 느슨한 결합 관계를 가지는 객체이다.

 

이를 외부에서의 의존성 주입 관계로 바꾸어 보고자 한다.

 

우선 스프링에서는 XML, Annotation, 자바를 통해 의존성을 주입할 수 있고, 

 

그 의존 관계를 설정하는 방법으로는 생성자, 설정자, 또 그 외의 방법을 통해 설정할 수 있다.

 

일단 XML을 통한 의존성 주입 방법을 알아보자.

 

XML을 통한 의존성 주입 방법의 경우 Maven Project 내 Pom.xml 파일에 Spring context 의존성을 추가해주면 된다.

 

이는 MVNRepository 사이트에서 복사할 수 있다.

 

그 후 Spring 설정 파일을 생성한 뒤 해당 파일 내에 Bean 을 등록한다.

 

이후 등록한 Bean을 getBean 명령어를 통해 객체를 가져올 수 있다.

 

이 때 Bean의 Scope를 정의해서 객체의 범위를 제어할 수 있는데,

 

기본값으로 Singleton Scope를 사용한다. 

 

따라서 다음과 같은 상황일 때,

 

Desktop d1 = context.getBean("Desktop", Desktop.class);
Desktop d2 = context.getBean("Desktop", Desktop.class);

System.out.println(d1==d2);

 

비록 객체의 호출은 2번 일어났지만 싱글톤 내에 존재하는 같은 객체를 두 번 불러온 꼴이 되어 

 

True가 출력된다.

 

이를 바꾸고 싶다면 Bean을 등록할 때 Scope를 따로 선언해주면된다.

 

Bean의 Scope는 

 

- singleton

 

- prototype

 

- request

 

- session

 

이 있다.

 

singleton의 경우 기본값이고, Spring IoC(Inversion of Control, 제어역전) 컨테이너에 대한 단일 객체 인스턴스를 사용하고

 

prototype의 경우 Bean을 요청할 때마다 새로운 인스턴스를 생성해서 사용한다.

 

request는 HTTP Request 주기로 Bean 인스턴스를 생성하고,

 

session의 경우 HTTP Session 주기로 Bean 인스턴스를 생성한다.

 

 

 

XML에서 의존성을 주입하는 방법 중 생성자를 이용해 주입하는 방법은 다음과 같다. 

 

constructor-arg 태그를 이용해서 의존성을 주입한다.

 

<bean class = "풀패키지명.Desktop" id = "desktop"></bean>
<bean class = "풀패키지명.Programmer" id = "programmer">
	<constructor-arg ref="desktop"></constructor-arg>
</bean>

 

이때, ref, value와 같은 하위 태그를 이용해서 설정할 수 있다.

 

arg라는 생성자에 ref에 쓰인 객체를 주입하는 것이다.

 

public class Programmer{
	private Computer computer;
    
    public Programmer(){
    }
    
    public Programmer(Computer Computer){
    	this.computer = computer;
    }
    
}

 

 

그 다음으로는 설정자를 사용해서 주입하는 방식이다. 

 

설정자의 경우도 생성자와 크게 다르지 않다. 다만 property 태그를 이용할 뿐

 

<bean id= "laptop" class= "풀패키지명.Laptop"></bean>

<bean id = "programmer" class= "풀패키지명.Programmer">
	<property name="computer" ref="laptop"></property>
</bean>

 

위와 같이 property 요소에 name 속성에 주입할 객체의 이름을 설정한다.

 

public class Programmer{
	private Computer computer;
    
    public Programmer(){
    }
    
    public void setComputer(Computer computer){
    	this.computer = computer;
    }
}

 

생성자가 아닌 setter 설정자를 이용해 의존성을 주입할 뿐이다.

 

그 외에도 인자가 객체가 아닌 문자열과 기초 자료형일 때 value 속성으로 지정할 수 있고,

 

<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <!-- results in a setDriverClassName(String) call -->
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
    <property name="username" value="root"/>
    <property name="password" value="misterkaoli"/>
</bean>


//https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-value-element

 

list, set, map, props 와 같은 collections 요소를 이용해서 속성을 설정할 수 있다.

 

<bean id="moreComplexObject" class="example.ComplexObject">
    <!-- results in a setAdminEmails(java.util.Properties) call -->
    <property name="adminEmails">
        <props>
            <prop key="administrator">administrator@example.org</prop>
            <prop key="support">support@example.org</prop>
            <prop key="development">development@example.org</prop>
        </props>
    </property>
    <!-- results in a setSomeList(java.util.List) call -->
    <property name="someList">
        <list>
            <value>a list element followed by a reference</value>
            <ref bean="myDataSource" />
        </list>
    </property>
    <!-- results in a setSomeMap(java.util.Map) call -->
    <property name="someMap">
        <map>
            <entry key="an entry" value="just some string"/>
            <entry key="a ref" value-ref="myDataSource"/>
        </map>
    </property>
    <!-- results in a setSomeSet(java.util.Set) call -->
    <property name="someSet">
        <set>
            <value>just some string</value>
            <ref bean="myDataSource" />
        </set>
    </property>
</bean>

 

위 두 코드 모두 Spring Reference 문서에 적혀 있으니 참고하면서 배우면 좋다.

 

라고 이해했다.