@ComponentScan
어노테이션을 사용하면, @Component
어노테이션이 붙은 클래스를 찾아서 Bean으로 등록한다.@Autowired
어노테이션을 사용하면, 해당 타입의 Bean을 찾아서 의존관계를 자동으로 주입한다.basePackages
: String[]
basePackageClasses
: Class<?>[]
includeFilters
: Filter[]
excludeFilters
: Filter[]
useDefaultFilters
: boolean
true
@Component
, @Repository
, @Service
, @Controller
, @Configuration
어노테이션을 스캔 대상으로 설정한다.lazyInit
: boolean
false
@Component
어노테이션을 가진 Bean을 생성할 때, Lazy Initialization을 사용할지 여부nameGenerator
: BeanNameGenerator
DefaultBeanNameGenerator
AnnotationBeanNameGenerator
FullyQualifiedAnnotationBeanNameGenerator
public interface BeanNameGenerator {
String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry);
}
scopeResolver
: ScopeMetadataResolver
AnnotationScopeMetadataResolver
Jsr330ScopeMetadataResolver
public interface ScopeMetadataResolver {
ScopeMetadata resolveScopeMetadata(BeanDefinition definition);
}
scopedProxy
: ScopedProxyMode
ScopedProxyMode.DEFAULT
ScopedProxyMode.NO
ScopedProxyMode.INTERFACES
: 인터페이스를 사용하여 JDK dynamic Proxy를 생성한다.ScopedProxyMode.TARGET_CLASS
: CGLIB 라이브러리를 사용하여 Proxy를 생성한다.lazyInit
: boolean
false
@Component
어노테이션을 가진 Bean을 생성할 때, Lazy Initialization을 사용할지 여부resourcePattern
: String
**/*.class
ClassPathScanningCandidateComponentProvider.DEFAULT_RESOURCE_PATTERN
@Component
@Controller
@Repository
@Service
@Configuration
@Bean
어노테이션을 가진 메서드를 호출하여 Singleton Bean으로 등록한다.@ComponentScan(includeFilters = {...})
@ComponentScan(excludeFilters = {...})
@Retention(RetentionPolicy.RUNTIME)
@Target({})
@interface Filter {
FilterType type() default FilterType.ANNOTATION;
@AliasFor("classes")
Class<?>[] value() default {};
@AliasFor("value")
Class<?>[] classes() default {};
String[] pattern() default {};
}
ANNOTATION
ASSIGNABLE_TYPE
ASPECTJ
pattern
을 사용하여 클래스를 찾는다.REGEX
pattern
을 사용하여 클래스를 찾는다.CUSTOM
TypeFilter
인터페이스를 구현한 클래스를 사용하여 클래스를 찾는다.public enum FilterType {
ANNOTATION,
ASSIGNABLE_TYPE,
ASPECTJ,
REGEX,
CUSTOM
}
public interface TypeFilter {
boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
throws IOException;
}
ConflictingBeanDefinitionException
예외 발생Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true
spring.main.allow-bean-definition-overriding=true
설정을 통해 오류를 해결할 수 있다.의존관계 주입에는 크게 4가지 방법이 있다.
@Autowired
어노테이션을 생략할 수 있다.@Component
@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService {
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
dependencies {
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
}
@Autowired(required = false)
로 설정할 경우@Component
public class OrderServiceImpl implements OrderService {
private MemberRepository memberRepository;
private DiscountPolicy discountPolicy;
@Autowired
public void setMemberRepository(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
@Autowired
public void setDiscountPolicy(DiscountPolicy discountPolicy) {
this.discountPolicy = discountPolicy;
}
}
@SpringBootTest
처럼 Spring Container를 기반으로 테스트하는 경우, 사용할 수 있다.@Component
public class OrderServiceImpl implements OrderService {
@Autowired
private MemberRepository memberRepository;
@Autowired
private DiscountPolicy discountPolicy;
}
@Component
public class OrderServiceImpl implements OrderService {
private MemberRepository memberRepository;
private DiscountPolicy discountPolicy;
@Autowired
public void init(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
}
@Autowired(required = false)
@Nullable
: org.springframework.lang.Nullable
null
이 주입된다.Optional<T>
Optional.empty
가 주입된다.NoUniqueBeanDefinitionException
예외 발생@Autowired
필드 명 매칭@Qualifier
사용@Primary
사용@Autowired
private DiscountPolicy rateDiscountPolicy;
@Qualifier
는 추가적인 구분자를 붙여준다.@Qualifier
어노테이션을 사용하여 추가적인 구분자를 붙여준다.@Autowired
어노테이션을 사용할 때, @Qualifier
어노테이션을 사용하여 구분자를 지정한다.@Component
@Qualifier("mainDiscountPolicy")
public class RateDiscountPolicy implements DiscountPolicy {
// ...
}
@Autowired
public OrderServiceImpl(MemberRepository memberRepository,
@Qualifier("mainDiscountPolicy") DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
@Primary
어노테이션을 사용하여 우선권을 가지는 Bean을 설정한다.@Component
@Primary
public class RateDiscountPolicy implements DiscountPolicy {
// ...
}
@Component
public class FixDiscountPolicy implements DiscountPolicy {
// ...
}
@Qualifier
가@Primary
보다 우선순위가 높다.
@Qualifier
끼리 매칭 @Primary
매칭List<T>
: 타입의 모든 Bean을 주입받을 수 있다.Map<String, T>
: 타입의 모든 Bean을 이름을 키로 조회할 수 있다.@Component
@RequiredArgsConstructor
public class DiscountService {
private final Map<String, DiscountPolicy> policyMap;
private final List<DiscountPolicy> policies;
public int discount(Member member, int price, String discountCode) {
DiscountPolicy discountPolicy = policyMap.get(discountCode);
return discountPolicy.discount(member, price);
}
}
@Component
, @Controller
, @Service
, @Repository
@Configuration
, @Bean
Reference: 스프링-핵심-원리-기본편 (인프런)