• 자동 주입과 함께 사용되는 기능
  • 스프링이 직접 클래스를 검색해서 빈으로 등록해주는 기능
  • 설정 코드가 크게 줄어듦

Component-scan은 xml에 일일이 빈등록을 하지않고 각 빈 클래스에 @Component를 통해 자동 빈 등록이 된다.

@Component @Controller @Service @Repository와 같은 어노테이션을 자동 등록 처리해준다.

 

 

 

@Component 애노테이션으로 스캔 대상 지정

 

 

스프링이 검색해서 빈으로 등록할 수 있으려면 클래스에 @Component 애노테이션을 붙여야 한다.
이 애노테이션은 해당 클래스를 스캔 대상으로 표시한다.

 

  • @Component 애노테이션에 값을 주면 그 값을 빈 이름으로 사용한다.
    ex. @Component("listPrinter")

 

 


@ComponentScan 애노테이션으로 스캔 설정

 

@Component 애노테이션을 붙인 클래스를 스캔해서 스프링 빈으로 등록하려면, 설정 클래스에 @ComponentScan 애노테이션을 적용해야한다.

 

 

 

@Configuration
@ComponentScan(basePackages = {"spring"})
public class AppCtx{
    ...
}

 

 

 

이 코드를 보면 AppCtx 클래스에서

 

@ComponentScan 애노테이션을 사용하여 @Component 애노테이션이 붙은 클래스를 검색해서 빈으로 등록해주기 때문에 설정 코드가 확연히 줄어든다.


또 컴포넌트 스캔 애노테이션을 살펴보면 basePackages 속성값은 {"spring"}이다. 이 속성은 스캔 대상 패키지 목록을 지정하는 것이다.
이는 spring 패키지와 그 하위 패키지에 속한 클래스를 스캔 대상으로 설정한다. 스캔 대상에 해당하는 클래스중 @Component 애노테이션이 붙은 클래스의 객체를 생성해 빈으로 등록한다.

 

 


 

 

스캔 대상에서 제외하거나 포함하기

 

excludeFilters 속성을 사용하면 스캔할 때 특정 대상을 자동 등록 대상에서 제외할 수 있다.

// 정규 표현식을 사용해서 제외 대상을 지정한다.
// "spring."으로 시작하고 Dao로 끝나는 정규 표현식을 지정
@ComponentScan(basePackages = {"spring"},
    excludeFilters = @Filter(type = FilterType.REGEX, pattern = "spring\\..*Dao"))





// AspectJ 패턴을 사용해 대상을 지정한다.
// spring 패키지의 Dao로 끝나는 타입을 지정
// AspectJ 패턴이 동작하려면 의존 대상에 aspectjweaver모듈을 추가해야한다.
@ComponentScan(basePackages = {"spring"},
        excludeFilters = @Filter(type = FilterType.ASPECTJ, pattern = "spring.*Dao"))





// 특정 애노테이션을 붙인 타입을 컴포넌트 대상에서 제외한다.
// 패턴은 Stringp[] 타입이므로 배열을 이용해 패턴을 한 개 이상 지정할 수 있다.
@ComponentScan(basePackages = {"spring", "spring2"},
        excludeFilters = @Filter(type = FilterType.Annotation, pattern = {NoProduct.class, ManualBean.class}))





// 특정 타입이나 그 하위 타입을 컴포넌트 스캔 대상에서 제외한다.
@ComponentScan(basePackages = {"spring"},
        excludeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = MemberDao.class))






