Spring FactoriesLoader 메커니즘 실례 상세 설명
1.1 SpringFactoriesLoader 소개
SpringFactoriesLoader 공장 로 딩 메커니즘 은 Spring 내부 에서 제공 하 는 약 속 된 로 딩 방식 으로 자바 spi 와 유사 하 며 모듈 의 META-INF/spring.factories 파일 에 Properties 형식(즉 key-value 형식)으로 설정 하면 해당 하 는 실 현 류 를 Spirng 용기 에 주입 할 수 있 습 니 다.
속성 형식:
key:전체 제한 이름(추상 클래스|인터페이스)
value:실현 입 니 다.여러 실현 은**쉼표**를 통 해 구 분 됩 니 다.
1.2 SpringFactoriesLoader 상용 방법
loadFactoryNames
classpath 에 있 는 모든 jar 패키지 의 모든 META-INF/spring.factories 속성 파일 을 읽 고 그 중에서 정 의 된 종류 인 factory Class 의 공장 클래스 를 찾 은 다음 이 공장 클래스 의 이름 목록 으로 돌아 갑 니 다.가방 이름 을 포함 하 는 모든 제한 이름 입 니 다.
loadFactories
classpath 에 있 는 모든 jar 패키지 의 모든 META-INF/spring.factories 속성 파일 을 읽 고 그 중에서 정 의 된 일치 하 는 유형의 factory Class 공장 클래스 를 찾 아 공장 클래스 의 대상/인 스 턴 스 를 만 들 고 이 공장 클래스 의 대상/인 스 턴 스 목록 을 되 돌려 줍 니 다.
1.3 loadFactory 흐름 도
2.SpringFactoriesLoader 소스 코드 분석
2.1 loadFactory Names 분석
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
//
String factoryTypeName = factoryType.getName();
// META-INF/spring.factories
//
return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
}
// , JAR
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
// ,
MultiValueMap<String, String> result = cache.get(classLoader);
if (result != null) {
return result;
}
try {
// classpath JAR META-INF/spring.factories
Enumeration<URL> urls = (classLoader != null ?
classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
result = new LinkedMultiValueMap<>();
while (urls.hasMoreElements()) {
// META-INF/spring.factories Properties , Properties
URL url = urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
for (Map.Entry<?, ?> entry : properties.entrySet()) {
// ( )
String factoryTypeName = ((String) entry.getKey()).trim();
// , result
for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
result.add(factoryTypeName, factoryImplementationName.trim());
}
}
}
//
cache.put(classLoader, result);
return result;
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load factories from location [" +
FACTORIES_RESOURCE_LOCATION + "]", ex);
}
}
default V getOrDefault(Object key, V defaultValue) {
V v;
return (((v = get(key)) != null) || containsKey(key))
? v
: defaultValue;
}
2.2 loadFactory 분석
public static <T> List<T> loadFactories(Class<T> factoryType, @Nullable ClassLoader classLoader) {
Assert.notNull(factoryType, "'factoryType' must not be null");
// ,
ClassLoader classLoaderToUse = classLoader;
if (classLoaderToUse == null) {
classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
}
//
List<String> factoryImplementationNames = loadFactoryNames(factoryType, classLoaderToUse);
// Trace ,
if (logger.isTraceEnabled()) {
logger.trace("Loaded [" + factoryType.getName() + "] names: " + factoryImplementationNames);
}
//
List<T> result = new ArrayList<>(factoryImplementationNames.size());
for (String factoryImplementationName : factoryImplementationNames) {
// ,
result.add(instantiateFactory(factoryImplementationName, factoryType, classLoaderToUse));
}
//
AnnotationAwareOrderComparator.sort(result);
return result;
}
private static <T> T instantiateFactory(String factoryImplementationName, Class<T> factoryType, ClassLoader classLoader) {
try {
Class<?> factoryImplementationClass = ClassUtils.forName(factoryImplementationName, classLoader);
if (!factoryType.isAssignableFrom(factoryImplementationClass)) {
throw new IllegalArgumentException(
"Class [" + factoryImplementationName + "] is not assignable to factory type [" + factoryType.getName() + "]");
}
return (T) ReflectionUtils.accessibleConstructor(factoryImplementationClass).newInstance();
}
catch (Throwable ex) {
throw new IllegalArgumentException(
"Unable to instantiate factory class [" + factoryImplementationName + "] for factory type [" + factoryType.getName() + "]",
ex);
}
}
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
[MeU] Hashtag 기능 개발➡️ 기존 Tag 테이블에 존재하지 않는 해시태그라면 Tag , tagPostMapping 테이블에 모두 추가 ➡️ 기존에 존재하는 해시태그라면, tagPostMapping 테이블에만 추가 이후에 개발할 태그 기반 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.