개키우는개발자 : )

DI 애플리케이션 작성(3) 본문

JAVA/Spring Framework

DI 애플리케이션 작성(3)

DOGvelopers 2019. 2. 7. 11:58
반응형

Spring Framework DI 애플리케이션 작성(3)



학습 목표


  • Bean 의존관계 설정 방법에 대한 이해
  • 프로퍼티(Property)값 설정 방법에 대한 이해
  • 프로퍼티(Property) 파일을 이용한 설정 방법에 대한 이해



1.Bean 의존관계 설정 방법에 대한 이해


1-1 Setter Injection : <property> 태그


Setter 메서드를 통해 의존관계가 있는 Bean을 주입하려면 <property> 태그를 사용할 수 있다.


- ref 속성은 사용하면 Bean 이름을 이용해 주입할 Bean을 찾는다


- value 속성은 단순 값 또는 Bean이 아닌 객체를 주입할 때 사용한다.


Setter 메서드 생성


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package myspring.di.xml;
 
public class Hello {
    
    //멤버변수 name 
    private String name;
    //멤버변수 Printer 타입 printer
    private Printer printer;
 
    public void setName(String name) {
        this.name = name;
    }
    
    public void setPrinter(Printer printer) {
        this.printer = printer;
    }
 
}
 
cs


Seeter 메서드에 주입 (bean 설정파일 beans.xml)


1
2
3
4
5
6
7
<bean id="hello" class="myspring.di.xml.Hello">
    <property name="name" value="Spring Study" />
    <!-- setPrinter(Printer) -->
    <property name="printer" ref="printer" />
</bean>
 
<bean id="printer" class="myspring.di.xml.StringPrinter"/>
cs



1-2 Constructor Injection : <constructor-arg> 태그


Constructor를 통해 의존관계가 있는 Bean을 주입하려면 <constructor-arg>태그를 사용할 수 있다.

Constructor 주입방식은 생성자의 파라미터를 이용하기 때문에 한번에 여러 개의 객체를 주입할 수 있다.


- 기본생성자와 인자값을 가지고있는 생성자를 설정해줍니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package myspring.di.xml;
 
public class Hello {
    
    //멤버변수 name 
    private String name;
    //멤버변수 Printer 타입 printer
    private Printer printer;
    
    //기본 생성자
    public Hello() {}
    
    //2개의 멤버 변수를 인자값으로 가지고있는 생성자
    public Hello(String name, Printer printer) {
        super();
        this.name = name;
        this.printer = printer;
    }
    
}
 
cs



- 생성자 주입을 위한 설정 : index 지정


1
2
3
4
<bean id="hello2" class="myspring.di.xml.Hello">
    <constructor-arg index="0" value="Spring Study" />
    <constructor-arg index="1" ref="printer" />
</bean>
cs



2.프로퍼티(Property) 값 설정 방법



2-1 단순 값(문자열이나 숫자)의 주입(Injection)


Setter 메서드를 통해 Bean의 레퍼런스가 아니라 단순 값을 주입하려고 할 때는 <property> 태그의 value 속성을 사용한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package myspring.di.xml;
 
public class Hello {
    
    //멤버변수 name 
    private String name;
    //멤버변수 Printer 타입 printer
    private Printer printer;
    
    //기본 생성자
    public Hello() {}
    
    public void setName(String name) {
        this.name = name;
    }
    
}
cs


1
2
3
<bean id="hello3" class="myspring.di.xml.Hello">
    <property name="name" value="스프링" />
</bean>
cs


2-2 컬렉션(Collection) 타입의 값 주입(Injection)


Spring은 List, Set, Map, Properties와 같은 컬렉션 타입을 XML로 작성해서 프로퍼티에 주입하는 방법을 제공한다.


- List와 Set 타입 : <list>와 <value> 태그를 이용


- 프로퍼티가 Set 타입 이면 <list> 대신에 <set>을 사용하면 된다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package myspring.di.xml;
 
import java.util.List;
 
public class Hello {
    //멤버변수 컬렉션 타입 names;
    private List<String> names;
    
    //기본 생성자
    public Hello() {}
 
    public void setNames(List<String> names) {
        this.names = names;
    }
}
 
cs


1
2
3
4
5
6
7
8
9
<bean id="hello3" class="myspring.di.xml.Hello">
    <property name="names">
        <list>
            <value>Spring</value>
            <value>IoC</value>
            <value>DI</value>
        </list>
    </property>
</bean>
cs


- Map 타입 : <map>과 <entry> 태그를 이용


1
2
3
4
5
6
7
8
9
10
11
12
13
14
package myspring.di.xml;
 
import java.util.Map;
 
public class Hello {
    //멤버변수 컬렉션 타입(map) ages;
    private Map<String,Integer> ages;
    //기본 생성자
    public Hello() {}
    
    public void setAges(Map<String, Integer> ages) {
        this.ages = ages;
    }
}
cs


1
2
3
4
5
6
7
8
9
<bean id="hello4" class="myspring.di.xml.Hello">
    <property name="ages">
        <map>
            <entry key="kim" value="30" />
            <entry key="lee" value="35" />
            <entry key="ahn" value="40" />
        </map>
    </property>
