• Spring5源码分析之AnnotationConfigApplicationContext


    前言: 主要了解的内容有如下几点:

    • @Qualifier与@Primary注解的使用
    • Spring中ApplicationContext的作用
    • BeanFactory与ApplicationContext区别
    • AnnotationConfigApplicationContext启动原理分析

    假设 IUser两个实现类UserImpl1 和 UserImpl2

    1. @Autowired + @Qualifier("UserImpl1") 可以指定使用哪个实现类。 也可以 @Resource("UserImpl1 ")

    2. @Primary是指定加载谁,用在实现类上。指定。

    图解:

     ApplicationContext:也就是上下文

      1. AnnotationConfigApplicationContext

      2. ClassPathXmlApplicationContext

    ApplicationContext 继承BeanFactory 实现扩展功能

    小结: 

     @Configuration 相当于XML配置

    注解方式启动,需要配置config,通过构造函数去加载config的配置信息

    看下这个构造函数:

    注意先执行父类的无参构造函数 再执行 子类的无参构造函数,无参构造函数如下:

     

    有父类的: 多态! 先执行父类的无参构造!

    父类的无参构造函数:

    可以看出:创建了个beanFactory

    然后走子类的无参构造函数:

    第一个: 基于 注解方式

    第二个: xml扫包方式

    1走完了,继续2:

     看下reader:

     比如我们可以直接使用:

    接着看2 : register()

    继续看 register:

    进行for循环遍历,多个注解情况

    继续查看

    查看该方法:注解情况的核心代码

    public void registerBean(Class<?> annotatedClass, String name, Class... qualifiers) {

    // 基于注解的类: 作用是 AnnotatedGenericBeanDefinition abd
    = new AnnotatedGenericBeanDefinition(annotatedClass); if (!this.conditionEvaluator.shouldSkip(abd.getMetadata())) { 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) { Class[] var7 = qualifiers; int var8 = qualifiers.length; for(int var9 = 0; var9 < var8; ++var9) { Class<? extends Annotation> qualifier = var7[var9]; if (Primary.class == qualifier) { abd.setPrimary(true); } else if (Lazy.class == 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); } }

    传统的用: RootBeanDefinition 传统表示注入Bean对象

     用注解的形式的话: AnnotatedGenericBeanDefinition 

     

     也是继承到了 BeanDefinition

     也可以推理出 AnnotatedGenericBeanDefinition  表示为封装注解方式启动注入配置类。 注解方式启动的配置注入IOC Bean信息

    根据条件注入Bean,Condition条件注入

    设置回调

    判断启动类上是否有Scope作用域,默认是单例的。设置作用域scope

    beanName的默认和设置,没有就生成一个

    调用了工具类

    工具类要做的是: 读取配置类上面的 注解信息 比如有没有加上 @DependsOn 加载顺序  @Role 角色分类  @Primary  等

    最终会在:registerBean方法中new  

    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);

    通过AnnotatedGenericBeanDefinition 封装注解的启动类

       DefinitionHolder 包装了 这个类: AnnotatedGenericBeanDefinition 

     然后通过工具类进行注册:

     然后进行注册:

    
    

    画图整理:

  • 相关阅读:
    牛客多校(2020第三场)C Operation Love
    牛客多校(2020第三场)C Operation Love
    牛客多校(2020第三场)B Classical String Problem
    牛客多校(2020第三场)B Classical String Problem
    牛客多校(2020第三场)L Problem L is the Only Lovely Problem
    牛客多校(2020第三场)L Problem L is the Only Lovely Problem
    一个图形或者控件旋转时 判断方向逆时针还是顺时针
    为什么 dll 改名字之后无法使用
    C# 几个特殊运算符的理解和Nullable<T> 的研究
    再次深入 C# Attribute
  • 原文地址:https://www.cnblogs.com/toov5/p/11223463.html
Copyright © 2020-2023  润新知