인프런 스프링 핵심 원리 요약 –

1. 자동 의존성 주입

– 자동 컨테이너 등록

앞의 예제에서는 Spring Bean을 등록할 때 구성 정보에 직접 등록해야 하는 Spring Bean을 Java 코드 또는 XML에서 @Bean을 통해 수동으로 등록했지만 Spring에서는 Spring Bean을 자동으로 등록하는 @ComponentScan이라는 기능을 제공합니다.

새로운 자동 구성을 수행하는 스케줄러

package hello.core;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import static org.springframework.context.annotation.ComponentScan.*;

@Configuration
@ComponentScan
public class AutoAppConfig {
 
}

@ComponentScan 주석을 첨부하면 @Bean 주석 및 내용이 없습니다.

빈으로 등록할 클래스에 @Component 어노테이션을 직접 붙이면 자동으로 빈으로 등록된다.


@Component 어노테이션을 추가하여 Bean이 MemberRepository에 대한 종속성을 주입하도록 MemoryMemberRepository만 등록하십시오.

마찬가지로 DiscountPolicy를 사용하면 RateDiscountPolicy에만 @Component 주석이 추가됩니다.

예)

@Component
public class MemoryMemberRepository implements MemberRepository {
	...
}
@Component
public class RateDiscountPolicy implements DiscountPolicy {
	...
}

기본 구성 요소 스캔 대상

– @Component : 컴포넌트 스캔 시 사용

– @Controller : Spring MVC 컨트롤러에서 사용

– @Service: Spring 비즈니스 로직에서 사용

– @Repository : Spring 데이터 접근 계층에서 사용

– @Configuration: 스프링 설정 정보에 사용

Spring 컨테이너를 인스턴스화할 때 적절한 구성 파일을 인수로 전달합니다.

– 자동 의존성 주입 등록

@Autowire 주석을 통한 자동 의존성 주입.

예)

@Component
public class MemberServiceImpl implements MemberService {
	private final MemberRepository memberRepository;
	
    @Autowired
	public MemberServiceImpl(MemberRepository memberRepository) {
		this.memberRepository = memberRepository;
	}
}
@Component
public class OrderServiceImpl implements OrderService {
	private final MemberRepository memberRepository;
	private final DiscountPolicy discountPolicy;
	
    // 여러 의존관계 한번에 주입 가능
    @Autowired
	public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
		this.memberRepository = memberRepository;
		this.discountPolicy = discountPolicy;
	}
}

@Autowire의 기본 검색 전략은 같은 유형이 비어 있음찾기 및 삽입 getBean(MemberRepository.class) 및 getBean(DiscountPolicy.class)과 동일합니다.

2. Bean 검색 위치 및 기본 검사 대상

모든 Java 클래스의 구성 요소를 검색하는 데 시간이 오래 걸립니다. 따라서 가장 필요한 위치부터 검색 시작 위치를 지정할 수 있습니다.

@ComponentScan( basePackages = "hello.core" )

basePackages : 검색할 패키지의 시작 위치를 지정합니다. 이 패키지를 포함하는 모든 하위 패키지를 검색합니다. basePackages = {“hello.core”, “hello.service”} 와 같은 여러 시작 위치를 지정할 수도 있습니다.

basePackageClasses : 지정된 클래스의 패키지를 검색 시작 위치로 설정합니다.

지정하지 않으면 @ComponentScan이 첨부된 구성 정보 클래스 패키지가 시작 위치가 됩니다.

※ 추천방법

구성 정보 클래스의 위치는 패키지 위치를 지정하지 않고 프로젝트의 맨 위에 배치됩니다. 최신 Spring Boot도 기본적으로 이 방법을 제공합니다.

3. 컴포넌트 스캔 대상 필터

includeFilters: 구성 요소에 대한 추가 검사 대상을 식별합니다.

ExcludeFilters: 구성 요소 검사에서 제외할 개체를 지정합니다.

– 주석 생성

구성 요소 검사 대상에 추가할 주석

package hello.core.scan.filter;
import java.lang.annotation.*;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyIncludeComponent { }

구성 요소 검사에서 제외할 주석

package hello.core.scan.filter;
import java.lang.annotation.*;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyExcludeComponent { }

– 주석 적용

구성 요소 검사 대상에 추가할 클래스

package hello.core.scan.filter;

@MyIncludeComponent
public class BeanA { }

구성 요소 검사에서 제외할 클래스

package hello.core.scan.filter;
@MyExcludeComponent
public class BeanB { }

– 시험

package hello.core.scan.filter;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.context.annotation.ComponentScan.Filter;

public class ComponentFilterAppConfigTest {
	@Test
	void filterScan() {
		ApplicationContext ac = new AnnotationConfigApplicationContext(ComponentFilterAppConfig.class);
		BeanA beanA = ac.getBean("beanA", BeanA.class);
		assertThat(beanA).isNotNull();
		Assertions.assertThrows(
			NoSuchBeanDefinitionException.class,
			() -> ac.getBean("beanB", BeanB.class));
	}
    
	@Configuration
	@ComponentScan(
		includeFilters = @Filter(type = FilterType.ANNOTATION, classes = MyIncludeComponent.class),
		excludeFilters = @Filter(type = FilterType.ANNOTATION, classes = MyExcludeComponent.class)
	)
	static class ComponentFilterAppConfig { }
}

FilterType에 대한 5가지 옵션

주석: 주석의 기본값, 감지 및 작동.

ASSIGNABLE_TYPE: 주어진 클래스의 유형과 하위 클래스의 유형을 인식하여 작동합니다.

ASPECTJ: AspectJ 패턴 사용

REGEX: 정규 표현식

CUSTOM: TypeFilter라는 인터페이스를 구현하여 처리

4. 중복 등록 및 충돌

– 자동 빈 등록 vs. 자동 등록

컴포넌트 스캔을 통한 자동 스프링 이름이 등록시 동일하면 Spring은 ConflictingBeanDefinitionException 예외를 발생시킵니다.

– 수동 등록 대 자동 등록

수동 레지스트리가 우선하며 덮어썼음을 나타내는 로그를 발행합니다.

빈 “XXXX”에 대한 빈 정의를 다른 정의로 ​​덮어씁니다: 교체

가능하면 자동 Bean을 사용하는 것이 좋습니다.