</bean>
cs



2-3 POJO 클래스 수정 및 Bean 설정 파일 수정


기존에 작성한 Hello.java파일에 List 타입의 맴버변수를 추가해보겠습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package myspring.di.xml;
 
import java.util.List;
 
public class Hello {
    
    //멤버변수 name 
    private String name;
    //멤버변수 Printer 타입 printer
    private Printer printer;
    //멤버변수 컬렉션 타입(list) names;
    private List<String> names;
 
    //기본 생성자
    public Hello() {}
 
    public void setName(String name) {
        this.name = name;
    }
    
    public void setPrinter(Printer printer) {
        this.printer = printer;
    }
    
    //리스트에 담긴 값을 출력하기 위한 get 메소드 생성
    public List<String> getNames() {
        return names;
    }
 
    public void setNames(List<String> names) {
        this.names = names;
    }
 
    //String 타입의 Hello 문자열과 + 멤버변수 name 값을 리턴
    public String sayHellow() {
        return "Hello " + name;
    }
    
    //Printer 인터페이스의 print 메서드를 호출해주는 메서드
    public void print() {
        this.printer.print(sayHellow());
    }
    
}
 

cs


기존의 beans.xml 파일을 수정합니다. 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<?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-3.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
    
    <bean id="hello" class="myspring.di.xml.Hello">
        <property name="name" value="Spring Study" />
        <!-- setPrinter(Printer) -->
        <property name="printer" ref="printer" />
    </bean>
    
    <bean id="hello2" class="myspring.di.xml.Hello">
        <constructor-arg index="0" value="Spring Study" />
        <constructor-arg index="1" ref="printer" />
    </bean>
    
    <bean id="hello3" class="myspring.di.xml.Hello">
        <property name="names">
            <list >
                <value>Spirng</value>
                <value>IoC</value>
                <value>DI</value>
            </list>
        </property>
    </bean>
    
    <bean id="hello4" class="myspring.di.xml.Hello">
        <property name="ages">
            <map>
                <entry key="kim" value="30" />
                <entry key="lee" value="35" />
                <entry key="ahn" value="40" />
            </map>
        </property>
    </bean>
    
    
    <bean id="printer" class="myspring.di.xml.StringPrinter"/>
    <bean id="consolePrinter" class="myspring.di.xml.ConsolePrinter"/>
</beans>
cs


기존의 HelloBeanJunitSpringTest.java 파일을 수정합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package myspring.di.xml.test;
 
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 
import myspring.di.xml.Hello;
import myspring.di.xml.Printer;
import static org.junit.Assert.*;
 
import java.util.List;
 
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:config/beans.xml")
public class HelloBeanJunitSpringTest {
 
    @Autowired
    private ApplicationContext context;
 
    @Test
    public void test1() {
        // 2. getBean() 호출
        Hello hello = (Hello) context.getBean("hello");
 
        // 3. Hello 의 sayHello()호출.
        /* Assert.assertEquals("Hello Spring Study",hello.sayHellow()); */
        assertEquals("Hello Spring Study", hello.sayHellow());
        // 4. Hello 의 print() 호출
        hello.print();
 
        // 5. SpringPrinter getBean() 호출
        Printer printer = context.getBean("printer", Printer.class);
        assertEquals("Hello Spring Study", printer.toString());
        
        
    }
 
    @Test
    public void test2() {
 
        Hello hello = (Hello) context.getBean("hello");
 
        Hello hello1 = (Hello) context.getBean("hello");
 
        assertSame(hello, hello1);
    }
    
    @Test
    public void test3() {
        Hello hello = context.getBean("hello3",Hello.class);
        
        //list 사이즈 가 3개 인지 비교
        assertEquals(3,hello.getNames().size());
        
        //bean주입한 값이 출력되는지 테스트
        List<String> list = hello.getNames();
        for (String value: list) {
            System.out.println(value);
        }
 
    }
}
 
cs


Ctrl + F11 또는 우클릭 - >Run as -> JUnit Test 실행


hello 테스트 성공hello 테스트 성공


(콘솔)결과 값 


1
2
3
AOP
Spring
DI
cs




3.프로퍼티(Property) 파일을 이용한 설정 방법에 대한 이해



3-1 환경에 따라 자주 변경되는 내용의 분리


- XML의 Bean 설정 메타정보는 애플리케이션 구조가 바뀌지 않으면 자주 변경되지 않는다.


- 반면에 프로퍼티 값으로 제공되는 일부 설정정보 (예 - DataSource Bean이 사용하는 DB 연결정보) 는 애플리케이션이 동작하는 환경(개발,테스트,스테이징,운영) 에 따라 자주 바뀔 수 있다.


- 변경되는 이유와 시점이 다르다면 분리하는 것이 객체지향 설계의 기본 원칙이다. 설정에도 동일한 원칙을 적용할 수 있다.


