본문 바로가기

Dev/[Java]

[Spring] 4. DI전략 3단계

반응형

 

 

2/1(월)

Spring DI 전략 3

 

 

 

전략3부터는 XML쓰지 않고 자바 코드로 컨테이너 설정 함

 

Configuration 어노테이션과 @Bean 어노테이션 사용한다.

전략2단계에서 @Component는 클래스 위에 선언했었다.

 

@Configuration도 비슷한 역할

전략1에서 전략3 사용방법

설정 역할을 하는 자바 클래스 위엔(XML역할을 하는 자바 클래스 위에는)

@Configuration 붙인다.

 

 

@Configuration

: 설정 역할을 하는 JAVA 클래스위에 선언된다.

 

@ComponentScan

: <context:component-scan base-package="" />

: XML에 이렇게 썻던걸 대신하는 어노테이션..

: Spring Bean(Component)를 Auto Scanning 해주는 역할, 설정 클래스 위에 선언

: 설정 클래스 위에 선언

 

@Bean 

: <bean id="" class""/>

: Spring Bean으로 선언해주는 역할

: 메서드 위에 붙는다.

 

 

 

 

 

 

@Configuration

@ComponentScan

@PropertySource

사용법 ( 아래 클래스에 대한 설정파일과 테스트를 해볼 것이다.)

 

package myspring.di.annot;

import javax.annotation.Resource;

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("helloBean")
public class HelloBean {
	
	// <property name="name value="어노테이션" />
	// 이거랑 똑같은거다.
	@Value("${name}")
	private String name;
	
	// <property name="printer" ref="stringPrinter" />
//	@Autowired
//	@Qualifier("stringPrinter")
	@Resource(name="${printer}")
	private PrinterBean printer;
	
	public HelloBean() {
		System.out.println("Hello Default constructor called");
	}
	
//	@Autowired
//	public HelloBean(@Value("생성자어노테이션")String name, 
//					 @Qualifier("stringPrinter")PrinterBean printer) {
//		this.name = name;
//		this.printer = printer;
//	}
	
	public HelloBean(String name, PrinterBean printer) {
		this.name = name;
		this.printer = printer;
	}

	public void setName(String name) {
		System.out.println("Hello setName() called" + name);
		this.name = name;
	}
	public void setPrinter(PrinterBean printer) {
		System.out.println("Hello setPrinter() called" + printer.getClass().getName());
		this.printer = printer;
	}
	
	public String sayHello() {
		return "Hello" + this.name;
	}
	
	public void print() {
		this.printer.print(sayHello());
	}
	
}

 

 

 

 

 

configuration package생성 후 configuration class생성

이후 아래와 같이 만들어준다.

package myspring.di.annot.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

@Configuration

//<!--  DI전략2의 Component Auto Scanning 설정 -->
//<context:component-scan base-package="myspring.di.annot" />
@ComponentScan(basePackages = {"myspring.di.annot"})

//<!-- Properties 파일 만들것이다. -->
//<context:property-placeholder location="classpath:config/values.properties"/> 	
@PropertySource("classpath:config/values.properties")
public class HelloBeanConfig {
	

}

 

전략3에서 Testcase 만들 때, XML이 없기 때문에

@ContextConfiguration()에서 Config Class를 알려줘야한다.

 

그 후 설정XML을 사용할 때 생성됬던 Spring 컨테이너 역할을 하는 클래스(GenericXmlApplicationContext)를 사용했었다.  그러나 전략3에서는

설정 클래스 사용할 때 AnnotationConfigApplicationContext 컨테이너 클래스를 사용해야 한다.

 

package myspring.di.annot.config.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 myspring.di.annot.HelloBean;
import myspring.di.annot.config.HelloBeanConfig;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = HelloBeanConfig.class, loader = AnnotationConfigContextLoader.class )
public class HelloBeanConfigTest {
	
