본문 바로가기

학원/복기

[Spring] Annotation 이용한 의존성 주입 (수정..)

@Component

@Component은 클래스를 스프링 컨테이너가 관리할 수 있는 Spring Bean으로 등록하기 위한 어노테이션이다.
스프링 프레임워크에서 컴포넌트 스캔(Component Scan)을 통해 빈(Bean)으로 등록한다.
여기서 컴포넌트 스캔은 스프링에서 자동으로 빈으로 등록할 클래스를 찾아주는 기능을 말한다.

클래스의 이름을 beanName으로 자동 설정할 수 있다. (클래스의 이름에서 첫문자는 소문자로 변환한다.)
@Compontent 어노테이션의 value 속성을 사용하여 beanName 변경이 가능하다.

@Component 어노테이션이 붙은 클래스는 자동으로 스프링의 컴포넌트 스캔에 의해 빈으로 등록되어, 
이후에 해당 빈을 필요로 하는 다른 클래스에서 @Autowired 어노테이션을 사용하여 자동 주입(Autowiring)을 받을 수 있게 된다.

@Component 어노테이션을 직접 사용하는 경우는 주로 일반적인 컴포넌트의 등록에 사용된다.
특별한 용도의 컴포넌트를 등록해야하는 경우에는 @Component 어노테이션과 유사한 다른 어노테이션들을 사용하기도 한다.

@Repository @Service @Controller ... 와 같은 어노테이션들은 모두 @Component 어노테이션을 기반으로 하며, 추가적인 기능을 제공하기 위해 사용된다.

 

예시)

@Component
public class MyComponent {

    // 컴포넌트의 기능들
    // ...
}

 

이처럼 @Component 어노테이션을 사용하여 일반적인 컴포넌트를 등록할 수 있다.

이 클래스는 스프링 빈으로 등록되고, 다른 컴포넌트에서 MyComponent 빈을 @Autowired 어노테이션을 통해 주입받을 수 있게 된다.

 

@Component 어노테이션을 사용하여 클래스를 빈으로 등록하면, 스프링이 해당 클래스를 자동으로 관리하고, 의존성 주입 등의 기능을 제공하여 객체 간의 연결을 쉽게 구성할 수 있게 된다.

 


@Repository

 

@Repository은 DAO 클래스를 스프링 컨테이너가 관리할 수 있는 Spring Bean으로 등록하기 위한 어노테이션이다.

@Component 어노테이션을 확장한 것으로, 데이터 베이스나 파일과 같은 데이터 저장소에 접근하는 클래스에 주로 사용된다.
일반적으로 JPA, Hibernate, MyBatis와 같은 영속성 기술과 함께 사용될 때 효과적이다.


@Component와의 차이점은
@Component는 일반적인 스프링 빈을 등록할 때 사용되고, @Repository는 데이터 접근 객체 (DAO)와 같은 데이터 액세스 클래스를 빈으로 등록할 때 사용된다는 것이다.

클래스의 이름을 beanName으로 자동 설정하지만 value 속성을 사용하여 beanName을 변경하는 것도 가능하다.

 

 


@Primary


@Primary은 의존성 주입을 위한 우선권을 제공하기 위한 어노테이션이다.

스프링 컨테이너에서 빈을 등록할 때, 동일한 타입의 빈이 여러 개 있을 수 있는데 이때 @Primary 어노테이션을 특정 빈에 적용하면,
해당 빈은 자동 주입(autowiring)과 같은 경우에 우선적으로 선택된다. 

단, 동일한 자료형의 클래스에 @Primary 어노테이션을 여러번 사용하면 의존성 주입이 되지 않기 때문에 주의해야 한다.

 

예시)

@Configuration
public class DataSourceConfig {
    
    @Bean
    public DataSource dataSource1() {
        // DataSource1 생성 코드
    }

    @Bean
    @Primary
    public DataSource dataSource2() {
        // DataSource2 생성 코드
    }
}

 

위의 코드에서 dataSource2() 메소드에 @Primary 어노테이션이 붙어 있다.

 이 경우에는 dataSource2 빈이 @Primary로 지정되어 있기 때문에, DataSource 타입의 빈을 자동 주입할 때 dataSource2 빈이 우선적으로 선택되어 주입된다.

 


