Spring Boot @ EnableAutoConfiguration 해석
을 추가 해 야 합 니 다. 주석 추가 @ComponentScan({ "xxx"})
.그 때 는 urgly 라 고 생각 했 지만 더 좋 은 방법 이 있 는 지 연구 하지 않 았 다.Spring Boot 에 접촉 할 때 까지 두 개의 가방 을 자동 으로 도입 할 수 있 는 bean 을 발견 합 니 다.하지만 이 실현 원 리 를 보지 못 했다.최근 면접 때 까지 물 어 봤 어 요.그래서 논 리 를 실현 하 는 걸 봤 어 요.
사용 자세
원 리 를 말 하기 전에 사용 자 세 를 먼저 말 해라.
프로젝트 A 에서 bean 을 정의 합 니 다.
package com.wangzhi;
import org.springframework.stereotype.Service;
@Service
public class Dog {
}
이 프로젝트 의
resources/META-INF/
아래 에 spring.factories
라 는 파일 을 만 듭 니 다. 이 파일 의 내용 은 다음 과 같 습 니 다.org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.wangzhi.Dog
그리고 procject B 에서 procject A 의 jar 가방 을 참조 합 니 다.
procject A 코드 는 다음 과 같 습 니 다.
package com.wangzhi.springbootdemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;
@EnableAutoConfiguration
public class SpringBootDemoApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringBootDemoApplication.class, args);
System.out.println(context.getBean(com.wangzhi.Dog.class));
}
}
인쇄 결과:
com.wangzhi.Dog@3148f668
원리 해석
전체적으로 두 부분 으로 나 뉜 다. 하 나 는 모든
spring.factories
중 EnableAutoConfiguration
관련 bean 의 종 류 를 수집 하 는 것 이 고, 다른 하 나 는 얻 은 종 류 를 spring 용기 에 등록 하 는 것 이다.bean 정의 클래스 수집
spring 용기 가 시 작 될 때 호출 됩 니 다
AutoConfigurationImportSelector#getAutoConfigurationEntry
protected AutoConfigurationEntry getAutoConfigurationEntry(
AutoConfigurationMetadata autoConfigurationMetadata,
AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// EnableAutoConfiguration :exclude,excludeName
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// Configurations
List configurations = getCandidateConfigurations(annotationMetadata,
attributes);
//
configurations = removeDuplicates(configurations);
// exclude
Set exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = filter(configurations, autoConfigurationMetadata);
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
getCandidateConfigurations
호출 방법 loadFactoryNames
:public static List loadFactoryNames(Class> factoryClass, @Nullable ClassLoader classLoader) {
// factoryClassName org.springframework.boot.autoconfigure.EnableAutoConfiguration
String factoryClassName = factoryClass.getName();
// spring.factories key org.springframework.boot.autoconfigure.EnableAutoConfiguration
return loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
}
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
private static Map> loadSpringFactories(@Nullable ClassLoader classLoader) {
MultiValueMap result = cache.get(classLoader);
if (result != null) {
return result;
}
try {
// "META-INF/spring.factories"
Enumeration urls = (classLoader != null ?
classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
result = new LinkedMultiValueMap<>();
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
UrlResource resource = new UrlResource(url);
// ,properties HashMap, key value
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
for (Map.Entry, ?> entry : properties.entrySet()) {
String factoryClassName = ((String) entry.getKey()).trim();
// ',' value
for (String factoryName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
result.add(factoryClassName, factoryName.trim());
}
}
}
cache.put(classLoader, result);
return result;
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load factories from location [" +
FACTORIES_RESOURCE_LOCATION + "]", ex);
}
}
용기 에 등록
위의 프로 세 스에 서
spring.factories
에서 지정 한 bean 의 클래스 경 로 를 모두 얻 었 습 니 다. processGroupImports
방법 에 서 는 @ import 주해 와 같은 논리 로 용기 에 가 져 옵 니 다.public void processGroupImports() {
for (DeferredImportSelectorGrouping grouping : this.groupings.values()) {
// getImports
grouping.getImports().forEach(entry -> {
ConfigurationClass configurationClass = this.configurationClasses.get(
entry.getMetadata());
try {
// @Import
processImports(configurationClass, asSourceClass(configurationClass),
asSourceClasses(entry.getImportClassName()), false);
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to process import candidates for configuration class [" +
configurationClass.getMetadata().getClassName() + "]", ex);
}
});
}
}
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection importCandidates, boolean checkForCircularImports) {
...
//
for (SourceClass candidate : importCandidates) {
...
// candidate ImportSelector ImportBeanDefinitionRegistrar ,
// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
// process it as an @Configuration class
this.importStack.registerImport(
currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
// @Configuration
processConfigurationClass(candidate.asConfigClass(configClass));
...
}
...
}
첫 번 째 단계 에서 수집 한 bean 류 의 정 의 는 최종 적 으로
Configuration
와 같은 처리 방식 으로 용기 에 등록 되 는 것 을 볼 수 있다.End
@EnableAutoConfiguration
주 해 는 양쪽 가방 bean 을 도입 하 는 원 가 를 간소화 했다.다른 응용 프로그램 에 사용 할 수 있 는 2 자 가방 을 제공 합 니 다. 2 자 가방 에서 대외 적 으로 노출 된 bean 을 spring.factories
에 정의 하면 됩 니 다.필요 하지 않 은 bean 에 대해 서 는 사용 자 용 @EnableAutoConfiguration
의 exclude
속성 에서 제외 할 수 있다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
[MeU] Hashtag 기능 개발➡️ 기존 Tag 테이블에 존재하지 않는 해시태그라면 Tag , tagPostMapping 테이블에 모두 추가 ➡️ 기존에 존재하는 해시태그라면, tagPostMapping 테이블에만 추가 이후에 개발할 태그 기반 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.