	@Autowired
	HelloBean hello;
	
	
	@Test
	public void config1() {
		System.out.println(hello.sayHello());

	}

}

 

@Bean사용법

@Bean은 @Component와 같은 역할을 한다.

아래 클래스에 대한 Config파일과 테스트를 진행할것이다.

 

package myspring.di.xml;

import java.util.Map;

public class Hello {
	private String name;
	private Printer printer;
	private Map<Integer,String> myMaps;
	
	public Hello() {
		System.out.println("Hello Default constructor called");
	}
	
	public Hello(String name, Printer printer) {
		this.name = name;
		this.printer = printer;
	}

	public void setName(String name) {
		System.out.println("Hello setName() called" + name);
		this.name = name;
	}
	public void setPrinter(Printer printer) {
		System.out.println("Hello setPrinter() called" + printer.getClass().getName());
		this.printer = printer;
	}
	
	public Map<Integer,String> getMyMaps() {
		return myMaps;
	}
	
	public void setMyMaps(Map<Integer, String> myMaps) {
		this.myMaps = myMaps;
	}

	public String sayHello() {
		return "Hello" + this.name;
	}
	
	public void print() {
		this.printer.print(sayHello());
	}
	
}

또한 아래 XML파일 설정값에 대한 것이다.

 

<!-- Hello Bean 설정 -->
	<!-- 
		scope종류
		1. singleton (default) : 객체 생성 하나만하겠다.
		2. prototype : 객체 생성 항상 한다.
		3. request, session : 웹에서 사용하는 스코프, session이 request 보다 범위가 넓음. 
	 -->
	<bean id="hello" class="myspring.di.xml.Hello" scope="singleton">
		<!-- Setter Injection 설정 -->
		<property name="name" value="스프링이다." />
		<property name="printer" ref="strPrinter" />
		<property name="myMaps">
			<map>
				<entry key="100" value="스프링클라우드" />
				<entry key="200" value="스프링배치" />
				<entry key="300" value="스프링쿠버네티스" />
			</map>
		</property>
	</bean>

 

 

package 생성하고, config 파일생성한다.

Property 파일에 있는 값들을 주입한다.

그러니까 여기 보면... Printer stringPrinter(){} 메서드,

Printer consolePrinter() 메서드위에 @Bean이 붙은 것을 볼 수 있다.

package myspring.di.xml.config;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.Scope;

import myspring.di.xml.ConsolePrinter;
import myspring.di.xml.Hello;
import myspring.di.xml.Printer;
import myspring.di.xml.StringPrinter;

@Configuration
//<!-- Properties 파일 만들것이다. -->
//<context:property-placeholder location="classpath:config/values.properties"/> 	
@PropertySource("classpath:config/values.properties")
public class HelloConfig {
	// Bean의 ID는 메서드이름이다.
	@Value("${name}")
	String name;
	
	@Resource(name = "${printer}")
	Printer printer;
	
	@Bean
	@Scope(value = "singleton")
	public Hello hello(){
		Hello hello= new Hello();
		hello.setName(name);
		//hello.setPrinter(stringPrinter());
		hello.setPrinter(printer);
		return hello;
	}
	
	@Bean
	public Printer stringPrinter() {
		Printer printer = new StringPrinter();
		return printer;
	}
	
	@Bean
	public Printer consolePrinter() {
		Printer printer = new ConsolePrinter();
		return printer;
	}
	
	
	
	
}

 

 

 

이걸 이제 테스트쪽으로 가보면

@Autowired
	Hello hello;
	
	@Autowired
	@Qualifier("hello")
	Hello hello2;
	
	@Autowired
	@Qualifier("stringPrinter")
	Printer printer;
	
	@Test 
	public void consoleConfig() {
		System.out.println(hello.sayHello());
		hello.print();
	}
	
	@Test @Ignore
	public void config(){
		System.out.println(hello == hello2);
		System.out.println(hello.sayHello());
		hello.print();
		System.out.println(printer.toString());
	}

 

 

반응형