Post

Spring Core Annotations

1. DI 관련 주석

1) @Autowired

@Autowired를 사용하여 Spring이 해결하고 주입할 종속성을 표시 할 수 있다. 생성자, 설정자 또는 필드 주입과 함께 이 주석을 사용할 수 있다.

Constructor injection

1
2
3
4
5
6
7
8
class Car {
    Engine engine;

    @Autowired
    Car(Engine engine) {
        this.engine = engine;
    }
}

Setter injection

1
2
3
4
5
6
7
8
class Car {
    Engine engine;

    @Autowired
    void setEngine(Engine engine) {
        this.engine = engine;
    }
}

Field injection

1
2
3
4
class Car {
    @Autowired
    Engine engine;
}

@Autowired에는 기본값이 true인 필수 라는 boolean 인수가 있다. 연결하기에 적합한 빈을 찾지 못할 때 Spring의 동작을 조정한다. true 이면 예외가 발생하고, 그렇지 않으면 아무것도 연결되지 않는다.

생성자 주입을 사용하는 경우 모든 생성자 인수가 필수이다.

버전 4.3부터는 최소한 두 개의 생성자를 선언하지 않는 한 명시적으로 @Autowired로 생성자에 주석을 달 필요가 없다.

2) @Bean

@Bean은 Spring 빈을 인스턴스화하는 팩토리 메소드를 표시한다.

1
2
3
4
@Bean
Engine engine() {
    return new Engine();
}

Spring은 반환 유형의 새 인스턴스가 필요할 때 이러한 메서드를 호출한다.

결과 빈은 팩토리 메소드와 동일한 이름을 갖는다. 다르게 이름을 지정하려면 이 주석의 name 또는 value 인수를 사용하여 그렇게 할 수 있다(인수 값은 인수 name의 별칭이다).

1
2
3
4
@Bean("engine")
Engine getEngine() {
    return new Engine();
}

@Bean으로 주석이 달린 모든 메소드는 @Configuration 클래스에 있어야 한다.

3) @Qualifier

모호한 상황에서 사용하려는 빈 id 또는 빈 name을 제공하기 위해 @Autowired와 함께 @Qualifier를 사용한다.

예를 들어, 다음 두 Bean은 동일한 인터페이스를 구현한다.

1
2
3
class Bike implements Vehicle {}

class Car implements Vehicle {}

Spring이 Vehicle 빈을 주입해야 하는 경우에는 여러 개의 일치하는 정의로 끝난다. 이러한 경우 @Qualifier 주석을 사용하여 명시적으로 Bean의 이름을 제공할 수 있다.

Constructor injection 사용

1
2
3
4
@Autowired
Biker(@Qualifier("bike") Vehicle vehicle) {
    this.vehicle = vehicle;
}

Setter injection 사용

1
2
3
4
@Autowired
void setVehicle(@Qualifier("bike") Vehicle vehicle) {
    this.vehicle = vehicle;
}

또는

1
2
3
4
5
@Autowired
@Qualifier("bike")
void setVehicle(Vehicle vehicle) {
    this.vehicle = vehicle;
}

field injection 사용

1
2
3
@Autowired
@Qualifier("bike")
Vehicle vehicle;

4) @Value

Bean에 속성 값을 주입하기 위해 @Value를 사용할 수 있다. 생성자, 설정자 및 필드 주입과 호환된다.

Constructor injection

1
2
3
Engine(@Value("8") int cylinderCount) {
    this.cylinderCount = cylinderCount;
}

Setter injection

1
2
3
4
@Autowired
void setCylinderCount(@Value("8") int cylinderCount) {
    this.cylinderCount = cylinderCount;
}

또는

1
2
3
4
@Value("8")
void setCylinderCount(int cylinderCount) {
    this.cylinderCount = cylinderCount;
}

Field injection

1
2
@Value("8")
int cylinderCount;

물론 정적 값을 주입하는 것은 유용하지 않다. 따라서 @Value의 자리 표시자 문자열을 사용하여 외부 소스 (예:.properties 또는 .yaml 파일)에 정의된 값을 연결할 수 있다.

다음 .properties 파일을 가정한다.

1
engine.fuelType=petrol

다음을 사용하여 engine.fuelType의 값을 주입할 수 있다.

1
2
@Value("${engine.fuelType}")
String fuelType;

SpEL에서도 @Value를 사용할 수 있다.

5) @DependsOn

이 주석을 사용하여 Spring이 주석이 달린 빈보다 먼저 다른 빈을 초기화 하도록 할 수 있다. 일반적으로 이 동작은 Bean 간의 명시적인 종속성을 기반으로 자동으로 수행된다.

JDBC 드라이버 로딩이나 정적 변수 초기화와 같이 종속성이 암시적일 때만 이 주석이 필요하다.

종속성 Bean의 이름을 지정하는 종속 클래스에서 @DependsOn을 사용할 수 있다. 주석의 값 인수에는 종속성 Bean 이름을 포함하는 배열이 필요하다.

1
2
@DependsOn("engine")
class Car implements Vehicle {}

또는 @Bean 주석으로 Bean을 정의하는 경우 팩토리 메소드에 @DependsOn 주석을 달아야 한다.

1
2
3
4
5
@Bean
@DependsOn("fuel")
Engine engine() {
    return new Engine();
}

6) @Lazy

