3-8 Spring DI 활용하기 - 이론(4)

서현우·2022년 5월 17일
0

스프링의정석

목록 보기
39/85

6. 스프링 애너테이션 - @Resource

Spring container에서 "이름(by Name)"으로 빈을 검색해서 참조변수에 자동 주입(DI).
일치하는 이름의 빈이 없으면, 예외 발생.

//아래 @Autowired에 @Qualifier("name")붙인 것과 같음
//@Resource(name="이름")
Class car {
	@Resource(name="superEngine")
	Engine engine;

//@Autowired로 byType으로 검색 후, 
//같은 타입의 빈이 n개면 
//@Qualifier("이름")으로 주입할 빈을 지정.
Class car {
	@Autowired
	@Qualifier("superEngine")
	Engine engine;
	
Class car {
//이름 생략 가능(생략하면 참조변수 engine이 빈의 이름이 됨)
//	@Resource(name="engine")
	@Resource
	Engine engine;
	

6. 스프링 애너테이션 - @Component

  1. <component-scan>로 @Component가 클래스를 자동 검색해서 빈으로 등록
<context:component-scan base-package="com.fastcampus.ch3" />
//서브 패키지까지 검색
//  <bean id="superEngine" class="com.fastcampus.ch3.SuperEngine"/>
//  @Component("superEngine") //id 생략 가능. class의 첫글자를 소문자로 바꾼 id를 빈에 저장.
	@Component
	class SuperEngine extends Engine {}
  1. @Controller, @Service, @Repository, @ControllerAdvice의 메타 애너테이션

<component-scan>을 하면 @Controller, @Service, @Repository, @ControllerAdvice가 붙으면 자동 등록됨.
(ex. homeController가 자동 등록됨.)

@Value, @PropertySource

//맵으로 환경변수들이 저장
Map<String, String> env = System.getenv();

//시스템 프로퍼티들이 담긴 프로퍼티 객체가 저장
Properties prop = System.getPorperties();

ac.getBean(SysInfo.class)

@Component
@PropertySource("setting.properties")
class SysInfo {

	//사용자의 시간대를 가져옴
	@Value("#{systemProperties['user.timezone']}")
	String timeZone;
	
	//현재 작업 디렉토리를 읽어옴
	@Value("#{systemEnvironment['PWD']}")
	String curDir
	
//[외부 파일]
//src/main/resources/setting.properties]
//key, value 형태
autosaveDir=autosave
autosave=true
autosaveInterval=30

	//외부 파일 주입
	//자동 저장되는 폴더
	@Value("${autosaveDir}")
	String autosaveDir;
	
	//자동 저장되는 주기
	@Value("${autosaveInterval}")
	int autosaveInterval;
	
	//자동 저장 유무
	@Value("${autosave}")
	boolean autosave;

7. 스프링 애너테이션 vs 표준 애너테이션(JSR-330)(Java Spec Request)

Java제공 애너테잉션

javax.inject-1.jar - @Inject, @Named, @Qualifier, @Scope, @Singleton
annotations-api.jar - @Resource, @ManagedBean, @PreDestroy, @PostContruct

[아주 가볍게 보고 넘어가기!!]

스프링 애너테이션표준 애너테이션비고
@Autowired@Inject@Inject에는 required속성이 없음
Qualifier@Qualifier, @Named스프링의 @Qualifier는 @Named와 유사
X@Resource스프링에는 이름 검색이 없음
@Scope("singleton")@Singleton표준에서는 prototype이 디폴트
@Component@Named, @ManagedBean표준에서는 반드시 이름이 있어야 함

8. 빈의 초기화 - <property>와 setter

<property>를 이용한 빈 초기화. setter를 이용

Class Car {
	String color;
	int oil;
	Engine engine;
	Door[] door;
}

//아래 setter와 <property>를 이용한 빈 초기화는 같은 코드
Car car = new Car();
car.setColor("red");
car.setOil(100);
car.setEngine(engine);
car.setDoors(new Door[]{new Door(), new Door()};

=================================================

//위의 세터와 같은 코드.
//<property>를 이용한 빈 초기화. setter를 이용.
//<property>설정 파일에 저장.
//car.setColor("red"); 처럼 세터를 따로 호출 안해도 됨.
<bean id="car" class="com.fastcampus.ch3.Car">
	<property name="color" value="red"/>
	<property name="oil" value="100"/>
	<property name="engine" ref="engine"/>
	<property name="doors">
		<array value-type="com.fastcampus.ch3.Door">
			<ref bean="door"/>
			<ref bean="door"/>
		</array>
	</property>
</bean>
<bean id="engine" class="com.fastcampus.ch3.Engine"/>
<bean id="door" class="com.fastcampus.ch3.Door" scope="prototype"/>

8. 빈의 초기화 - <contructor-arg>와 생성자

<construgtor-arg>를 이용한 빈 초기화. 생성자를 이용.

public Car(String color, int oil, Engine engine, Door[] doors)
	this.color = color;
	this.oil = oil;
	this.engine = engine;
	this.doors = doors;
}

=================================================================

//위 생성자를 이용하는 코드.
//<constructor-arg>를 이용한 빈 초기화. 생성자를 이용.
//생성자가 있어야 아래 태그를 사용 할 수 있음.
<bean id="car" class="com.fastcampus.ch3.Car">
	<constructor-arg name="color" value="red"/>
	<constructor-arg name="oil" value="100"/>
	<constructor-arg name="engine" ref="engine"/>
	<constructor-arg name="doors">
		<array value-type="com.fastcampus.ch3.Door">
			<ref bean="door"/>
			<ref bean="door"/>
		</array>
	</constructor-arg>
</bean>
<bean id="engine" class="com.fastcampus.ch3.Engine"/>
<bean id="door" class="com.fastcampus.ch3.Door" scope="prototype"/>

빈의 초기화 - <list>, <set>, <map>

//<list>, String 또는 기본형일 때 빈의 초기화
<property name="colors">
	<list>
		<value>red</value>
		<value>green</value>
		<value>blue</value>
		<value>white</value>
	</list>
</property>

//<list>, 참조형일 때 빈의 초기화
<property name="engines">
	<list>
		<ref bean="superEngine"/>
		<ref bean="turboEngine"/>
	</list>
</property>

//<set>을 사용한 빈의 초기화
<property name="engines">
	<set>
		<ref bean="superEngine"/>
		<ref bean="turboEngine"/>
	</set>
</property>

//<map>, 기본형일 때 빈의 초기화
<property name="doorColors">
	<map>
		<entry key="left" value="red"/>
		<entry key="right" value="blue"/>
	</map>
</property>

//<map>, 참조형일 때 빈의 초기화
<property name="doors">
	<map>
		<entry key="left" value-ref="door"/>
		<entry key="right" value-ref="door"/>
	</map>
</property>

ApplicationContextTest.java

@Value, @PropertySource 실습

package com.fastcampus.ch3;

import org.springframework.beans.factory.annotation.*;
import org.springframework.context.*;
import org.springframework.context.annotation.*;
import org.springframework.context.annotation.Scope;
import org.springframework.context.support.*;
import org.springframework.stereotype.*;

import javax.inject.*;
import java.util.*;

@Component
@Scope("prototype")
class Door {}
@Component class Engine {}
@Component class TurboEngine extends Engine {}
@Component class SuperEngine extends Engine {}

@Component
class Car {
    @Value("red") String color;
    @Value("100") int oil;
//    @Autowired
      Engine engine;

//    @Autowired
      Door[] doors;

    //생성자가 여러개 일때는 @Autowired쓰는 것을 권장
    public Car() {}
//    @Autowired
    public Car(@Value("red") String color, @Value("100") int oil, Engine engine, Door[] doors) {
        this.color = color;
        this.oil = oil;
        this.engine = engine;
        this.doors = doors;
    }

    @Override
    public String toString() {
        return "Car{" +
                "color='" + color + '\'' +
                ", oil=" + oil +
                ", engine=" + engine +
                ", doors=" + Arrays.toString(doors) +
                '}';
    }
}


@Component
@PropertySource("setting.properties")
class SysInfo {
    @Value("#{systemProperties['user.timezone']}")
    String timeZone;
    @Value("#{systemEnvironment['APPDATA']}")
    String currDir;
    @Value("${autosaveDir}")
    String autosaveDir;
    @Value("${autosaveInterval}")
    int autosaveInterval;
    @Value("${autosave}")
    boolean autosave;

    @Override
    public String toString() {
        return "SysInfo{" +
                "timeZone='" + timeZone + '\'' +
                ", currDir='" + currDir + '\'' +
                ", autosaveDir='" + autosaveDir + '\'' +
                ", autosaveInterval=" + autosaveInterval +
                ", autosave=" + autosave +
                '}';
    }
}

public class ApplicationContextTest {
    public static void main(String[] args) {
        ApplicationContext ac = new GenericXmlApplicationContext("config.xml");
//      Car car = ac.getBean("car", Car.class); // 타입을 지정하면 형변환 안해도됨. 아래의 문장과 동일
        Car car  = (Car) ac.getBean("car"); // 이름으로 빈 검색
        System.out.println("car = " + car);

        System.out.println("ac.getBean(SysInfo.class) = " + ac.getBean(SysInfo.class));
        Map<String, String> map = System.getenv();
        System.out.println("map = " + map);
        System.out.println("System.getProperties() = " + System.getProperties());
    }
}
profile
안녕하세요!!

0개의 댓글