最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring中的ImportSelector接口原理解析

 更新時間:2024年01月29日 09:03:34   作者:立小言先森  
這篇文章主要介紹了Spring中的ImportSelector接口原理解析,ImportSelector接口是spring中導(dǎo)入外部配置的核心接口,根據(jù)給定的條件(通常是一個或多個注釋屬性)判定要導(dǎo)入那個配置類,需要的朋友可以參考下

ImportSelector接口原理

ImportSelector接口是spring中導(dǎo)入外部配置的核心接口,根據(jù)給定的條件(通常是一個或多個注釋屬性)判定要導(dǎo)入那個配置類,在spring自動化配置和@EnableXXX中都有它的存在;

1.ImportSelector接口源碼解析

/**
 * Interface to be implemented by types that determine which @{@link Configuration}
 * class(es) should be imported based on a given selection criteria, usually one or
 * more annotation attributes.
 *
 * <p>An {@link ImportSelector} may implement any of the following
 * {@link org.springframework.beans.factory.Aware Aware} interfaces,
 * and their respective methods will be called prior to {@link #selectImports}:
 * <ul>
 * <li>{@link org.springframework.context.EnvironmentAware EnvironmentAware}</li>
 * <li>{@link org.springframework.beans.factory.BeanFactoryAware BeanFactoryAware}</li>
 * <li>{@link org.springframework.beans.factory.BeanClassLoaderAware BeanClassLoaderAware}</li>
 * <li>{@link org.springframework.context.ResourceLoaderAware ResourceLoaderAware}</li>
 * </ul>
 *
 * <p>Alternatively, the class may provide a single constructor with one or more of
 * the following supported parameter types:
 * <ul>
 * <li>{@link org.springframework.core.env.Environment Environment}</li>
 * <li>{@link org.springframework.beans.factory.BeanFactory BeanFactory}</li>
 * <li>{@link java.lang.ClassLoader ClassLoader}</li>
 * <li>{@link org.springframework.core.io.ResourceLoader ResourceLoader}</li>
 * </ul>
 *
 * <p>{@code ImportSelector} implementations are usually processed in the same way
 * as regular {@code @Import} annotations, however, it is also possible to defer
 * selection of imports until all {@code @Configuration} classes have been processed
 * (see {@link DeferredImportSelector} for details).
 *
 * @author Chris Beams
 * @author Juergen Hoeller
 * @since 3.1
 * @see DeferredImportSelector
 * @see Import
 * @see ImportBeanDefinitionRegistrar
 * @see Configuration
 */
public interface ImportSelector {
	/**
	 * Select and return the names of which class(es) should be imported based on
	 * the {@link AnnotationMetadata} of the importing @{@link Configuration} class.
	 * @return the class names, or an empty array if none
	 */
	String[] selectImports(AnnotationMetadata importingClassMetadata);
	/**
	 * Return a predicate for excluding classes from the import candidates, to be
	 * transitively applied to all classes found through this selector's imports.
	 * <p>If this predicate returns {@code true} for a given fully-qualified
	 * class name, said class will not be considered as an imported configuration
	 * class, bypassing class file loading as well as metadata introspection.
	 * @return the filter predicate for fully-qualified candidate class names
	 * of transitively imported configuration classes, or {@code null} if none
	 * @since 5.2.4
	 */
	@Nullable
	default Predicate<String> getExclusionFilter() {
		return null;
	}
}

接口文檔已經(jīng)說的很明白,其主要作用是收集需要導(dǎo)入的配置類,如果該接口的實現(xiàn)類同時實現(xiàn)了org.springframework.beans.factory.Aware相關(guān)接口,如:EnvironmentAware、BeanFactoryAware、BeanClassLoaderAware、ResourceLoaderAware等,那么在調(diào)用其selectImports方法之前先調(diào)用上述接口中的回調(diào)方法;如果需要在所有的@Configuration處理完再導(dǎo)入,可以實現(xiàn)DeferredImportSelector接口;