- 환경에 따라 자주 변경될 수 있는 내용은 properties 파일로 분리하는 것이 가장 깔끔하다 XML 처럼 복잡한 구성이 필요 없고 키와 값으 쌍(key=value)으로 구성하면 된다.


3-2 환경에 따라 자주 변경되는 내용의 분리 예시


- value 속성에 설정된 값들은 환경에 따라 변경될 수 있는 내용 이다.


- 자주 변경되는 값들은 properties 파일에 넣어 분리하는 것이 좋다.


- 프로퍼티 파일로 분리한 정보는 ${ } (프로퍼티 치환자)를 이용하여 설정한다.


- ${ } 값을 치환해주는 기능은 <context:property-placeholder> 태그에 의해 자동으로 등록되는 

PropertyPlaceHolderConfigurer Bean이 담당한다.


3-3 Bean 설정 파일 수정


New -> file -> config폴더 하위에 -> value.properties 생성


New -> file 생성New -> file 생성

 

value.properties 파일 생성value.properties 파일 생성


생성한 value.properties 파일에 해당 값을 작성합니다.


1
2
3
4
5
6
7
8
myname=Spring Study
myprinter=printer
value1=AOP
value2=Spring
value3=DI
 
printer1 = stringPrinter
printer2 = consolePrinter
cs


beans.xml 에서 프로퍼티 치환자를 사용하여 수정하겠습니다.

수정하기 전에 beans.xml에 Namespaces 탭을 선택후 context 를 체크한후 version을 체크해줍니다.


beans,context 선택beans,context 선택


${} 치환자를 사용해 값을 주입합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<?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-3.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
    
    <!-- 태그와 경로를 설정합니다. -->
    <context:property-placeholder location="classpath:config/value.properties"/>
    
    <bean id="hello" class="myspring.di.xml.Hello">
        <property name="name" value="Spring Study" />
        <!-- setPrinter(Printer) -->
        <property name="printer" ref="printer" />
    </bean>
    
    <bean id="hello2" class="myspring.di.xml.Hello">
        <!-- 치환자를 이용해 값을 주입합니다. -->
        <constructor-arg index="0" value="${myname}" />
        <constructor-arg index="1" ref="${myprinter}" />
    </bean>
    
    <bean id="hello3" class="myspring.di.xml.Hello">
        <property name="names">
            <list >
                <value>${value1}</value>
                <value>${value2}</value>
                <value>${value3}</value>
            </list>
        </property>
    </bean>
    
    <bean id="hello4" class="myspring.di.xml.Hello">
        <property name="ages">
            <map>
                <entry key="kim" value="30" />
                <entry key="lee" value="35" />
                <entry key="ahn" value="40" />
            </map>
        </property>
    </bean>
    
    
    <bean id="printer" class="myspring.di.xml.StringPrinter"/>
    <bean id="consolePrinter" class="myspring.di.xml.ConsolePrinter"/>
</beans>
 
cs


beans.xml 변경후 테스트 파일을 다시한번 실행합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package myspring.di.xml.test;
 
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 
import myspring.di.xml.Hello;
import myspring.di.xml.Printer;
import static org.junit.Assert.*;
 
import java.util.List;
 
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:config/beans.xml")
public class HelloBeanJunitSpringTest {
 
    @Autowired
    private ApplicationContext context;
 
    @Test
    public void test1() {
        // 2. getBean() 호출
        Hello hello = (Hello) context.getBean("hello");
 
        // 3. Hello 의 sayHello()호출.
        /* Assert.assertEquals("Hello Spring Study",hello.sayHellow()); */
        assertEquals("Hello Spring Study", hello.sayHellow());
        // 4. Hello 의 print() 호출
        hello.print();
 
        // 5. SpringPrinter getBean() 호출
        Printer printer = context.getBean("printer", Printer.class);
        assertEquals("Hello Spring Study", printer.toString());
        
        
    }
 
    @Test
    public void test2() {
 
        Hello hello = (Hello) context.getBean("hello");
 
        Hello hello1 = (Hello) context.getBean("hello");
 
        assertSame(hello, hello1);
    }
    
    @Test
    public void test3() {
        Hello hello = context.getBean("hello3",Hello.class);
        
        //list 사이즈 가 3개 인지 비교
        assertEquals(3,hello.getNames().size());
        
        //bean주입한 값이 출력되는지 테스트
        List<String> list = hello.getNames();
        for (String value: list) {
            System.out.println(value);
        }
 
    }
}
 
cs


테스트 성공하는것을 볼 수 있습니다.


hello 테스트 성공hello 테스트 성공


1
2
3
AOP
Spring
DI
cs

완성된 프로젝트 코드를 다운받으실수 있습니다.

https://dog-developers.tistory.com/30

반응형

'JAVA > Spring Framework' 카테고리의 다른 글

사용자관리 프로젝트  (0) 2019.02.07
DI 애플리케이션 작성(4)  (0) 2019.02.07
DI 애플리케이션 작성(2)  (0) 2019.02.06
DI 애플리케이션 작성(1)  (0) 2019.02.06
IoC 컨테이너와 DI(Dependency Injection)  (2) 2019.02.06
Comments