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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

spring boot实战(第九篇)Application创建源码分析

發布時間:2025/3/21 编程问答 15 豆豆
生活随笔 收集整理的這篇文章主要介紹了 spring boot实战(第九篇)Application创建源码分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

通過前面的文章了解到在spring boot的啟動時,利用的是編寫的Application類,使用了注解@SpringBootApplication,本篇將闡述該Bean的加載過程。

?

[html]?view plain?copy

  • @SpringBootApplication??
  • public?class?Application?{??
  • ????public?static?void?main(String[]?args)?{??
  • ????????SpringApplication?app?=?new?SpringApplication(Application.class);???
  • ????????app.addListeners(new?MyApplicationStartedEventListener());??
  • ????????app.run(args);??
  • ????}??
  • }??
  • ?

    ?

    ?

    ?

    ?

    Application

    上篇中講述了上下文的創建,在run方法中接下來會執行

    [html]?view plain?copy

  • load(context,?sources.toArray(new?Object[sources.size()]));??

  • 這個的sources表示的為Application類,在創建SpringApplication時手動傳遞

    [html]?view plain?copy

  • SpringApplication?app?=?new?SpringApplication(Application.class);??
  • ?

    load方法如下:

    ?

    [html]?view plain?copy

  • protected?void?load(ApplicationContext?context,?Object[]?sources)?{??
  • ????????if?(this.log.isDebugEnabled())?{??
  • ????????????this.log.debug("Loading?source?"??
  • ????????????????????+?StringUtils.arrayToCommaDelimitedString(sources));??
  • ????????}??
  • ????????BeanDefinitionLoader?loader?=?createBeanDefinitionLoader(??
  • ????????????????getBeanDefinitionRegistry(context),?sources);??
  • ????????if?(this.beanNameGenerator?!=?null)?{??
  • ????????????loader.setBeanNameGenerator(this.beanNameGenerator);??
  • ????????}??
  • ????????if?(this.resourceLoader?!=?null)?{??
  • ????????????loader.setResourceLoader(this.resourceLoader);??
  • ????????}??
  • ????????if?(this.environment?!=?null)?{??
  • ????????????loader.setEnvironment(this.environment);??
  • ????????}??
  • ????????loader.load();??
  • ????}??

  • 調用loader.load();

    [html]?view plain?copy

  • private?int?load(Object?source)?{??
  • ????????Assert.notNull(source,?"Source?must?not?be?null");??
  • ????????if?(source?instanceof?Class<?>)?{??
  • ????????????return?load((Class<?>)?source);??
  • ????????}??
  • ????????if?(source?instanceof?Resource)?{??
  • ????????????return?load((Resource)?source);??
  • ????????}??
  • ????????if?(source?instanceof?Package)?{??
  • ????????????return?load((Package)?source);??
  • ????????}??
  • ????????if?(source?instanceof?CharSequence)?{??
  • ????????????return?load((CharSequence)?source);??
  • ????????}??
  • ????????throw?new?IllegalArgumentException("Invalid?source?type?"?+?source.getClass());??
  • ????}??

  • 執行load((Class<?>) source)

    ?

    [html]?view plain?copy

  • private?int?load(Class<?>?source)?{??
  • ????????if?(isGroovyPresent())?{??
  • ????????????//?Any?GroovyLoaders?added?in?beans{}?DSL?can?contribute?beans?here??
  • ????????????if?(GroovyBeanDefinitionSource.class.isAssignableFrom(source))?{??
  • ????????????????GroovyBeanDefinitionSource?loader?=?BeanUtils.instantiateClass(source,??
  • ????????????????????????GroovyBeanDefinitionSource.class);??
  • ????????????????load(loader);??
  • ????????????}??
  • ????????}??
  • ????????if?(isComponent(source))?{??
  • ????????????this.annotatedReader.register(source);??
  • ????????????return?1;??
  • ????????}??
  • ????????return?0;??
  • ????}??
  • ?

    isComponent判斷Application是否存在注解Compent

    ?

    [html]?view plain?copy

  • private?boolean?isComponent(Class<?>?type)?{??
  • ????????//?This?has?to?be?a?bit?of?a?guess.?The?only?way?to?be?sure?that?this?type?is??
  • ????????//?eligible?is?to?make?a?bean?definition?out?of?it?and?try?to?instantiate?it.??
  • ????????if?(AnnotationUtils.findAnnotation(type,?Component.class)?!=?null)?{??
  • ????????????return?true;??
  • ????????}??
  • ????????//?Nested?anonymous?classes?are?not?eligible?for?registration,?nor?are?groovy??
  • ????????//?closures??
  • ????????if?(type.getName().matches(".*\\$_.*closure.*")?||?type.isAnonymousClass()??
  • ????????????????||?type.getConstructors()?==?null?||?type.getConstructors().length?==?0)?{??
  • ????????????return?false;??
  • ????????}??
  • ????????return?true;??
  • ????}??

  • AnnotationUtils.findAnnotation(type, Component.class) 工具類獲取執行類對應的注解信息,該工具類在自己編碼代碼時可用得到

    ?

    由于Application使用注解@SpringBootApplication,其定義如下

    ?

    [html]?view plain?copy

  • @Target(ElementType.TYPE)??
  • @Retention(RetentionPolicy.RUNTIME)??
  • @Documented??
  • @Inherited??
  • @Configuration??
  • @EnableAutoConfiguration??
  • @ComponentScan??
  • public?@interface?SpringBootApplication?{??
  • ??
  • ????/**??
  • ?????*?Exclude?specific?auto-configuration?classes?such?that?they?will?never?be?applied.??
  • ?????*?@return?the?classes?to?exclude??
  • ?????*/??
  • ????Class<?>[]?exclude()?default?{};??
  • ??
  • }??

  • 發現不存在Compoment注解,是不是表明Application不是一個Component呢?其實不然,來看下@Configuration注解

    ?

    [html]?view plain?copy

  • @Target(ElementType.TYPE)??
  • @Retention(RetentionPolicy.RUNTIME)??
  • @Documented??
  • @Component??
  • public?@interface?Configuration?{??
  • ??
  • ????/**??
  • ?????*?Explicitly?specify?the?name?of?the?Spring?bean?definition?associated??
  • ?????*?with?this?Configuration?class.??If?left?unspecified?(the?common?case),??
  • ?????*?a?bean?name?will?be?automatically?generated.??
  • ?????*?<p>The?custom?name?applies?only?if?the?Configuration?class?is?picked?up?via??
  • ?????*?component?scanning?or?supplied?directly?to?a?{@link?AnnotationConfigApplicationContext}.??
  • ?????*?If?the?Configuration?class?is?registered?as?a?traditional?XML?bean?definition,??
  • ?????*?the?name/id?of?the?bean?element?will?take?precedence.??
  • ?????*?@return?the?specified?bean?name,?if?any??
  • ?????*?@see?org.springframework.beans.factory.support.DefaultBeanNameGenerator??
  • ?????*/??
  • ????String?value()?default?"";??
  • ??
  • }??

  • 發現Configuration注解上存在Component注解,表明Application為Component

    ?

    接下來執行this.annotatedReader.register(source);

    ?

    [html]?view plain?copy

  • public?void?register(Class<?>...?annotatedClasses)?{??
  • ????????for?(Class<?>?annotatedClass?:?annotatedClasses)?{??
  • ????????????registerBean(annotatedClass);??
  • ????????}??
  • ????}??

  • 調用registerBean注冊Application對應的bean信息

    ?

    [html]?view plain?copy

  • public?void?registerBean(Class<?>?annotatedClass,?String?name,??
  • ????????????@SuppressWarnings("unchecked")?Class<??extends?Annotation>...?qualifiers)?{??
  • ??
  • ????????AnnotatedGenericBeanDefinition?abd?=?new?AnnotatedGenericBeanDefinition(annotatedClass);??
  • ????????if?(this.conditionEvaluator.shouldSkip(abd.getMetadata()))?{??
  • ????????????return;??
  • ????????}??
  • ??
  • ????????ScopeMetadata?scopeMetadata?=?this.scopeMetadataResolver.resolveScopeMetadata(abd);??
  • ????????abd.setScope(scopeMetadata.getScopeName());??
  • ????????String?beanName?=?(name?!=?null???name?:?this.beanNameGenerator.generateBeanName(abd,?this.registry));??
  • ????????AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);??
  • ????????if?(qualifiers?!=?null)?{??
  • ????????????for?(Class<??extends?Annotation>?qualifier?:?qualifiers)?{??
  • ????????????????if?(Primary.class.equals(qualifier))?{??
  • ????????????????????abd.setPrimary(true);??
  • ????????????????}??
  • ????????????????else?if?(Lazy.class.equals(qualifier))?{??
  • ????????????????????abd.setLazyInit(true);??
  • ????????????????}??
  • ????????????????else?{??
  • ????????????????????abd.addQualifier(new?AutowireCandidateQualifier(qualifier));??
  • ????????????????}??
  • ????????????}??
  • ????????}??
  • ??
  • ????????BeanDefinitionHolder?definitionHolder?=?new?BeanDefinitionHolder(abd,?beanName);??
  • ????????definitionHolder?=?AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata,?definitionHolder,?this.registry);??
  • ????????BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder,?this.registry);??
  • ????}??

  • 首先來看

    ?

    [html]?view plain?copy

  • if?(this.conditionEvaluator.shouldSkip(abd.getMetadata()))?{??
  • ????????????return;??
  • ????????}??

  • 判斷是否需要跳過,其代碼如下:

    ?

    [html]?view plain?copy

  • public?boolean?shouldSkip(AnnotatedTypeMetadata?metadata,?ConfigurationPhase?phase)?{??
  • ????????if?(metadata?==?null?||?!metadata.isAnnotated(Conditional.class.getName()))?{??
  • ????????????return?false;??
  • ????????}??
  • ??
  • ????????if?(phase?==?null)?{??
  • ????????????if?(metadata?instanceof?AnnotationMetadata?&&??
  • ????????????????????ConfigurationClassUtils.isConfigurationCandidate((AnnotationMetadata)?metadata))?{??
  • ????????????????return?shouldSkip(metadata,?ConfigurationPhase.PARSE_CONFIGURATION);??
  • ????????????}??
  • ????????????return?shouldSkip(metadata,?ConfigurationPhase.REGISTER_BEAN);??
  • ????????}??
  • ??
  • ????????List<Condition>?conditions?=?new?ArrayList<Condition>();??
  • ????????for?(String[]?conditionClasses?:?getConditionClasses(metadata))?{??
  • ????????????for?(String?conditionClass?:?conditionClasses)?{??
  • ????????????????Condition?condition?=?getCondition(conditionClass,?this.context.getClassLoader());??
  • ????????????????conditions.add(condition);??
  • ????????????}??
  • ????????}??
  • ??
  • ????????AnnotationAwareOrderComparator.sort(conditions);??
  • ??
  • ????????for?(Condition?condition?:?conditions)?{??
  • ????????????ConfigurationPhase?requiredPhase?=?null;??
  • ????????????if?(condition?instanceof?ConfigurationCondition)?{??
  • ????????????????requiredPhase?=?((ConfigurationCondition)?condition).getConfigurationPhase();??
  • ????????????}??
  • ????????????if?(requiredPhase?==?null?||?requiredPhase?==?phase)?{??
  • ????????????????if?(!condition.matches(this.context,?metadata))?{??
  • ????????????????????return?true;??
  • ????????????????}??
  • ????????????}??
  • ????????}??
  • ??
  • ????????return?false;??
  • ????}??

  • 該代碼判斷Application上是否存在Conditional注解,如果不滿足Conditional對應條件則該bean不被創建;

    ?

    Conditional注解

    代碼分析到這里可以先看看Conditional注解的使用,其定義為:

    [html]?view plain?copy

  • @Retention(RetentionPolicy.RUNTIME)??
  • @Target({ElementType.TYPE,?ElementType.METHOD})??
  • public?@interface?Conditional?{??
  • ????/**??
  • ?????*?All?{@link?Condition}s?that?must?{@linkplain?Condition#matches?match}??
  • ?????*?in?order?for?the?component?to?be?registered.??
  • ?????*/??
  • ????Class<??extends?Condition>[]?value();??
  • ??
  • }??

  • 從源碼可以看出,首先判斷Application上是否存在Conditional,如果存在,則獲取Conditional注解中的value數組值,對應的Class必須實現Condition接口:

    ?

    [html]?view plain?copy

  • public?interface?Condition?{???
  • ????boolean?matches(ConditionContext?context,?AnnotatedTypeMetadata?metadata);??
  • ??
  • }??

  • 如果matches返回true 表明該bean需要被創建,否則表明該bean不需要被創建。

    ?

    明白了該注解的用法后,來一個實際案例

    [html]?view plain?copy

  • package?com.lkl.springboot.condition;??
  • ??
  • import?org.springframework.context.annotation.Conditional;??
  • import?org.springframework.stereotype.Component;??
  • ??
  • @Component("MyCondition")??
  • @Conditional(MyCondition.class)??
  • public?class?ConditionBean?{??
  • }??

  • 創建ConditionBean,使用注解@Conditional(MyCondition.class)調用MyCondition類

    ?

    [html]?view plain?copy

  • /**??
  • ?*?自定義condition??修改返回值,查看bean是否創建??
  • ?*???
  • ?*?@author?liaokailin??
  • ?*/??
  • public?class?MyCondition?implements?Condition?{??
  • ??
  • ????/**??
  • ?????*?返回true?生成bean??
  • ?????*?返回false?不生成bean???
  • ?????*/??
  • ????@Override??
  • ????public?boolean?matches(ConditionContext?context,?AnnotatedTypeMetadata?metadata)?{??
  • ????????Map<String,?Object>?map?=?metadata.getAnnotationAttributes(Component.class.getName());??
  • ????????return?"MyCondition".equals(map.get("value").toString());??
  • ????}??
  • ??
  • }??

  • MyCondition實現接口Condition,在matches方法中獲取bean上注解Component信息,如果bean名稱等于MyCondition返回true,否則返回false,bean不會被創建。

    ?

    回到前面Application的分析,Application上不存在Conditional,因此shouldSkip返回false,代碼繼續執行

    ?

    [html]?view plain?copy

  • ScopeMetadata?scopeMetadata?=?this.scopeMetadataResolver.resolveScopeMetadata(abd);??
  • 處理Scope注解信息,默認是單例bean

    執行

    [html]?view plain?copy

  • AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);??

  • 處理一些常見注解信息

    ?

    [html]?view plain?copy

  • static?void?processCommonDefinitionAnnotations(AnnotatedBeanDefinition?abd,?AnnotatedTypeMetadata?metadata)?{??
  • ????????if?(metadata.isAnnotated(Lazy.class.getName()))?{??
  • ????????????abd.setLazyInit(attributesFor(metadata,?Lazy.class).getBoolean("value"));??
  • ????????}??
  • ????????else?if?(abd.getMetadata()?!=?metadata?&&?abd.getMetadata().isAnnotated(Lazy.class.getName()))?{??
  • ????????????abd.setLazyInit(attributesFor(abd.getMetadata(),?Lazy.class).getBoolean("value"));??
  • ????????}??
  • ??
  • ????????if?(metadata.isAnnotated(Primary.class.getName()))?{??
  • ????????????abd.setPrimary(true);??
  • ????????}??
  • ????????if?(metadata.isAnnotated(DependsOn.class.getName()))?{??
  • ????????????abd.setDependsOn(attributesFor(metadata,?DependsOn.class).getStringArray("value"));??
  • ????????}??
  • ??
  • ????????if?(abd?instanceof?AbstractBeanDefinition)?{??
  • ????????????AbstractBeanDefinition?absBd?=?(AbstractBeanDefinition)?abd;??
  • ????????????if?(metadata.isAnnotated(Role.class.getName()))?{??
  • ????????????????absBd.setRole(attributesFor(metadata,?Role.class).getNumber("value").intValue());??
  • ????????????}??
  • ????????????if?(metadata.isAnnotated(Description.class.getName()))?{??
  • ????????????????absBd.setDescription(attributesFor(metadata,?Description.class).getString("value"));??
  • ????????????}??
  • ????????}??
  • ????}??

  • 處理Lazy、Primary、DependsOn、Role、Description等注解

    ?

    最后調用

    [html]?view plain?copy

  • BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder,?this.registry);??

  • 注冊bean信息,在注冊bean信息之前通過

    [html]?view plain?copy

  • String?beanName?=?(name?!=?null???name?:?this.beanNameGenerator.generateBeanName(abd,?this.registry));??
  • 獲取bean名稱


    bean的注冊調用為

    [html]?view plain?copy

  • registry.registerBeanDefinition(beanName,?definitionHolder.getBeanDefinition());??
  • 該代碼在上篇中已有說明。

    ?

    此時Application對應bean已創建完成。

    總結

    以上是生活随笔為你收集整理的spring boot实战(第九篇)Application创建源码分析的全部內容,希望文章能夠幫你解決所遇到的問題。

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

    主站蜘蛛池模板: 欧美日韩一区二区区别是什么 | 精品欧美一区二区在线观看 | 奇米网7777| 精品一区二区三 | xx69欧美 | 中文字幕第一页在线播放 | 会喷水的亲姐姐 | 免费福利影院 | 久久久久久网 | 国产日批视频 | 国产一区=区 | 久操影视 | 日本大尺度吃奶做爰久久久绯色 | 学生孕妇videosex性欧美 | 懂色av一区二区在线播放 | 中文字幕免费在线观看视频 | 亚洲视频综合 | 久久久国产成人一区二区三区 | 香蕉久久国产av一区二区 | 日韩成人一级 | 99热1 | 都市激情校园春色亚洲 | 国产精品99无码一区二区视频 | 亚洲欧美日韩中文字幕在线观看 | 亚洲一区二区三区电影 | 亚洲视频精品在线观看 | 成人免费网站视频 | 毛片毛片毛片毛片毛片毛片 | 桥本有菜aⅴ一区二区三区 在线午夜电影 | 国产真实乱人偷精品视频 | 又污又黄的网站 | 好男人www | 久久久久久免费 | 日韩欧美在线免费 | 欧美激情黑白配 | 噼里啪啦动漫高清在线观看 | 狠狠cao日日穞夜夜穞av | 天堂在线一区二区 | 国产女优在线播放 | 久久这里只有精品23 | 91精品国产乱码久久久久久久久 | 国产精选av| 日韩欧美中文字幕一区二区三区 | 欧美成人黄色 | 午夜精品在线视频 | xxxwww黄色| 国内一级黄色片 | 中文在线一区二区三区 | 金鱼妻日剧免费观看完整版全集 | 在线亚洲欧美 | 殴美一级视频 | exo妈妈mv在线播放高清免费 | 久久精品免费看 | 久久久久久无码午夜精品直播 | 亚洲最大色网站 | 日本熟妇浓毛 | 亚洲四区在线 | 欧美肉丝袜videos办公室 | 日本xxxx18高清hd| 天天看天天爽 | 成人a在线 | 久草视频在线免费 | 痴汉电车在线播放 | 国产中文字幕在线播放 | 最新视频 - 88av| 四虎影院免费视频 | 香蕉网在线观看 | 亚洲性生活网站 | 亚洲精品视频中文字幕 | 四虎影视库| 亚洲网站一区 | 国产免费资源 | 在线观看欧美日韩视频 | 性感美女被爆操 | 欧美性在线观看 | 日本高清免费视频 | 国产主播在线一区 | 制服丝袜在线视频 | 黄色免费网页 | 韩国毛片视频 | 精品一区亚洲 | 成人xxx视频 | 国产视频一区二区三区在线 | 99精品中文字幕 | 鲍鱼av在线 | 亚洲精品免费在线播放 | 一区二区三区xxx | 久久久999视频 | 国产亚洲区 | 国产精品视频第一页 | 动漫美女露胸网站 | 亚洲三级在线免费观看 | 在线观看免费黄视频 | 亚洲av久久久噜噜噜噜 | 国产成人自拍网站 | 蜜桃啪啪| 丰满人妻翻云覆雨呻吟视频 | 日韩免费av在线 | 99精品人妻少妇一区二区 |