2.DeferredImportSelector接口源碼解析

DeferredImportSelector接口是ImportSelector接口的子接口,該接口會在所有的@Configuration配置類(不包括自動化配置類,即spring.factories文件中的配置類)處理完成后運行;當(dāng)選擇器和@Conditional條件注解一起使用時是特別有用的,此接口還可以和接口Ordered或者@Ordered一起使用,定義多個選擇器的優(yōu)先級;

/**
 * A variation of {@link ImportSelector} that runs after all {@code @Configuration} beans
 * have been processed. This type of selector can be particularly useful when the selected
 * imports are {@code @Conditional}.
 *
 * <p>Implementations can also extend the {@link org.springframework.core.Ordered}
 * interface or use the {@link org.springframework.core.annotation.Order} annotation to
 * indicate a precedence against other {@link DeferredImportSelector DeferredImportSelectors}.
 *
 * <p>Implementations may also provide an {@link #getImportGroup() import group} which
 * can provide additional sorting and filtering logic across different selectors.
 *
 * @author Phillip Webb
 * @author Stephane Nicoll
 * @since 4.0
 */
public interface DeferredImportSelector extends ImportSelector {
	/**
	 * 返回指定的導(dǎo)入結(jié)果集
	 */
	@Nullable
	default Class<? extends Group> getImportGroup() {
		return null;
	}
	/**
	 * 用于從不同DeferredImportSelector中獲取需要導(dǎo)入類的結(jié)果集
	 */
	interface Group {
		/**
		 * 根據(jù)AnnotationMetadata注解元數(shù)據(jù)獲取@Configuration配置的@Import注解導(dǎo)入的DeferredImportSelector選擇器對應(yīng)的bean
		 */
		void process(AnnotationMetadata metadata, DeferredImportSelector selector);
		/**
		 * 返回類應(yīng)該導(dǎo)入的Entry
		 */
		Iterable<Entry> selectImports();
		/**
		 * 存放要導(dǎo)入類的全限定名及AnnotationMetadata注解元數(shù)據(jù)
		 */
		class Entry {
			private final AnnotationMetadata metadata;
			private final String importClassName;
			public Entry(AnnotationMetadata metadata, String importClassName) {
				this.metadata = metadata;
				this.importClassName = importClassName;
			}
			/**
			 * 返回要引入的Configuration類的AnnotationMetadata注解元數(shù)據(jù)
			 */
			public AnnotationMetadata getMetadata() {
				return this.metadata;
			}
			/**
			 * 返回要導(dǎo)入類的全限定名
			 */
			public String getImportClassName() {
				return this.importClassName;
			}
			@Override
			public boolean equals(@Nullable Object other) {
				if (this == other) {
					return true;
				}
				if (other == null || getClass() != other.getClass()) {
					return false;
				}
				Entry entry = (Entry) other;
				return (this.metadata.equals(entry.metadata) && this.importClassName.equals(entry.importClassName));
			}
			@Override
			public int hashCode() {
				return (this.metadata.hashCode() * 31 + this.importClassName.hashCode());
			}
			@Override
			public String toString() {
				return this.importClassName;
			}
		}
	}
}

3.示例

AutoConfigurationImportSelector是DeferredImportSelector接口的實現(xiàn)類,用于處理EnableAutoConfiguration自動化配置,

我們知道SpringFactoriesLoader類是自動化配置的核心類,用來將spring.factories配置文件中定義的類加載到內(nèi)存之中,供后面的程序?qū)⑵渥缘絀OC容器之中;AutoConfigurationImportSelector類是DeferredImportSelector接口的一個子類,它的作用就是將SpringFactoriesLoader類加載到內(nèi)中的配置類獲取到,交給后置處理器加載到內(nèi)存中(不是本文重點);

