Spring中的AnnotationConfigApplicationContex深度解析

    技术2024-06-23  73

    BeanFactory和ApplicationContext的作用和区别

    BeanFactory负责读取bean配置文档,管理bean的加载,实例化,维护bean之间的依赖关心,负责bean的生命周期ApplicationContext继承BeanFactory,除了BeanFactory所提供的功能之外,还提供了更完整的框架功能

    AnnotationConfigApplicationContex

    AnnotationConfigApplicationContex的类图

    基于注解

    package com.mayikt.v3; import com.mayikt.v3.config.MySpringConfig; import org.springframework.context.annotation.AnnotationConfigApplicationContext; /** * @Description: * @Author: ChenYi * @Date: 2020/07/02 23:16 **/ public class Test03 { private static AnnotationConfigApplicationContext annotationConfigApplicationContext; public static void main(String[] args) { //基于注解创建上下文对象 annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MySpringConfig.class); } } public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) { //里面会先调用父类的GenericApplicationContext无参构造函数创建一个new DefaultListableBeanFactory()对象 this(); //注意这里只是把注解的配置类注入ioc容器中,其他的对象在这个方法中是还没有开始注入的 register(annotatedClasses); refresh(); } GenericApplicationContext的无参构造函数 public GenericApplicationContext() { this.beanFactory = new DefaultListableBeanFactory(); }

    Register方法的执行流程

    BeanDefinition是定义 Bean 的配置元信息接口,类图

    把注解的配置类放到ioc容器中 <T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) { //注解的方式注入ioc中bean的信息 AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass); //判断是否有加Condition注解,有条件的注入对象 if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) { return; } //设置回调 abd.setInstanceSupplier(instanceSupplier); ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd); //设置是否单例还是多例 abd.setScope(scopeMetadata.getScopeName()); //获取beanId 没有的话就使用类的小写 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); } //把AnnotatedGenericBeanDefinition封装成一个对象 BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); //把注解方式的配置类注册到ioc容器中 BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry); }

    流程图

    基于扫包

    package com.mayikt.v3; import org.springframework.context.annotation.AnnotationConfigApplicationContext; /** * @Description: * @Author: ChenYi * @Date: 2020/07/02 23:16 **/ public class Test03 { private static AnnotationConfigApplicationContext annotationConfigApplicationContext; public static void main(String[] args) { //基于扫包创建上下文对象 annotationConfigApplicationContext = new AnnotationConfigApplicationContext("com.mayikt.v2"); } } public AnnotationConfigApplicationContext(String... basePackages) { //里面会先调用父类的GenericApplicationContext无参构造函数创建一个new DefaultListableBeanFactory()对象 this(); //基于扫包的注入对象的方法 scan(basePackages); refresh(); }

    Spring的父子容器

    子容器可以访问父容器中bean,父容器无法访问子容器中的beanBeanFactory接口支撑层次查找ListableBeanFactory接口不支持层次查找BeanFactoryUtils工具类中提供了一些非常使用的方法,比如支持bean层次查找的方法等等通常我们使用的spirngmvc的时候,采用3层结构,controller层、service层、dao层,父容器中会包含dao层和service层,而子容器中包含的只有controller层,这2个容器组成了父子容器的关系,controller层通常会注入service层的bean,采用父子容器可以避免有些人在service层去注入controller层的bean,导致整个依赖层次比较混乱的 参考:蚂蚁课堂
    Processed: 0.011, SQL: 9