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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring5源码 - 00 IOC容器创建_前期准备

發布時間:2025/3/21 javascript 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring5源码 - 00 IOC容器创建_前期准备 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 實例化容器
  • 源碼分析
    • this
      • 調用父類的構造函數
      • 然后調用自己的構造函數
        • new AnnotatedBeanDefinitionReader(this);
        • new ClassPathBeanDefinitionScanner(this);
    • register(annotatedClasses);


實例化容器

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(App.class);

源碼分析

進去看一下

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {//調用構造函數this();//注冊我們的配置類register(annotatedClasses);//IOC容器刷新接口refresh();}

這里我們分析一下AnnotationConfigApplicationContext 構造函數中的前兩個方法

  • this()
  • register(annotatedClasses);

this

調用父類的構造函數

調用AnnotationConfigApplicationContext無參的構造器,會先調用父類GenericApplicationContext的無參構造器

public GenericApplicationContext() {//創建IOC容器 ,用于存放beanthis.beanFactory = new DefaultListableBeanFactory();}

調用父類的構造方法 生成一個IOC容器,主要是存放bean定義


然后調用自己的構造函數

public AnnotationConfigApplicationContext() {StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");/*** 初始化注解模式下的bean定義掃描器 * 調用AnnotatedBeanDefinitionReader構造方法,傳入的是this(AnnotationConfigApplicationContext)對象*/this.reader = new AnnotatedBeanDefinitionReader(this);createAnnotatedBeanDefReader.end();/*** 初始化我們的classPath類型的bean定義掃描器*/this.scanner = new ClassPathBeanDefinitionScanner(this);}

我們看下這里面主要的方法

new AnnotatedBeanDefinitionReader(this);

跟進去

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {this(registry, getOrCreateEnvironment(registry));}

就是為bean定義讀取器賦值,

那毫無疑問 先getOrCreateEnvironment(registry) ---- 創建環境

/*** Get the Environment from the given registry if possible, otherwise return a new* StandardEnvironment.*/private static Environment getOrCreateEnvironment(BeanDefinitionRegistry registry) {Assert.notNull(registry, "BeanDefinitionRegistry must not be null");if (registry instanceof EnvironmentCapable) {return ((EnvironmentCapable) registry).getEnvironment();}return new StandardEnvironment();}

然后繼續this方法的調用 ,

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {Assert.notNull(registry, "BeanDefinitionRegistry must not be null");Assert.notNull(environment, "Environment must not be null");this.registry = registry;this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);}

第一步

this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);

創建一個條件計算器對象 ,用于處理 條件表達式計算 @Conditionl注解


第二步 , 為容器中注冊系統的bean定義信息 ,這些后置處理器 是Spring開天辟地初始化內部beandefinition的地方, 沒有這個,就沒有IOC,非常重要。

AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);

來跟進去

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source) {DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);if (beanFactory != null) {if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {//注冊了實現Order接口的排序器beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);}//設置@AutoWired的候選的解析器if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());}}Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);/*** 為我們容器中注冊了解析我們配置類的后置處理器ConfigurationClassPostProcessor* 名字叫:org.springframework.context.annotation.internalConfigurationAnnotationProcessor*/if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));}/*** 為我們容器中注冊了處理@Autowired 注解的處理器AutowiredAnnotationBeanPostProcessor* 名字叫:org.springframework.context.annotation.internalAutowiredAnnotationProcessor*/if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));}/*** 為我們容器中注冊處理@Required屬性的注解處理器RequiredAnnotationBeanPostProcessor* 名字叫:org.springframework.context.annotation.internalRequiredAnnotationProcessor*/if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));}/*** 為我們容器注冊處理JSR規范的注解處理器CommonAnnotationBeanPostProcessor* org.springframework.context.annotation.internalCommonAnnotationProcessor*/if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));}/*** 處理jpa注解的處理器org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor*/if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition();try {def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,AnnotationConfigUtils.class.getClassLoader()));}catch (ClassNotFoundException ex) {throw new IllegalStateException("Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);}def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));}/*** 處理監聽方法的注解解析器EventListenerMethodProcessor*/if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));}/*** 注冊事件監聽器工廠*/if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));}return beanDefs;}

new ClassPathBeanDefinitionScanner(this);

簡言之 初始化我們的classPath類型的bean定義掃描器

/*** ClassPathBeanDefinitionScanner就是用來掃描我們classpath下的標注了@Service @Compent @Respository @Controller* 注解* @param environment 環境對象* definition profile metadata* @param resourceLoader the {@link ResourceLoader} to use* @since 4.3.6*/public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,Environment environment, @Nullable ResourceLoader resourceLoader) {Assert.notNull(registry, "BeanDefinitionRegistry must not be null");this.registry = registry;/*** 設置默認的掃描規則為true的話 默認是掃描所有的 若使用 includeFilters 來表示只包含需要設置為false*/if (useDefaultFilters) {registerDefaultFilters();}//設置環境對象setEnvironment(environment);//設置資源加載器setResourceLoader(resourceLoader);}

我們來關注下 registerDefaultFilters();

/*** 這也是為啥我們標注了@Compent @Repository @Service @Controller 能夠被識別解析* <p>Also supports Java EE 6's {@link javax.annotation.ManagedBean} and* JSR-330's {@link javax.inject.Named} annotations, if available.**/@SuppressWarnings("unchecked")protected void registerDefaultFilters() {//加入掃描我們的@Component的this.includeFilters.add(new AnnotationTypeFilter(Component.class));ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();try {//加入掃描我們的JSR250規范的this.includeFilters.add(new AnnotationTypeFilter(((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));logger.debug("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");}catch (ClassNotFoundException ex) {// JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.}try {//加入掃描我們JSR330規范的this.includeFilters.add(new AnnotationTypeFilter(((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));logger.debug("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");}catch (ClassNotFoundException ex) {// JSR-330 API not available - simply skip.}}

支持分析完了this(),接下來看看 register(annotatedClasses);


register(annotatedClasses);

看名字,也能猜到 是注冊我們的配置類的方法。

其實

public void register(Class<?>... annotatedClasses) {Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");this.reader.register(annotatedClasses);}

繼續 register

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

可以看到是支持多個配置類的,

public void registerBean(Class<?> annotatedClass) {doRegisterBean(annotatedClass, null, null, null);}

我們發現Spring真正干活的方法都是do開頭的。。。。。,所以重點關注

繼續

/*** Register a bean from the given bean class, deriving its metadata from* class-declared annotations.* * @since 5.0*/<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {return;}abd.setInstanceSupplier(instanceSupplier);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 == qualifier) {abd.setPrimary(true);}else if (Lazy.class == qualifier) {abd.setLazyInit(true);}else {abd.addQualifier(new AutowireCandidateQualifier(qualifier));}}}for (BeanDefinitionCustomizer customizer : definitionCustomizers) {customizer.customize(abd);}// 注冊自己傳入的主配置類bean定義到容器中BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);}

重點就是最后幾句 : 注冊自己傳入的主配置類bean定義到容器中

BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);