빈을 느리게 초기화하고 싶을 때 @Lazy를 사용한다. 기본적으로 Spring은 애플리케이션 컨텍스트의 시작/부트스트래핑 시 모든 싱글톤 Bean을 열심히 생성한다.

그러나 애플리케이션 시작 시가 아니라 요청할 때 Bean을 생성해야 하는 경우가 있다.

이 주석은 정확히 어디에 배치하느냐에 따라 다르게 동작한다. 우리는 그것을 넣을 수 있다.

  • 메소드 호출을 지연시키기 위한 @Bean 주석이 달린 빈 팩토리 메소드 (따라서 빈 생성)

  • @Configuration 클래스와 포함된 모든 @Bean 메소드가 영향을 받음

  • @Configuration 클래스가 아닌 @Component 클래스, 이 Bean은 느리게 초기화됨

  • (프록시를 통해) 종속성 자체를 느리게 로드하기 위한 @Autowired 생성자, 설정자 또는 필드

이 주석에는 기본값이 true인 value라는 인수가 있다. 기본 동작을 재정의하는 것이 유용하다.

예를 들어 전역 설정이 게으른 경우 Bean을 즉시 로드하도록 표시하거나 @Lazy로 표시된 @Configuration 클래스에서 특정 @Bean 메서드를 즉시 로드하도록 구성한다.

1
2
3
4
5
6
7
8
9
10
@Configuration
@Lazy
class VehicleFactoryConfig {

    @Bean
    @Lazy(false)
    Engine engine() {
        return new Engine();
    }
}

7) @Lookup

@Lookup으로 주석이 달린 메소드는 호출할 때 메소드의 반환 유형 인스턴스를 반환하도록 Spring에 지시한다.

8) @Primary

때로는 동일한 유형의 여러 Bean을 정의해야 하는 경우도 있다. 이러한 경우 Spring은 필요한 빈이 무엇인지 전혀 모르기 때문에 주입이 실패한다.

즉, @Qualifier로 모든 연결 지점을 표시 하고 필요한 Bean의 이름을 지정하는 것이다.

그러나 대부분의 경우 특정 Bean이 필요하고 다른 Bean은 거의 필요하지 않다. @Primary를 사용하여 이 사례를 단순화 할 수 있다. 가장 자주 사용되는 Bean을 @Primary로 표시하면 자격이 없는 주입 지점에서 선택된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Component
@Primary
class Car implements Vehicle {}

@Component
class Bike implements Vehicle {}

@Component
class Driver {
    @Autowired
    Vehicle vehicle;
}

@Component
class Biker {
    @Autowired
    @Qualifier("bike")
    Vehicle vehicle;
}

이전 예에서는 자동차가 기본 차량이다. 따라서 Driver 클래스에서 Spring은 Car Bean을 주입한다. 물론 Biker 빈에서는 필드 차량의 값이 자격을 갖추었기 때문에 Bike 객체가 된다.

9) @Scope

@Component 클래스나 @Bean 정의의 범위를 정의하기 위해 @Scope를 사용한다. 싱글톤, 프로토타입, 요청, 세션, globalSession 또는 일부 사용자 정의 범위 일 수 있다.

1
2
3
@Component
@Scope("prototype")
class Engine {}

2. 컨텍스트 구성 주석

주석을 사용하여 애플리케이션 컨텍스트를 구성할 수 있다.

1) @Profile

Spring이 특정 프로필이 활성화된 경우에만 @Component 클래스나 @Bean 메서드를 사용 하도록 하려면 @Profile로 표시하면 된다. 주석의 값 인수를 사용하여 프로필 이름을 구성할 수 있다.

1
2
3
@Component
@Profile("sportDay")
class Bike implements Vehicle {}

2) @Import

이 주석을 사용하면 구성 요소 검색 없이 특정 @Configuration 클래스를 사용할 수 있다. @Import의 값 인수를 사용하여 해당 클래스를 제공할 수 있다.

1
2
@Import(VehiclePartSupplier.class)
class VehicleFactoryConfig {}

3) @ImportResource

이 주석을 사용하여 XML 구성을 가져올 수 있다. 위치 인수 또는 별칭인 값 인수를 사용하여 XML 파일 위치를 지정할 수 있다.

1
2
3
@Configuration
@ImportResource("classpath:/annotations.xml")
class VehicleFactoryConfig {}

4) @PropertySource

이 주석을 사용하면 애플리케이션 설정에 대한 속성 파일을 정의 할 수 있다.

1
2
3
@Configuration
@PropertySource("classpath:/annotations.properties")
class VehicleFactoryConfig {}

@PropertySource는 Java 8 반복 주석 기능을 활용한다. 즉, 이 주석으로 클래스를 여러 번 표시할 수 있다.

1
2
3
4
@Configuration
@PropertySource("classpath:/annotations.properties")
@PropertySource("classpath:/vehicle-factory.properties")
class VehicleFactoryConfig {}

5) @PropertySources

이 주석을 사용하여 여러 @PropertySource 구성을 지정할 수 있다.

1
2
3
4
5
6
@Configuration
@PropertySources({ 
    @PropertySource("classpath:/annotations.properties"),
    @PropertySource("classpath:/vehicle-factory.properties")
})
class VehicleFactoryConfig {}

Java 8부터는 위에서 설명한 반복 주석 기능을 사용하여 동일한 결과를 얻을 수 있다.

[출처 및 참고]

This post is licensed under CC BY 4.0 by the author.