AutoConfigurationGroup是一個靜態(tài)內(nèi)部類,實現(xiàn)了DeferredImportSelector.Group接口,所以其作用是根據(jù)注解的AnnotationMetadata元數(shù)據(jù)獲取導(dǎo)入的DeferredImportSelector接口實現(xiàn)類對應(yīng)的自動化配置類;

  • AutoConfigurationImportSelector.AutoConfigurationGroup類的核心方法process用于獲取自動化配置類:
//存放配置類全限定名和注解元數(shù)據(jù)類
		private final Map<String, AnnotationMetadata> entries = new LinkedHashMap<>();
		//存放配置類的實體對象(包含需要導(dǎo)入的配置類、排除的配置類)
		private final List<AutoConfigurationEntry> autoConfigurationEntries = new ArrayList<>();		
		@Override
		public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
			//獲取spring.factories配置文件中的配置類(包括需要導(dǎo)入的、不需要導(dǎo)入的)
			AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
					.getAutoConfigurationEntry(annotationMetadata);
			this.autoConfigurationEntries.add(autoConfigurationEntry);
			for (String importClassName : autoConfigurationEntry.getConfigurations()) {
				this.entries.putIfAbsent(importClassName, annotationMetadata);
			}
		}
  • AutoConfigurationEntry類用于存放排除掉的配置類,以及需要導(dǎo)入的配置類:
protected static class AutoConfigurationEntry {
	//需要導(dǎo)入的配置類
	private final List<String> configurations;
	//排除不用導(dǎo)入的配置類
	private final Set<String> exclusions;
}  
  • AutoConfigurationImportSelector#getAutoConfigurationEntry方法獲取基于配置類注解的AnnotationMetaData元數(shù)據(jù)導(dǎo)入Configuration配置類
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
	if (!isEnabled(annotationMetadata)) {
		return EMPTY_ENTRY;
	}
//獲取注解的屬性配置(exclude和excludeName)
	AnnotationAttributes attributes = getAttributes(annotationMetadata);
//獲取自動化配置文件spirng.factories中的配置類
	List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
//刪除List中重復(fù)的配置類(去重方法值得參考)
	configurations = removeDuplicates(configurations);
//獲取排除導(dǎo)入的配置類(包括spring.autoconfigure.exclude屬性配置及注解屬性exclude和excludeName)
	Set<String> exclusions = getExclusions(annotationMetadata, attributes);
//檢驗排除類
	checkExcludedClasses(configurations, exclusions);
//刪除掉排除的類
	configurations.removeAll(exclusions);
//獲取過濾器,并對配置類進(jìn)行過濾
	configurations = getConfigurationClassFilter().filter(configurations);
//觸發(fā)自動化配置導(dǎo)入事件
	fireAutoConfigurationImportEvents(configurations, exclusions);
	return new AutoConfigurationEntry(configurations, exclusions);
}
  • AutoConfigurationImportSelector#getCandidateConfigurations方法用于獲取spring.factories配置文件中的配置類(其實際獲取是直接從SpringFactoriesLoader類中的cache獲取的,已經(jīng)在初始化器階段加載到緩存中了):
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    //獲取自動化配置對應(yīng)spring.factories文件中的配置類,
		List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
				getBeanClassLoader());
		return configurations;
	}

返回加載配置類:

protected Class<?> getSpringFactoriesLoaderFactoryClass() {
		return EnableAutoConfiguration.class;
	}
  • AutoConfigurationImportSelector#removeDuplicates方法刪除重復(fù)的配置類
protected final <T> List<T> removeDuplicates(List<T> list) {
		return new ArrayList<>(new LinkedHashSet<>(list));
	}

很好的去重思路,以后可以參考使用;

  • AutoConfigurationImportSelector#getExclusions獲取排除導(dǎo)入的配置類