@Service 


@Service는 Service 클래스를 스프링 컨테이너가 관리할 수 있는 Spring Bean으로 등록하기 위한 어노테이션이다.

@Service 어노테이션을 사용하여 서비스 계층의 클래스에 등록된 빈은 자동으로 스프링의 컴포넌트 스캔에 의해 빈으로 등록된다.
이후에 해당 빈을 필요로 하는 컴포넌트(주로 컨트롤러)에서 @Autowired 어노테이션을 사용하여 자동 주입(Autowiring)을 받을 수 있게 된다.

 

예시)

@Service
public class MyService {

    // 비즈니스 로직 메소드들
    // ...
}

 

위의 코드에서 MyService 클래스에 @Service 어노테이션이 붙어 있으므로, 이 클래스는 스프링 빈으로 등록되고, 다른 컴포넌트에서 MyService 빈을 @Autowired 어노테이션을 통해 주입받을 수 있게 된다.

 

 

클래스의 이름을 beanName으로 자동 설정하지만 value 속성을 사용하여 beanName 변경이 가능하다.

@Service("studentService")
...

 


@Autowired

@Autowired은 스프링 컨테이너로부터 Spring Bean를 제공받아 필드에 저장하여 의존관계를 자동으로 구현하기 위한 어노테이션이다.  - DI 구현을 위한 어노테이션

  • 필드에 @Autowired 어노테이션을 사용하여 의존성을 주입한다.  - 필드 레벨의 의존성 주입
  • 필드가 여러개 선언된 경우 필드마다 @Autowired 어노테이션을 사용하여 의존성을 주입할 수 있다.
  • bean 엘리먼트의 autowire 속성값을 [byType]으로 설정한 것과 같은 방법으로 의존성을 주입한다. - Setter Injection
  • Setter 메소드를 이용하여 의존관계를 구현하지만 Setter 메소드를 선언하지 않하도 의존성 주입이 가능하다.

 

문제점)

필드의 자료형과 같은 자료형의 Spring Bean이 2개 이상인 경우 의존성 주입에 실패하여 NoUniqueBeanDefinitionException이 발생할 수 있다.


해결법1)

필드의 자료형과 같은 자료형의 Spring Bean이 2개 이상인 경우 필드에 저장될 Spring Bean의 식별자(beanName)을 필드명과 동일하게 변경한다.
=> @Autowird 어노테이션은 필드의 자료형과 같은 자료형의 Spring Bean이 2개 이상인 경우autowire 속성값을 [byName]으로 설정한 것과 동일한 방법으로 의존성 주입


해결법2)

필드의 자료형과 같은 자료형의 Spring Bean이 2개 이상인 경우 필드에 저장될 Spring Bean의 클래스에 @Primary 어노테이션을 사용하여 의존성 주입


해결법3)

@Autowired 어노테이션에 종속된 @Qualifier 어노테이션을 사용하여 의존성 주입

 

@Qualifier : 필드에 저장된 Spring Bean을 직접 지정하여 의존성 주입

  • value 속성에 의존성 주입을 위한 Spring Bean 식별자(beanName)를 속성값으로 설정
  • value 속성외에 다른 속성이 없는 경우 속성값만 설정 가능 

 

/@Autowired 어노테이션 대신 @Resource 어노테이션 또는 @Inject 어노테이션을 사용하여 의존성 주입 가능
// => @Autowired 어노테이션은 Spring 프레임워크의 라이브러리에서 제공하는 어노테이션이지만 
//@Resource 어노테이션 또는 @Inject 어노테이션은 Java 라이브러리에서 제공하는 어노테이션
// => @Resource 어노테이션 또는 @Inject 어노테이션은 다른 프레임워크에서도 사용 가능
//@Resource 어노테이션 : bean 엘리먼트의 autowire 속성값을 [byName]으로 설정한 것과 동일한 방법으로 의존성 주입
//@Inject 어노테이션 : bean 엘리먼트의 autowire 속성값을 [byType]으로 설정한 것과 동일한 방법으로 의존성 주입
// => 동일한 자료형의 Spring Bean이 여러개 있는 경우 @Named 어노테이션을 사용하여 의존성 주입