日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java 自动装载_springboot自动装载

發布時間:2024/9/3 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 自动装载_springboot自动装载 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

代碼分析版本為2.1.4.RELEASE

! V: P8 _??m??d% `' d: C$ N. ~springboot是spring的拓展框架,不需要再寫xml文件,來配置bean的加載,使開發更加便捷和高效。

4 I$ W* y* t6 S1 }/ K8 }1. 從哪里加載bean?

( E9 Q8 s; ]: W9 e

2 g# R) w( s3 W! E$ ^??K從注解開始分析

1 V9 h" o* e. [+ n5 d' v$ O% g; N6 O??z5 i) W5 ]

7 V9 W, I0 r4 o9 {5 H, r& JSpringBootApplication.java:

+ t* h0 h) G1 u) i0 @' n0 Z/ M@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 { …… }??分別查看SpringBootApplication上的注解,發現EnableAutoConfiguration.java有比較重要的信息:. x( }* m! E: {0 h/ Z1 {3 `/ g

@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited//重點看這里@AutoConfigurationPackage//重點看這里@Import(AutoConfigurationImportSelector.class)public @interface EnableAutoConfiguration {? ? String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";? ? /**? ???* Exclude specific auto-configuration classes such that they will never be applied.? ???* @return the classes to exclude? ???*/? ? Class[] exclude() default {};? ? /**? ???* Exclude specific auto-configuration class names such that they will never be? ???* applied.? ???* @return the class names to exclude? ???* @since 1.3.0? ???*/? ? String[] excludeName() default {};}@AutoConfigurationPackage:表示將該類所對應的包加入到自動配置。即將MainApplication.java對應的包名加入到自動裝配。@Import(AutoConfigurationImportSelector.class) :這里在程序初始化的時候,會執行AutoConfigurationImportSelector.AutoConfigurationGroup.process,自動裝載bean,詳情邏輯請繼續看下面。

3 ~, _8 b3 r??W1 qAutoConfigurationImportSelector.java:

& X/ f8 ~8 |1 f: B; dpublic class AutoConfigurationImportSelector? ?? ???implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware,? ?? ???BeanFactoryAware, EnvironmentAware, Ordered {}AutoConfigurationImportSelector的類圖:

. ^5 F" N" F( D: Q

2 ]. L9 |) u% C' ~; D3 T. {0 b

可見其實現了DeferredImportSelector類,而DeferredImportSelector又繼承ImportSelector類。該實現關系請記住,將有利于下面的代碼分析。