protected Set<String> getExclusions(AnnotationMetadata metadata, AnnotationAttributes attributes) {
	Set<String> excluded = new LinkedHashSet<>();
	//獲取exclude屬性指定的配置類
	excluded.addAll(asList(attributes, "exclude"));
	//獲取excludeName屬性指定的配置類
	excluded.addAll(Arrays.asList(attributes.getStringArray("excludeName")));
	//獲取spring.autoconfigure.exclude屬性指定的配置類
	excluded.addAll(getExcludeAutoConfigurationsProperty());
	return excluded;
}
  • AutoConfigurationImportSelector#getExcludeAutoConfigurationsProperty獲取spring.autoconfigure.exclude屬性配置類
private static final String PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE = "spring.autoconfigure.exclude";
	protected List<String> getExcludeAutoConfigurationsProperty() {
		Environment environment = getEnvironment();
		if (environment == null) {
			return Collections.emptyList();
		}
		if (environment instanceof ConfigurableEnvironment) {
			Binder binder = Binder.get(environment);
      //獲取配置文件中排除導(dǎo)入配置類
			return binder.bind(PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE, String[].class).map(Arrays::asList)
					.orElse(Collections.emptyList());
		}
		String[] excludes = environment.getProperty(PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE, String[].class);
		return (excludes != null) ? Arrays.asList(excludes) : Collections.emptyList();
	}
  • AutoConfigurationImportSelector#getConfigurationClassFilter
private ConfigurationClassFilter getConfigurationClassFilter() {
		if (this.configurationClassFilter == null) {
			List<AutoConfigurationImportFilter> filters = getAutoConfigurationImportFilters();
			for (AutoConfigurationImportFilter filter : filters) {
				invokeAwareMethods(filter);
			}
			this.configurationClassFilter = new ConfigurationClassFilter(this.beanClassLoader, filters);
		}
		return this.configurationClassFilter;
	}
  • AutoConfigurationImportSelector#fireAutoConfigurationImportEvents
private void fireAutoConfigurationImportEvents(List<String> configurations, Set<String> exclusions) {
	List<AutoConfigurationImportListener> listeners = getAutoConfigurationImportListeners();
	if (!listeners.isEmpty()) {
		AutoConfigurationImportEvent event = new AutoConfigurationImportEvent(this, configurations, exclusions);
		for (AutoConfigurationImportListener listener : listeners) {
			invokeAwareMethods(listener);
			listener.onAutoConfigurationImportEvent(event);
		}
	}
}
  • AutoConfigurationImportSelector.AutoConfigurationGroup#selectImports獲取上述process方法處理后的配置類
@Override
public Iterable<Entry> selectImports() {
	if (this.autoConfigurationEntries.isEmpty()) {
		return Collections.emptyList();
	}
//獲取所有需要排除的配置類
	Set<String> allExclusions = this.autoConfigurationEntries.stream()
			.map(AutoConfigurationEntry::getExclusions).flatMap(Collection::stream).collect(Collectors.toSet());
//獲取所有經(jīng)過自動化配置過濾器的配置類
	Set<String> processedConfigurations = this.autoConfigurationEntries.stream()
			.map(AutoConfigurationEntry::getConfigurations).flatMap(Collection::stream)
			.collect(Collectors.toCollection(LinkedHashSet::new));
//排除過濾后配置類中需要排除的類
	processedConfigurations.removeAll(allExclusions);
	return sortAutoConfigurations(processedConfigurations, getAutoConfigurationMetadata()).stream()
			.map((importClassName) -> new Entry(this.entries.get(importClassName), importClassName))
			.collect(Collectors.toList());
}