// 설정할 필터가 2개 이상이면 excludeFilters 속성에 배열을 사용해서 목록을 전달하면 된다.
@ComponentScan(basePackages = {"spring"},
        excludeFilters = {
                @Filter(type = FilterType.ANNOTATION, classes = ManualBean.class),
                @Filter(type = FilterType.REGEX, pattern = "spring2\\..*")
        }

 

 

 

 

 

 

@Component 애노테이션을 붙인 클래스만 스캔 대상에 포함되는 것이 아니다.

  • @Component
  • @Controller
  • @Service
  • @Repository
  • @Aspect
  • @Configuration

@Aspect를 제외하고 나머지 애노테이션은 @Component 애노테이션에 대한 특수 애노테이션이다.




 

컴포넌트 스캔에 따른 충돌 처리


컴포넌트 스캔 기능을 사용해서 Bean을 등록할 경우, 아래와 같은 두 가지 충돌이 발생 가능

  1. Bean 이름의 충돌
  2. 수동 등록에 따른 충돌

2-1. Bean 이름 충돌

  • 서로 다른 패키지에 같은 클래스의 이름이 존재하고, 두 클래스 모두 @Component 어노테이션이 붙게 된다면,
    Exception이 발생하게 됨
  • 이럴 경우, 둘 중 하나에 명시적으로 Bean 이름을 지정해서 이름 충돌을 피해야 함

2-2. 수동 등록에 따른 충돌

  1. 같은 클래스를 같은 이름으로 설정할 때:
    • @Component 어노테이션을 통해 이미 지정한 Bean의 클래스 이름이 존재하지만,
      클래스 설정에 직접 해당 클래스를 동일한 이름으로 정해 등록하는 경우 발생
    • 즉, 스캔할 때 사용하는 Bean 이름과 수동 등록한 이름이 같을 경우, 수동 등록한 Bean이 우선시 됨
  2. 같은 클래스를 다른 이름으로 설정할 때:
    • 만약, 스캔할 때 사용하는 Bean 이름과 동일한 클래스를 다른 이름으로 수동 등록하는 경우에는
      다른 이름의 두 개의 Bean이 만들어지게 됨
    • 이런 경우에는 @Qualifier 어노테이션을 통해 알맞은 Bean을 선택해야 함

 


Reference.

'초보 웹 개발자를 위한 스프링5 프로그래밍 입문' link1

출처 : https://sehun-kim.github.io/sehun/springbean-lifecycle/#2

 

스프링의 삼각형
DI IoC AOP

스프링의 기반이 되는 설계 개념인 스프링의 삼각형

 

 

의존성 주입 DI ( Dependency Injection )

Inversion of Control 이라고도 하는 의존 관계 주입(Dependency Injection)이라고도 하며, 어떤 객체가 사용하는 의존 객체를 직접 만들어 사용하는게 아니라, 주입 받아 사용하는 방법이다. (new 연산자를 이용해서 객체를 생성하는 것이라고 생각하면 된다) 스프링이 다른 프레임워크와 차별화되어 제공하는 의존 관계 주입 기능으로, DI(의존성 주입)를 통해서 모듈 간의 결합도가 낮아지고 유연성이 높아진다.

출처 :https://velog.io/@gillog/Spring-DIDependency-Injection

A 객체에서 B, C객체를 사용(의존)할 때, A 객체에서 직접 생성 하는 것이 아니라 외부(IOC컨테이너)에서 생성된 B, C객체를 조립(주입)시켜 setter 혹은 생성자를 통해 사용하는 방식 

 

예시로 장난감과 배터리를 들 수 있다. 장난감들은 베터리가 있어야 움직일 수 있으며 즉 베터리에 의존하고 있다. 장난감들에게 베터리를 넣어주는 것을 의존성 주입이라고 생각하면 좋다.

베터리의 일체형인 경우에는 생성자에서만 의존성을 주입해주는 상황이라 베터리가 떨어지게 된다면 다른 베터리로 교체하지 못하고 새로운 것으로 바꿔야 하기 때문에 유연하지 못한 방식이다. 

자바와 같은 경우엔 setter, 생성자를 이용해서 외부에서 주입해주는 상황은 외부에서 베터리를 교체해줄 수 있기 때문에 일체형보다 유연한 상황이다. 

 

 

출처 : https://velog.io/@gillog/Spring-DIDependency-Injection

스프링에서는 객체를 Bean이라고 부르며, 프로젝트가 실행될때 사용자가 Bean으로 관리하는 객체들의 생성과 소멸에 관련된 작업을 자동적으로 수행해주는데 객체가 생성되는 곳을 스프링에서는 Bean 컨테이너라고 부른다.

 

 

 

의존성 주입을 사용하는 이유

1. 재사용성을 높여준다.

2. 테스트에 용이하다.

3. 코드를 단순화 시켜준다.

4. 사용하는 이유를 파악하기 수월하고 코드가 읽기 쉬워지는 점이 있다.

5. 종속성이 감소하기 때문에 변경에 민감하지 않다.

6. 결합도(coupling)는 낮추면서 유연성과 확장성은 향상 시킬 수 있다.

7. 객체간의 의존관계를 설정할 수 있다.

 


Reference.

link1 link2

'🔥 > Spring' 카테고리의 다른 글

[spring] 빈 라이프 사이클과 범위  (0) 2021.08.31
[spring] 컴포넌트 스캔이란  (0) 2021.08.31
[Spring] "회초리단" 스프링 스터디 1차  (0) 2021.08.20
[Spring] DI의 세가지 방법  (0) 2021.08.18

+ Recent posts