& p4 J6 n2 @0 ]在這里,先跟大家說一下,程序初始化的時候會執行AutoConfigurationImportSelector.AutoConfigurationGroup.process(為什么會執行該方法?詳情查看2)+ {* U& K/ j( {2 P

那么該方法實現了什么邏輯呢?& [: U5 l$ p$ e* g

@Override? ?? ???public void process(AnnotationMetadata annotationMetadata,? ?? ?? ?? ?? ? DeferredImportSelector deferredImportSelector) {? ?? ?? ?? ?Assert.state(? ?? ?? ?? ?? ?? ???deferredImportSelector instanceof AutoConfigurationImportSelector,? ?? ?? ?? ?? ?? ???() -> String.format("Only %s implementations are supported, got %s",? ?? ?? ?? ?? ?? ?? ?? ?? ? AutoConfigurationImportSelector.class.getSimpleName(),? ?? ?? ?? ?? ?? ?? ?? ?? ? deferredImportSelector.getClass().getName()));? ?? ?? ?? ?//重點看這里:獲取自動裝配實體? ?? ?? ?? ?AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)? ?? ?? ?? ?? ?? ???.getAutoConfigurationEntry(getAutoConfigurationMetadata(),? ?? ?? ?? ?? ?? ?? ?? ?? ? annotationMetadata);? ?? ?? ?? ?this.autoConfigurationEntries.add(autoConfigurationEntry);? ?? ?? ?? ?for (String importClassName : autoConfigurationEntry.getConfigurations()) {? ?? ?? ?? ?? ? this.entries.putIfAbsent(importClassName, annotationMetadata);? ?? ?? ?? ?}? ?? ???}其中再看一下getAutoConfigurationEntry方法:

& e+ q# a2 y& z+ h/**? ???* Return the {@link AutoConfigurationEntry} based on the {@link AnnotationMetadata}? ???* of the importing {@link Configuration @Configuration} class.? ???* @param autoConfigurationMetadata the auto-configuration metadata? ???* @param annotationMetadata the annotation metadata of the configuration class? ???* @return the auto-configurations that should be imported? ???*/? ? protected AutoConfigurationEntry getAutoConfigurationEntry(? ?? ?? ?? ?AutoConfigurationMetadata autoConfigurationMetadata,? ?? ?? ?? ?AnnotationMetadata annotationMetadata) {? ?? ???if (!isEnabled(annotationMetadata)) {? ?? ?? ?? ?return EMPTY_ENTRY;? ?? ???}? ?? ???AnnotationAttributes attributes = getAttributes(annotationMetadata);? ?? ? //猜測:獲取配置類,從哪里獲取?再細看這里的代碼? ?? ???List configurations = getCandidateConfigurations(annotationMetadata,? ?? ?? ?? ?? ? attributes);? ?? ?//刪除重復名稱的bean? ?? ???configurations = removeDuplicates(configurations);? ?? ?//獲取元數據的不應包括的類名(excludeName、exclude)? ?? ???Set exclusions = getExclusions(annotationMetadata, attributes);? ?? ???checkExcludedClasses(configurations, exclusions);? ?? ?//刪除不應包括的類名? ?? ???configurations.removeAll(exclusions);? ?? ?//過濾需要過濾的配置類? ?? ???configurations = filter(configurations, autoConfigurationMetadata);? ?? ???fireAutoConfigurationImportEvents(configurations, exclusions);? ?? ???return new AutoConfigurationEntry(configurations, exclusions);? ? }下面來重點看看該方法的實現:$ y2 j, l) D' P$ C

//猜測:獲取配置類,從哪里獲取?再細看這里的代碼? ?? ???List configurations = getCandidateConfigurations(annotationMetadata,? ?? ?? ?? ?? ? attributes);org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#getCandidateConfigurations:

% e* z6 o$ r- P( X4 f8 c) A/**? ???* Return the auto-configuration class names that should be considered. By default? ???* this method will load candidates using {@link SpringFactoriesLoader} with? ???* {@link #getSpringFactoriesLoaderFactoryClass()}.? ???* @param metadata the source metadata? ???* @param attributes the {@link #getAttributes(AnnotationMetadata) annotation? ???* attributes}? ???* @return a list of candidate configurations? ???*/? ? protected List getCandidateConfigurations(AnnotationMetadata metadata,? ?? ?? ?? ?AnnotationAttributes attributes) {? ?? ? //實質調用了SpringFactoriesLoader.loadFactoryNames(EnableAutoConfiguration.class, this.beanClassLoader);? ?? ???List 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;? ? }??/**? ???* Return the class used by {@link SpringFactoriesLoader} to load configuration? ???* candidates.? ???* @return the factory class? ???*/? ? protected Class getSpringFactoriesLoaderFactoryClass() {? ?? ???return EnableAutoConfiguration.class;? ? }從上面的代碼注解中,繼續深入loadFactoryNames方法,即獲取EnableAutoConfiguration為key的所有類名4 p4 ]2 c1 W7 o, m??n

org.springframework.core.io.support.SpringFactoriesLoader#loadFactoryNames:

3 a* H& _1 Q' a- }: J* ^0 O# Spublic static List loadFactoryNames(Class factoryClass, @Nullable ClassLoader classLoader) {? ?? ???String factoryClassName = factoryClass.getName();? ?? ???return loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());? ? }? ? private static Map loadSpringFactories(@Nullable ClassLoader classLoader) {? ?? ???MultiValueMap result = cache.get(classLoader);? ?? ???if (result != null) {? ?? ?? ?? ?return result;? ?? ???}? ?? ???try {? ?? ?? ?? ?Enumeration urls = (classLoader != null ?? ?? ???//注解1:FACTORIES_RESOURCE_LOCATION=META-INF/spring.factories,即從該路徑下獲取類? ?? ?? ?? ?? ?? ? 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);? ?? ???}? ? }注解1:就是加載所有包的spring.factories文件,然后逐個解釋7 y% [0 H) L: J8 n- U: s0 G

其中:" K# H9 y6 U' D8 _% p2 Y

Properties properties = PropertiesLoaderUtils.loadProperties(resource);# b/ p' K3 m; ]/ J??v4 K???

解釋spring.factories文件" ^* ^: T9 \+ U7 P" }5 C) A1 ?

如下圖所示,某個包下的spring.factories文件:

: K1 e6 @- _0 f

轉化為# E9 K3 o* u7 c. T" M- M/ v

org.springframework.boot.autoconfigure.EnableAutoConfiguration->

2 ]$ @' X4 F2 Q2 xorg.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration

% a7 F4 Q0 b) R; H4 I) T4 e6 }9 p0 T' l相關流程圖如下:

" U8 c$ h4 l8 S* c# L

; J??y, j$ c" i

2. 為什么會執行AutoConfigurationImportSelector.AutoConfigurationGroup.process?' Q6 b$ \/ Y/ x+ ^5 |7 J/ Z

5 E8 Z2 }" v, b- U* D4 ^9 S* e4 s9 V

從springApplication.run開始:" s6 G( Y* S# b0 A+ K+ l

5 G0 x' r1 u7 ~. h% M

代碼太多,挑重點的說:

6 `; _# s# k" R0 e' ?org.springframework.context.annotation.ConfigurationClassParser#doProcessConfigurationClass6 x3 Q) {??J+ A4 f/ w

會處理如下圖所示的注解,在分析@Import注解時,會查看該類是不是實現DeferredImportSelector類,如果是,則會調用this.deferredImportSelectorHandler.process()。很明顯,在前面提到,AutoConfigurationImportSelector實現了DeferredImportSelector,所以在后面的邏輯中,會調用AutoConfigurationImportSelector.AutoConfigurationGroup.process方法9 p- z% w4 U; D; Y$ W; n' h

總結:

3 J; c# d8 a* p) Q??d) g- U4 C0 a??~$ u?????G, O5 |9 e! A: `

springboot會自動掃描mainApplication類所在包的所有bean- N+ v9 I& m' R7 T# P% Q, i! d

springboot會自動掃描jar包下面的/METF/spring.factories文件,將EnableAutoConfiguration為key的所有類名加載出來,并進行去重、過濾

) q3 r* ~+ D6 m% A3 X??x6 i

( U; M3 z??I??`' ^5 e! A7 r; d! hJava吧 收集整理 java論壇 www.java8.com

總結

以上是生活随笔為你收集整理的java 自动装载_springboot自动装载的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。