到此這篇關(guān)于Spring中的ImportSelector接口原理解析的文章就介紹到這了,更多相關(guān)ImportSelector接口原理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • IDEA創(chuàng)建方法時如何快速添加注釋

    IDEA創(chuàng)建方法時如何快速添加注釋

    這篇文章主要介紹了IDEA創(chuàng)建方法時如何快速添加注釋問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • Golang Protocol Buffer案例詳解

    Golang Protocol Buffer案例詳解

    這篇文章主要介紹了Golang Protocol Buffer案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • Java實現(xiàn)將html字符串插入到PPT幻燈片

    Java實現(xiàn)將html字符串插入到PPT幻燈片

    Java后端代碼操作PPT幻燈片時,可直接在幻燈片中繪制形狀,并在形狀中添加文本字符串內(nèi)容。本篇文章主要介紹通過java實現(xiàn)將html字符串添加到PPT幻燈片的的方法,可添加文字、圖片、視頻、音頻等。以下是具體方法和步驟。
    2021-11-11
  • 關(guān)于Java中使用jdbc連接數(shù)據(jù)庫中文出現(xiàn)亂碼的問題

    關(guān)于Java中使用jdbc連接數(shù)據(jù)庫中文出現(xiàn)亂碼的問題

    這篇文章主要介紹了關(guān)于Java中使用jdbc連接數(shù)據(jù)庫中文出現(xiàn)亂碼的問題,默認(rèn)的編碼和數(shù)據(jù)庫表中的數(shù)據(jù)使用的編碼是不一致的,如果是中文,那么在數(shù)據(jù)庫中執(zhí)行時已經(jīng)是亂碼了,需要的朋友可以參考下
    2023-04-04
  • 基于SpringBoot的Dubbo泛化調(diào)用的實現(xiàn)代碼

    基于SpringBoot的Dubbo泛化調(diào)用的實現(xiàn)代碼

    這篇文章主要介紹了基于SpringBoot的Dubbo泛化調(diào)用的實現(xiàn),從泛化調(diào)用實現(xiàn)的過程來看,我們可以對自己提供所有服務(wù)進(jìn)行測試,不需要引入調(diào)用的接口,減少代碼的侵入,需要的朋友可以參考下
    2022-04-04
  • Java的Spring框架中bean的繼承與內(nèi)部bean的注入

    Java的Spring框架中bean的繼承與內(nèi)部bean的注入

    這篇文章主要介紹了Java的Spring框架中bean的繼承與內(nèi)部bean的注入,Spring框架是Java的SSH三大web開發(fā)框架之一,需要的朋友可以參考下
    2015-12-12
  • Java使用CompletableFuture進(jìn)行非阻塞IO詳解

    Java使用CompletableFuture進(jìn)行非阻塞IO詳解

    這篇文章主要介紹了Java使用CompletableFuture進(jìn)行非阻塞IO詳解,CompletableFuture是Java中的一個類,用于支持異步編程和處理異步任務(wù)的結(jié)果,它提供了一種方便的方式來處理異步操作,并允許我們以非阻塞的方式執(zhí)行任務(wù),需要的朋友可以參考下
    2023-09-09
  • ApplicationListenerDetector監(jiān)聽器判斷demo

    ApplicationListenerDetector監(jiān)聽器判斷demo

    這篇文章主要為大家介紹了ApplicationListenerDetector監(jiān)聽器判斷demo,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • Java8 Comparator: 列表排序的深入講解

    Java8 Comparator: 列表排序的深入講解

    這篇文章主要給大家介紹了關(guān)于Java 8 Comparator: 列表排序的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Java8具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • springboot中使用Feign整合nacos,gateway進(jìn)行微服務(wù)之間的調(diào)用方法

    springboot中使用Feign整合nacos,gateway進(jìn)行微服務(wù)之間的調(diào)用方法

    這篇文章主要介紹了springboot中使用Feign整合nacos,gateway進(jìn)行微服務(wù)之間的調(diào)用方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-03-03

最新評論

出国| 平顶山市| 镇康县| 浪卡子县| 泰顺县| 梨树县| 玉树县| 江北区| 若羌县| 凤翔县| 罗田县| 綦江县| 获嘉县| 清苑县| 温宿县| 潢川县| 应用必备| 论坛| 区。| 墨竹工卡县| 郑州市| 宁海县| 浦江县| 博乐市| 龙门县| 施甸县| 峨山| 林州市| 宣威市| 钦州市| 长兴县| 防城港市| 黔西县| 盈江县| 湖南省| 沛县| 盐边县| 滨海县| 哈巴河县| 邳州市| 新化县|