스프링5 의존성주입(DI)관련 어노테이션, @Autowired, @Scope, @Bean
@Qualifier, @Required, @Value
@DependsOn, @Primary, @Lazy
n @Autowired
ü Spring Framework에 종속적인 어노테이션.
ü Type Driven Injection
ü 여러 개의 빈이 검색될 경우 @Qualifier(name="xxx")로 구분한다.
ü 기본적으로 @Autowired된 속성은 모두 빈이 주입 되어야 한다.
ü (주입될 빈이 없는 경우가 있다면 required=false로 하면 오류는 발생하지 않는다.)
ü 멤버변수, setter 메소드, 생성자, 일반 메소드에 적용 가능
[Emp.java]
interface Emp {
public abstract void gotoOffice();
}
[Programmer.java]
@Service
class Programmer implements Emp {
public void gotoOffice() {
System.out.println("프로그래머 출근 합니다.");
}
}
[Designer.java]
@Service
class Designer implements Emp {
public void gotoOffice() {
System.out.println("디자이너 출근 합니다.");
}
}
[Develope.java]
@Service
public class Develope {
Emp emp;
@Autowired
public Develope(@Qualifier(value="designer") Emp emp) {
this.emp = emp;
}
void coding() {
emp.gotoOffice();
System.out.println("개발합니다...");
}
}
n @Scope
ü 일반적으로 @Component, @Service, @Repository 등으로 자동 스캐닝한 자바빈은 싱글톤 형태로 하나만 생성하는데(default : @Scope가 쓰여져 있지 않을 때는 scope="singleton") 이를 변경하려면 @Scope 어노테이션을 사용하면 된다. 즉 빈의 범위를 설정한다.
singleton – Spring IoC 컨테이너당 하나의 빈을 리턴
prototype – 요구가 있을 때 마다 새로운 빈을 만들어 리턴
request - HTTP request 객체당 하나의 빈을 리턴
session - HTTP session 당 하나의 빈만 존재
globalSession – 포틀릿의 global Http Session 생명주기 동안 하나의 빈만 존재, 표준 HTTP 세션 범위 유사하며, 단지 포틀릿(Portlet) 기반 웹 응용 프로그램의 맥락에서 적용된다. globalSession 은 포틀릿 컨테이너를 지원한다.
@Component
@Scope("prototype") //요구시마다 하나의 새로운 빈을 리턴
class Ojc {
……
}
<bean id="ojc" class="oraclejava.edu.Ojc" scope="prototype"/>
n @Bean
ü @Configuration으로 설정된 클래스의 메소드의 사용 가능.
ü 메소드가 Return 하는 객체가 Bean으로 등록된다.
ü @Component는 @Configuration 없이 개발자가 작성한 클래스 위에 기술하여 그 클래스의 객체를 빈으로 만들지만 @Bean은 개발자가 만든 클래스가 아닌, 직접 제어 불가능한 외부 라이브러리(클래스)를 빈으로 만들 때 사용한다.
ü @Bean 어노테이션에 name or value 속성으로 빈의 ID를 지정하지 않으면 메소드 이름을 camelCase 한 것이 빈의 ID가 된다. (첫 글자는 소문자로 이후 연결된 단어들의 첫 글자는 대문자로 표기)
@Configuration //자바설정파일
class A {
@Bean(name=”makeArrayList”)
@Bean(value=”makeArrayList”)
@Bean(“makeArrayList”)
@Bean
public ArrayList<String> makeArrayList() {
Return new ArrayList<String>();
}
}
n @Qualifier
ü @Autowired에서 같은 TYPE의 객체가 여러 개인 경우 오류가 발생하는데 이러한 모호한 상황에서 사용하려는 빈을 제공하기 위해 @Qualifier를 사용한다.
Car 인터페이스를 구햔한 Sonata, Santafe 두 클래스가 있고 둘다 타입은 Car 이다.
@Component(“sonata”)
class Sonata implements Car{}
@Component(“santafe”)
class Santafe implements Car {}
생성자 주입
class Sonata {
@Autowired
public Sonata(@Qualifier("sonata") Car car) {
this.car = car;
}
}
세터주입
@Autowired
void setCar(@Qualifier("santafe") Car car) {
this.car = car;
}
아래도 동일하다.
@Autowired
@Qualifier("santafe")
void setCar(Car car) {
this.car = car;
}
필드주입
@Autowired
@Qualifier("santafe")
Car car;
n @Required
ü Setter 메소드 위에 기술하여 필수 프로퍼티를 설정하는 용도로 사용된다.
package day1;
public class Emp {
private String ename;
@Required
public void setEname(String ename) { this.ename = ename; }
public String getEname() { return this.ename; }
}
XML설정에서(Beans.xml)…
<context:annotation-config/>
<bean id="emp" class="day1.Emp">
<!-- 아래 프로퍼티를 설정하지 않으면 오류 -->
<!-- <property ename="ename" value="홍길동" /> -->
</bean>
main에서…
ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
Emp emp = (Student) context.getBean("emp");
System.out.println(“Ename : " + emp.getEname() );
오류메시지 Property 'ename' is required for bean 'emp'
n @Value
ü 빈에 속성 값을 주입하기 위해 사용한다.
ü 물론 정적 값을 주입하는 것은 그다지 유용하지 않으며, 따라서 @Value의 자리 표시자 문자열(placeholder strings)을 사용하여 외부 소스 (예 : .properties 또는 .yaml 파일)에 정의 된 값을 연결할 수 있다.
생성자주입
Sonata(@Value("8888") int carNum) {
this.carNum = carNum;
}
세터주입
@Autowired
void setCarNum(@Value("8888") int carNum) {
this.carNum = carNum;
}
아래와 동일하다.
@Value("8888")
void setCarNum(int carNum) {
this.carNum = carNum;
}
필드주입
@Value("8888")
int carNum;
다른 예를 보자. 프로퍼티 파일에서 어떤 값을 읽어 동적으로 주입하는 경우이다.
application.properties
emp.name=scott
Emp 클래스
@Component
public class Emp {
@Value("${emp.name}")
private String name;
……
}
n @DependsOn
ü 빈의 초기화 순서를 지정한다.
ü 스프링이 @DependsOn이 있는 다른 빈을 초기화 하도록 할 수 있다. DependsOn에 따라 결정되는 종속성에 의해 자동으로 수행 된다.
@Component
@DependsOn("engine")
class Sonata implements Car {}
@Bean
@DependsOn("fuel")
Engine engine() {
return new Engine();
}
n @Primary
ü @Autowired 사용시 동일한 TYPE의 Bean이 여러 개 있을 때 Bean에 더 높은 우선 순위를 부여하기 위해 @Primary를 사용한다. @Qualifier를 사용하여 일일이 빈의 ID를 지정해도 되지만 @Primary로 표시해 두면 @Autowired만 했을 때 @Primary로 지정된 빈이 주입된다.
ü 가장 자주 사용되는 빈을 @Primary로 표시하면 된다.
@Component
@Primary
class Sonata implements Car {}
@Component
class Santafe implements Car {}
@Component
class Driver {
@Autowired
Car car; //Sonata 가 주입된다.
}
@Component
class Santafe{
@Autowired
@Qualifier("santafe")
Car car;
}
n @Lazy
ü 스프링 빈을 느리게 초기화하고 싶을 때 @Lazy를 사용한다.
ü 기본적으로 Spring은 애플리케이션 서블릿 컨텍스트의 시작시 모든 싱글 톤 빈을 생성한다. 그러므로 애플리케이션 시작 시가 아니라 요청할 때 Bean을 생성해야하는 경우가 있는데 이때 @Lazy를 사용한다.
ü @Lazy는 정확히 어디에 배치했는지에 따라 다르게 작동할 수 있다.
ü 예를 들어 어떤 빈 A가 @Lazy 때문에 느리게 로딩하려고 하지만 B클래스의 Setter에서 A를 주입 받고, B 클래스 자체는 Eager 로딩인 경우 A의 @Lazy는 작동하지 않는다.
ü 다음과 같은 경우 @Lazy가 잘 작동한다.
l @Lazy가 팩토리 메소드의 @Bean에 위치하는 경우 메소드 호출을 지연시킨다.
@Lazy
@Bean
Sonata sonata() { return new Sonata(); } //Lazy Loading
}
l @Lazy가 @Configuration 클래스에 위치하는 경우 @Bean 메소드가 영향을 받는다.
@Configuration
@Lazy
class CarConfig {
@Bean //Lazy Loading
Sonata sonata() { return new Sonata(); }
}
l @Lazy가 @Configuration 클래스가 아닌 @Component 클래스에 위치하는 경우 이 Bean은 느리게 초기화 된다.
@Component
@Lazy
class Sonata {
……
}
l @Lazy가 @Autowired 생성자, 세터, 또는 필드에 위치하는 경우 종속성 자체를 느리게 로드한다.(프록시를 통해)
아래 예문은 CarConfig는 Lazy Loading이지만 sonata() 메소드는 Eager Loading을 한다.
@Configuration
@Lazy
class CarConfig {
@Bean
@Lazy(false)
Sonata sonata() { return new Sonata(); }
}
#스프링강의, #스픵강좌, #스프링동영상, #스프링어노테이션, @스프링교육, #Spring어노테이션, #@Autowired, #@Scope, #@Bean, #@Qualifier, #@Required, #@Value, #@DependsOn, #@Primary, #@Lazy
댓글 없음:
댓글 쓰기