欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring中的ImportSelector接口原理解析

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

ImportSelector接口原理

ImportSelector接口是spring中導入外部配置的核心接口,根據(jù)給定的條件(通常是一個或多個注釋屬性)判定要導入那個配置類,在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;
	}
}

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

2.DeferredImportSelector接口源碼解析

DeferredImportSelector接口是ImportSelector接口的子接口,該接口會在所有的@Configuration配置類(不包括自動化配置類,即spring.factories文件中的配置類)處理完成后運行;當選擇器和@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 {
	/**
	 * 返回指定的導入結果集
	 */
	@Nullable
	default Class<? extends Group> getImportGroup() {
		return null;
	}
	/**
	 * 用于從不同DeferredImportSelector中獲取需要導入類的結果集
	 */
	interface Group {
		/**
		 * 根據(jù)AnnotationMetadata注解元數(shù)據(jù)獲取@Configuration配置的@Import注解導入的DeferredImportSelector選擇器對應的bean
		 */
		void process(AnnotationMetadata metadata, DeferredImportSelector selector);
		/**
		 * 返回類應該導入的Entry
		 */
		Iterable<Entry> selectImports();
		/**
		 * 存放要導入類的全限定名及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;
			}
			/**
			 * 返回要導入類的全限定名
			 */
			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配置文件中定義的類加載到內存之中,供后面的程序將其注冊到IOC容器之中;AutoConfigurationImportSelector類是DeferredImportSelector接口的一個子類,它的作用就是將SpringFactoriesLoader類加載到內中的配置類獲取到,交給后置處理器加載到內存中(不是本文重點);

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

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

返回加載配置類:

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

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

  • AutoConfigurationImportSelector#getExclusions獲取排除導入的配置類
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);
      //獲取配置文件中排除導入配置類
			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());
//獲取所有經過自動化配置過濾器的配置類
	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());
}

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

相關文章

最新評論