SpringBoot快速通關(guān)自動配置應(yīng)用
@EnableAutoConfiguration
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import(AutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration { String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration"; Class<?>[] exclude() default {}; String[] excludeName() default {}; }
標注了@AutoConfigurationPackage,并且導入了AutoConfigurationImportSelector
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Import(AutoConfigurationPackages.Registrar.class) public @interface AutoConfigurationPackage { }
@AutoConfigurationPackage注解導入了AutoConfigurationPackages.Registrar。
下面來看看這兩個導入類
AutoConfigurationPackages.Registrar
這是一個內(nèi)部類,外部類AutoConfigurationPackages是一個抽象類
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports { @Override public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { //注冊 register(registry, new PackageImport(metadata).getPackageName()); } //這個方法沒有地方調(diào)用,暫不分析 @Override public Set<Object> determineImports(AnnotationMetadata metadata) { return Collections.singleton(new PackageImport(metadata)); } }
注冊
private final String packageName; PackageImport(AnnotationMetadata metadata) { this.packageName = ClassUtils.getPackageName(metadata.getClassName()); }
PackageImport也是一個內(nèi)部類,構(gòu)造方法中賦值了一個成員變量packageName。
public static String getPackageName(String fqClassName) { Assert.notNull(fqClassName, "Class name must not be null"); int lastDotIndex = fqClassName.lastIndexOf(PACKAGE_SEPARATOR); return (lastDotIndex != -1 ? fqClassName.substring(0, lastDotIndex) : ""); }
getPackageName方法中會根據(jù)@AutoConfigurationPackage標注類的全限定名,獲取@AutoConfigurationPackage標注類的包名。
然后將@AutoConfigurationPackage標注類的包名賦值給PackageImport的成員變量packageName。
String getPackageName() { return this.packageName; }
getPackageName方法只是簡單的將PackageImport#packageName返回。
然后調(diào)用外部類AutoConfigurationPackages的靜態(tài)方法register
private static final String BEAN = AutoConfigurationPackages.class.getName(); public static void register(BeanDefinitionRegistry registry, String... packageNames) { //已經(jīng)注冊過 BEAN 了,代表不是第一次調(diào)用AutoConfigurationPackages.Registrar if (registry.containsBeanDefinition(BEAN)) { BeanDefinition beanDefinition = registry.getBeanDefinition(BEAN); ConstructorArgumentValues constructorArguments = beanDefinition.getConstructorArgumentValues(); //將這次調(diào)用AutoConfigurationPackages.Registrar,將標注@AutoConfigurationPackage 注解的類的包名添加到 BEAN 的參數(shù)中 constructorArguments.addIndexedArgumentValue(0, addBasePackages(constructorArguments, packageNames)); } else { //第一次調(diào)用AutoConfigurationPackages.Registrar,注冊 BEAN GenericBeanDefinition beanDefinition = new GenericBeanDefinition(); beanDefinition.setBeanClass(BasePackages.class); //獲取BasePackages構(gòu)造器的參數(shù),是個 String... ,將packageNames放到數(shù)組第一個位置 beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0, packageNames); beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); registry.registerBeanDefinition(BEAN, beanDefinition); } }
注冊AutoConfigurationPackages
static final class BasePackages { private final List<String> packages; private boolean loggedBasePackageInfo; BasePackages(String... names) { List<String> packages = new ArrayList<>(); for (String name : names) { if (StringUtils.hasText(name)) { packages.add(name); } } this.packages = packages; } List<String> get() { if (!this.loggedBasePackageInfo) { if (this.packages.isEmpty()) { if (logger.isWarnEnabled()) { ...//只是輸出日志 } } else { if (logger.isDebugEnabled()) { String packageNames = StringUtils.collectionToCommaDelimitedString(this.packages); ...//輸出日志 } } this.loggedBasePackageInfo = true; } return this.packages; } }
注冊時bean的名稱是上面的 BEAN,bean的類為BasePackages。
已經(jīng)注冊過AutoConfigurationPackages
private static String[] addBasePackages(ConstructorArgumentValues constructorArguments, String[] packageNames) { //取出BasePackages構(gòu)造器的參數(shù) String... String[] existing = (String[]) constructorArguments.getIndexedArgumentValue(0, String[].class).getValue(); //創(chuàng)建新的集合,將原有的包名和現(xiàn)有的包名添加進去,用set去重,然后返回 Set<String> merged = new LinkedHashSet<>(); merged.addAll(Arrays.asList(existing)); merged.addAll(Arrays.asList(packageNames)); return StringUtils.toStringArray(merged); }
AutoConfigurationImportSelector
AutoConfigurationImportSelector實現(xiàn)了DeferredImportSelector,DeferredImportSelector實現(xiàn)了ImportSelector。
public String[] selectImports(AnnotationMetadata annotationMetadata) { //不起用自動裝配 if (!isEnabled(annotationMetadata)) { return NO_IMPORTS; } //獲得AutoConfiguration的注解元數(shù)據(jù) AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader .loadMetadata(this.beanClassLoader); AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata); return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations()); }
protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) { if (!isEnabled(annotationMetadata)) { return EMPTY_ENTRY; } //獲取注解的屬性 AnnotationAttributes attributes = getAttributes(annotationMetadata); //獲取實現(xiàn)EnableAutoConfiguration的類名集合 List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes); //去重 configurations = removeDuplicates(configurations); //獲取要排除的類名 Set<String> exclusions = getExclusions(annotationMetadata, attributes); checkExcludedClasses(configurations, exclusions); //排除 configurations.removeAll(exclusions); //過濾 configurations = filter(configurations, autoConfigurationMetadata); fireAutoConfigurationImportEvents(configurations, exclusions); return new AutoConfigurationEntry(configurations, exclusions); }
獲取所有EnableAutoConfiguration實現(xiàn)類名
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { //利用spi獲取實現(xiàn)了EnableAutoConfiguration的類名集合 List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()); Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you " + "are using a custom packaging, make sure that file is correct."); return configurations; }
protected Class<?> getSpringFactoriesLoaderFactoryClass() { return EnableAutoConfiguration.class; }
去重
protected final <T> List<T> removeDuplicates(List<T> list) { return new ArrayList<>(new LinkedHashSet<>(list)); }
獲取要排除的類名
protected Set<String> getExclusions(AnnotationMetadata metadata, AnnotationAttributes attributes) { Set<String> excluded = new LinkedHashSet<>(); excluded.addAll(asList(attributes, "exclude")); excluded.addAll(Arrays.asList(attributes.getStringArray("excludeName"))); excluded.addAll(getExcludeAutoConfigurationsProperty()); return excluded; }
private List<String> getExcludeAutoConfigurationsProperty() { if (getEnvironment() instanceof ConfigurableEnvironment) { Binder binder = Binder.get(getEnvironment()); return binder.bind(PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE, String[].class).map(Arrays::asList) .orElse(Collections.emptyList()); } String[] excludes = getEnvironment().getProperty(PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE, String[].class); return (excludes != null) ? Arrays.asList(excludes) : Collections.emptyList(); }
過濾
private List<String> filter(List<String> configurations, AutoConfigurationMetadata autoConfigurationMetadata) { long startTime = System.nanoTime(); String[] candidates = StringUtils.toStringArray(configurations); boolean[] skip = new boolean[candidates.length]; boolean skipped = false; for (AutoConfigurationImportFilter filter : getAutoConfigurationImportFilters()) { invokeAwareMethods(filter); boolean[] match = filter.match(candidates, autoConfigurationMetadata); for (int i = 0; i < match.length; i++) { if (!match[i]) { skip[i] = true; candidates[i] = null; skipped = true; } } } if (!skipped) { return configurations; } List<String> result = new ArrayList<>(candidates.length); for (int i = 0; i < candidates.length; i++) { if (!skip[i]) { result.add(candidates[i]); } } if (logger.isTraceEnabled()) { int numberFiltered = configurations.size() - result.size(); logger.trace("Filtered " + numberFiltered + " auto configuration class in " + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime) + " ms"); } return new ArrayList<>(result); }
protected List<AutoConfigurationImportFilter> getAutoConfigurationImportFilters() { return SpringFactoriesLoader.loadFactories(AutoConfigurationImportFilter.class, this.beanClassLoader); }
根據(jù)AutoConfigurationImportFilter的實現(xiàn)類過濾自動裝配類
到此這篇關(guān)于SpringBoot快速通關(guān)自動配置應(yīng)用的文章就介紹到這了,更多相關(guān)SpringBoot自動配置內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java使用正則表達式實現(xiàn)找出數(shù)字功能示例
這篇文章主要介紹了Java使用正則表達式實現(xiàn)找出數(shù)字功能,結(jié)合實例形式分析了Java針對數(shù)字的匹配查找及非數(shù)字替換操作相關(guān)實現(xiàn)技巧,需要的朋友可以參考下2017-03-03Java模擬實現(xiàn)撲克牌洗牌和發(fā)牌的示例代碼
這篇文章主要為大家詳細介紹了如何利用Java模擬實現(xiàn)撲克牌洗牌和發(fā)牌的功能,文中的示例代碼講解詳細,感興趣的小伙伴可以嘗試一下2022-09-09

Java實現(xiàn)讀取TXT和CSV文件內(nèi)容

SpringBoot中JPA實現(xiàn)Sort排序的三種方式小結(jié)