1. Bean 등록 메타정보 구성 전략
1. XML 설정 단독 사용
- 모든 Bean을 명시적으로 XML에 등록하는 방법
- 생성되는 모든 Bean을 XML에서 확인할 수 있다는 장점이 있으나 Bean의 개수가 많아지면
XML 파일을 관리하기 번거로울 수 있다.
- 여러 개발자가 같은 설정파일을 공유해서 개발하다 보면 설정파일을 동시에 수정하다가 충돌이
일어나는 경우도 적지 않다.
- DI에 필요한 적절한 setter메서드 또는 constructor가 코드 내에 만드시 존재해야 한다.
1.1 XML 단독 사용방식을 사용한 코드
1. 인터페이스 Printer.java
1 2 3 4 5 | package di.xml; public interface Printer { public void print(String message); } | cs |
2. 인터페이스 구현 클래스1 StringPrinter.java
1 2 3 4 5 6 7 8 9 10 11 12 13 | package di.xml; public class StringPrinter implements Printer { private StringBuffer buffer = new StringBuffer(); public void print(String message) { this.buffer.append(message); } public String toString() { return this.buffer.toString(); } } | cs |
3. 인터페이스 구현클래스2 ConsolePrinter.java
1 2 3 4 5 6 7 | package di.xml; public class ConsolePrinter implements Printer { public void print(String message) { System.out.println(message); } } | cs |
4. 모델 Hello.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 | package di.xml; import java.util.List; public class Hello { String name; Printer printer; List<String> names; public Hello() { System.out.println("Hello Default Constructor Called.."); } public Hello(String name, Printer printer) { this.name = name; this.printer = printer; } public List<String> getNames() { return this.names; } public void setNames(List<String> list) { this.names = list; } public void setName(String name) { System.out.println("setName() called " + name); this.name = name; } public void setPrinter(Printer printer) { System.out.println("setPrinter() called " + printer.getClass().getName()); this.printer = printer; } public String sayHello() { return "Hello " + name; } public void print() { this.printer.print(sayHello()); } } | cs |
5. DI를 위한 bean.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 | <?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" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd"> <!-- StringPrinter 클래스를 bean으로 등록 --> <bean id="stringPrinter" class="di.xml.StringPrinter"/> <!-- Console.Printer 클래스를 bean으로 등록 --> <bean id="consolePrinter" class="di.xml.ConsolePrinter"/> <!-- setter injection --> <!-- Hello 클래스를 bean으로 등록 --> <bean id="helloBean" class="di.xml.Hello" scope="singleton"> <property name="name" value="상현"/> <property name="printer" ref="stringPrinter"/> </bean> <!-- constructor injection --> <bean id="helloConstructor" class="di.xml.Hello"> <!-- constructor injection --> <constructor-arg index="0" value="생성자" /> <constructor-arg index="1" ref="consolePrinter" /> </bean> </beans> | cs |
6. 검증에 필요한 jUnit 사용 Test 클래스 HelloBeanTest.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 | package di.xml.test; import org.junit.Assert; import static org.junit.Assert.*; import org.junit.Test; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.support.GenericXmlApplicationContext; import di.xml.Hello; import di.xml.Printer; public class HelloBeanTest { @Test public void hellobean() { // 1. Spring Container 생성 BeanFactory factory = new GenericXmlApplicationContext("config/beans.xml"); // 2. Bean 을 요청 Hello helloBean = (Hello)factory.getBean("helloBean"); Hello helloBean2 = factory.getBean("helloBean",Hello.class); // 주소 비교 Assert.assertSame(helloBean, helloBean2); assertSame(helloBean, helloBean2); // 값 비교 // name변수 값이 잘 주입되었는지 확인 가능` assertEquals("Hello 상현", helloBean.sayHello()); // printer 변수 잘 주입 되었는지 확인 helloBean.print(); Printer printer = factory.getBean("stringPrinter", Printer.class); assertEquals("Hello 상현", printer.toString()); } } | cs |
결과 :
2. 어노테이션과 XML 설정 혼용해서 사용
- Bean으로 사용될 클래스에 특별한 어노테이션(Annotation)을 부여해주면 이런 클래스를 자동으로 찾아서 Bean으로 등록한다.
- @Component 어노테이션이 선언된 클래스를 자동으로 찾아서 Bean으로 등록해주는 방식을
빈 스캐닝(Bean Scanning)을 통한 자동인식 Bean 등록기능이라고 한다.
- 어노테이션을 부여하고 자동 스캔으로 Bean을 등록 하면 XML문서 생성과 관리에 따른 수고를 덜어주고
개발속도를 향상 시킬수 있다.
- 애플리케이션에 등록될 Bean이 어떤것들이 있고, 의존관계가 어떻게 되는지를 한눈에 파악할수 없다는 단점이 있다.
2.1 어노테이션과 XML 혼용방식을 사용한 코드
1. 인터페이스 Printer.java
1 2 3 4 5 | package di.annotation; public interface Printer { public void print(String message); } | cs |
2. 인터페이스 구현 클래스1 StringPrinter.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | package di.annotation; import org.springframework.stereotype.Component; @Component public class StringPrinter implements Printer { private StringBuffer buffer = new StringBuffer(); public void print(String message) { this.buffer.append(message); } public String toString() { return this.buffer.toString(); } } | cs |
3. 인터페이스 구현클래스2 ConsolePrinter.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | package di.annotation; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; /* * @Component 의 default 값은 consolePrinter */ @Component("consolePrinter") @Scope("singleton") public class ConsolePrinter implements Printer { public void print(String message) { System.out.println(message); } } | cs |
4. 기본생성자와 setter메소드를 뺀 모델 Hello.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 | package di.annotation; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @Component("helloA") public class Hello { String name; Printer printer; List<String> names; public Hello() { System.out.println("Hello Default Constructor Called.."); } // public Hello(String name, Printer printer) { // this.name = name; // this.printer = printer; // } // 생성자 어노테이션 @Autowired public Hello(@Value("어노테이션") String name, @Qualifier("consolePrinter") Printer printer) { this.name = name; this.printer = printer; } public List<String> getNames() { return this.names; } public void setNames(List<String> list) { this.names = list; } // public void setName(String name) { // System.out.println("setName() called " + name); // this.name = name; // } // // public void setPrinter(Printer printer) { // System.out.println("setPrinter() called " + printer.getClass().getName()); // this.printer = printer; // } public String sayHello() { return "Hello " + name; } public void print() { this.printer.print(sayHello()); } } | cs |
5. DI를 위한 annot.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <?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:c="http://www.springframework.org/schema/c" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd"> <context:component-scan base-package="di.annotation" /> </beans> | cs |
6. 검증에 필요한 jUnit 사용 Test 클래스 HelloBeanTest.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 | package di.annotation.test; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import di.annotation.Hello; import di.annotation.Printer; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations="classpath:config/annot.xml") public class HelloAnnotationTest { @Autowired Hello hello; @Autowired @Qualifier("stringPrinter") Printer printer; @Test public void hello() { System.out.println(hello.sayHello()); hello.print(); } } | cs |
결과
3. 어노테이션 설정 단독 사용
- @Configuration 어노테이션과 @Bean 어노테이션을 이용해서 스프링 컨테이너에 새로운 빈 객체를 제공할 수 있다.
- Spring 3.0 부터는 어노테이션을 이용한 Bean의 등록과 Bean 들 간의 연결설정을 자바코드 내부에 하므로
XML을 전혀 사용하지 않는다.
3.1 XML 안쓰는 방법 전략 - 1
1. @Bean어노테이션을 사용한 HelloJavaConfig.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 | package di.xml.config; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import di.xml.ConsolePrinter; import di.xml.Hello; import di.xml.Printer; import di.xml.StringPrinter; //전략 3-1 xml 안쓰는 방법 @Configuration public class HelloJavaConfig { @Bean public Hello hello() { Hello hello = new Hello(); hello.setName("Java컨피그"); hello.setPrinter(printer()); return hello; } @Bean @Qualifier("stringPrinter") public Printer printer() { Printer printer = new StringPrinter(); return printer; } @Bean @Qualifier("consolePrinter") public Printer cPrinter() { Printer printer = new ConsolePrinter(); return printer; } } | cs |
2. AnnotationConfigContextLoader를 사용한 HelloJavaConfigTest.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 | package di.xml.test; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.support.AnnotationConfigContextLoader; import di.xml.Hello; import di.xml.Printer; import di.xml.config.HelloJavaConfig; // 전략 3의 1번째 방법 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes=HelloJavaConfig.class, loader=AnnotationConfigContextLoader.class) public class HelloJavaConfigTest { @Autowired Hello hello; @Autowired @Qualifier("stringPrinter") Printer printer; @Test public void hello() { System.out.println(hello.sayHello()); hello.print(); System.out.println(printer.toString()); } } | cs |
결과
3.2 XML 안쓰는 방법 전략 - 2
1. @ComponentScan을 사용한 HelloJavaConfig2.java
1 2 3 4 5 6 7 8 9 10 | package di.annotation.config; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @Configuration @ComponentScan(basePackages= {"di.annotation"}) public class HelloJavaConfig2 { } | cs |
2. AnnotationConfigContextLoader를 사용한 HelloJavaConfigTest2.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 | package di.annotation.test; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.support.AnnotationConfigContextLoader; import di.annotation.Hello; import di.annotation.config.HelloJavaConfig2; // 전략 3의 2번째 방법 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes=HelloJavaConfig2.class, loader=AnnotationConfigContextLoader.class) public class HelloJavaConfig2Test { @Autowired Hello hello; @Test public void hello() { System.out.println(hello.sayHello()); hello.print(); } } | cs |
결과
Bean 등록 전략 테스트 코드 :
'전체 > Spring' 카테고리의 다른 글
Spring AOP, Aspect 개념 특징, AOP 용어 정리 (1) | 2019.02.24 |
---|---|
MyBatis 개념, 특징, DB 액세스 아키텍처, 데이터 액세스 계층 흐름도, 주요 컴포넌트 역할 정리 (0) | 2019.02.24 |
Bean 등록 및 의존관계 주입 Annotation 종류 (0) | 2019.02.23 |
jUnit 개념, 특징, 어노테이션, 메서드 (1) | 2019.02.23 |
IoC와 Spring DI (0) | 2019.02.23 |