其實這個register 就是使用 AnnotatedBeanDefinitionReader實例化的過程中

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {this(registry, getOrCreateEnvironment(registry));}

生成的bean定義讀取器注冊配置類


到此為止,refresh方法之前的兩個方法就是這樣的 ,get了么…

總結

以上是生活随笔為你收集整理的Spring5源码 - 00 IOC容器创建_前期准备的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 久久久在线 | 2018av| www.爆操 | 99热91 | 天天av网 | 色噜噜狠狠狠综合曰曰曰 | 亚洲精品乱码久久久久久久 | 国产主播一区二区三区 | 超碰人人草 | 亚洲一级二级 | 亚洲制服在线观看 | 亚洲天堂女人 | 五月天激情四射 | 国产欧美日韩三区 | 欧美大片91 | 污导航在线 | 欧美最猛黑人xxxx | 清清草视频 | 亚洲一区二区三区欧美 | 伊人网在线免费观看 | 三级国产网站 | 五月婷婷,六月丁香 | 蜜桃9999| 亚洲第一天堂网 | 男人的天堂av网站 | 三年大全国语中文版免费播放 | 久操操| 雨宫琴音一区二区三区 | 天堂久久久久 | 亚洲国产福利视频 | 无码日韩人妻精品久久蜜桃 | 天海翼一区二区 | 成人深夜福利在线观看 | 91蝌蚪视频在线观看 | 超碰成人av | 国产美女菊爆在线播放APP | 国产色片在线观看 | 精品伦精品一区二区三区视频 | 国产一区二区在线视频观看 | 日韩电影一二三区 | 国产sm网站 | 中文字幕麻豆 | 国产欧美一区二区三区白浆喷水 | 一区二区三区在线 | 亚洲国产精品一区 | 久久伊| 久久大胆视频 | 综合久久一区二区 | www一区二区 | 日韩爱爱免费视频 | 欧美日韩六区 | 成人在线一区二区三区 | 短裙公车被强好爽h吃奶视频 | www.国产.com| 在线免费观看黄网站 | 丰满人妻一区二区三区精品高清 | 无遮挡aaaaa大片免费看 | 国产xxx在线 | 麻豆精品影院 | 女女调教被c哭捆绑喷水百合 | 丰满岳乱妇在线观看中字无码 | 狼人综合伊人 | 亚洲码在线观看 | 亚洲精品免费网站 | 在线中文字幕第一页 | 草草影院在线观看 | 一区二区av | 91网入口| 大香依人| 中文字幕av观看 | 日韩精品电影一区二区三区 | www.精品 | 91手机视频 | 亚洲一级片 | 国产精品亚洲五月天丁香 | 亚洲国产精品久久AV | 国产69久久 | 日本黄色一区二区 | 淫视频网站 | 中文字幕亚洲在线观看 | 很很干很很日 | 欧美亚洲色综久久精品国产 | 久久这里只有精品9 | 国产精品第五页 | www.污在线观看 | 色午夜视频 | 久久94| 国产视频久久久久 | 夜夜摸夜夜操 | 中文字幕在线视频不卡 | 激情网站在线观看 | 狠狠躁日日躁 | 人体一级片| 俄罗斯av在线 | 日韩两性视频 | 亚洲av无码一区二区乱孑伦as | 中文字幕亚洲激情 | 特黄特色大片免费播放器使用方法 | 欧美日韩性生活 |