私たちは、自動組立SpringBootの原則を要約するためにここにいる、先生の背後にあるいくつかのコンテンツはSpringBootにこのソースをベースに、ちょうどに滞在する多くの小さなパートナーは、これらは、しない理由、状況の知っているように、現在のサービスは、すでに零細企業の標準であります後で学習のためのSpringBootの自動組立の原理を理解していれば、直接書き込みコードに自動組立原理は、倍のより数百になります。
自動組立原則@SpringApplicationの原則を解決するためのプロセスを開始SpringBoot
まずSpringBootは、プロジェクトのために、最も明白な兆候があるということ@SpringBootApplication
SpringBoot自動組立原則今日はそれがで開始するからであるので、それは、SpringBootマークこのプロジェクトです。
まず、私たちが戻って何謎それこのコメント@SpringBootApplicationを見て、私たちは、Ctrlキー+は、優しくタップ、一瞬の奇跡を目撃するために、この時間は、マウスの左ボタンを押してください...
我々は、次のエレガントなコードを参照してください
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM,
classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
// 此处省略一万字
...
}
この1は、2つの比較的簡単に、私達の注意を一方のリードしている@SpringBootConfiguration
別で、ノートを@EnableAutoConfiguration
彼らは素敵に育ったが、理由は他のコメントがあまりにもないので、2は私達の注意を引き付けるためにノートを比較する理由;コメント醜い(主な理由は、我々はすべてに精通している他のコメントの、でも彼らがやっている知らなくても、確かに多くの組立自動化されたが、関連はありません)。その後、我々は悪の小さな手を伸ばし、おなじみの操作は、Ctrl +は、Seのミミ小さな目を見つめ、散瞳をマウスの左ボタンを、奇跡を待って百倍... ...こするこするこする... ...回し
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
}
何も...
私はあなたには役に立たない男が存在を作る方法を、使用するので、世界トップクラスのオープンソースプロジェクトとは何かをしたいん?だから、複雑な操作の後に脳細胞軍の十億を費やし、我々はそれが、これは、構成SpringBootプロジェクトでマークするために使用することができますという結論に来て飛ぶことはありません。心は完全な蒸気が砂漠を飛んで、先にアルパカの何万人ものであるのでSpringBootConfigurationは、SpringBoot構成を変換しているため。
ゆったりとした後、に付着した元の場所に戻るには、Ctrlキー+表ボタンを押すことでギャップを埋めるために、信仰の、熟練した手「失敗することは成功の母です」。@EnableAutoConfigurationを見つめ、見て回る、アドレスバーにGoogleの翻訳を入力して、結果が自動組立を示しています。私はあなたが本当に百度の彼女の何千もの痕跡、その人は薄暗い光の中ではないということです探しています。熟練が入るのを待つことができない、Ctrlキー+左を押し、「土地桃の花の」古典詩から静かに暗唱:
水を作るために森、彼らは山を持って、山は光かのかのように、小さな口を持っています。次に口から、船を丸めます。非常に狭いだけウォルターの始まり。突然の再ラインシュウ渋、
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
// 此处省略100字
...
}
この時点で、人々は良い感じ、その後、私たちは多くのことを静める、新しい世界の顔の前の経験を持っていました。Googleの翻訳は私たちを教えているので、この時点で脳高速動作、もはやもつれ、黄龍を破壊し、AutoConfigurationImportSelector.classクラスに入っていない、これは自動的にインポートセレクタに設定されています。だから我々は新しい世界を発見しました。
public class AutoConfigurationImportSelector
implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware,
BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
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);
// 获取候选的配置类,即使后宫佳丽三千,也是要筛选的
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);
}
}
そして、このエンティティAutoConfigurationEntry自動設定2つの属性の設定および除外があります。
protected static class AutoConfigurationEntry {
// 用来存储需要的配置项
private final List<String> configurations;
// 用来存储排除的配置项
private final Set<String> exclusions;
private AutoConfigurationEntry() {
this.configurations = Collections.emptyList();
this.exclusions = Collections.emptySet();
}
}
バックでは、getAutoConfigurationEntry()メソッドを参照してくださいすることができ、ここで我々が持っている必要がある設定があるオブジェクトの戻り新しいAutoConfigurationEntry(構成、除外)を返します。
それは、彼がそれ候補の設定クラスを得た方法ですか?私たちは、その後、候補の設定方法のこの種を見ることを得ます
List<String> configurations = getCandidateConfigurations(annotationMetadata,attributes);
私たちは、候補特定の構成のコンテンツクラスを取得する次の方法に進むを参照してください
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
AnnotationAttributes attributes) {
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;
}
ここでは、getSpringFactoriesLoaderFactoryClass()メソッドに最初に行くための休憩に従ってください
protected Class<?> getSpringFactoriesLoaderFactoryClass() {
// 返回的是 EnableAutoConfiguration字节码对象
return EnableAutoConfiguration.class;
}
その後、我々はgetBeanClassLoader()メソッドを入力して、これはクラスローダであります
protected ClassLoader getBeanClassLoader() {
return this.beanClassLoader;
}
最後に、私たちは、クラスのバイトコードファイルとクラスローダの構成に基づいて候補者を見つけることですloadFactoryNames()メソッドを、入力します。バイトコード上を通過
public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
// 获取的EnableAutoConfiguration.class的权限定名 //org.springframework.boot.autoconfigure.EnableAutoConfiguration
String factoryClassName = factoryClass.getName();
return loadSpringFactories(classLoader).getOrDefault(factoryClassNa me, Collections.emptyList());
}
図は次のとおりです。
最後に、)(loadSpringFactoriesによってすべての設定クラスを取得します
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
// 缓存加载的配置类,
MultiValueMap<String, String> result = cache.get(classLoader);
if (result != null) {
return result;
}
try {
Enumeration<URL> 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 properties = PropertiesLoaderUtils.loadProperties(resource);
for (Map.Entry<?, ?> entry properties.entrySet()) {
String factoryClassName = ((String) entry.getKey()).trim();
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);
}
}
ここでは、設定ファイルにリソースディレクトリ・パスからロードされFACTORIES_RESOURCE_LOCATIONがロードされている方法を見て
public final class SpringFactoriesLoader {
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
プロジェクトはすべてspring.factories META-INF内のすべてのファイルをロードするために開始する時期であること、私たちは、このファイルについて見つけ、私はシンプルなSpringBootプロジェクトを構築し、それが関連を見つけるために3つのjar内部に移動しますコンフィギュレーション・クラス。
しかし、最後のカテゴリは、ばねブート自動構成-2.1.5.RELEASE.jarの自動組立です
係るEnableAutoConfiguration.classローディングバイトコード・クラスのみ、この構成の自動コンフィギュレーション・クラス118
概要
実際には、自動組立SpringBootの原理は、実際には、このプロジェクトは、META-INF内の負荷spring.factoriesファイルに始めたとき、上のように背が高くていないようでした。もちろん、他の設定項目の負荷があるだろう開始の過程で、ここではロードプロセスのように自動組立を言います。私たちは鼓舞することができます願っています。
質問:私たちは、彼は私たちのカスタム設定クラスをロードしたときに、プロジェクトを始めるために必要がある場合は、それを作成する方法、自動組立SpringBootの原理を理解できますか?