【深入浅出Spring原理及实战】「IOC容器初始化」彻底让你明白和理解运行原理和源码流程

news2024/9/20 1:03:06

前言介绍

本篇文章篇幅较大,希望读者可以慢慢阅读,建议收藏,分多次阅读学习。

  • 学习源码的过程当中,有几点建议:

    • 一定要学会抓重点,归纳核心类、核心方法、核心步骤;

    • 分析源码我们不需要太过于纠结细节,不然,这个源码最起码得分析月才能分析完

    • 主要的目的是分析整个容器初始化过程,怎么初始化bean,怎么设置动态代理;我们主要学习的是他们的思想,以及代码中运用到的设计模式

容器框架重要对象

  • BeanFactory:用于访问容器中bean的接口,使用的是工厂模式,重点注意DefaultListableBeanFactory,是贯穿的整个容器的基本工厂类。

  • BeanDefinition:BeanDefinition是bean在Spring中的描述,先读取到bean的各种元素,然后利用BeanDefinition去初始化bean,是spring从起管理bean对象的数据模型。

  • BeanDefinitionRegistry接口:注册bean定义到Spring容器中,与BeanFactory接口相对应,主要针对于Bean的注册,BeanFactory主要针对于bean对象的管理。

  • BeanFactoryPostProcessor接口:bean工厂后置处理器,该接口的作用主要是提供扩展点,用于各种bean定义的注册和实例化等,比较需要主要关注ConfigurationClassPostProcessor该类;

  • BeanPostProcessor接口:bean的后置处理器,该接口提供的扩展点,用于初始化bean,以及初始化完成后的各种扩展

IOC容器初始化的大致流程

  • 首先读取BeanDefinition放到容器中。

  • 通过BeanFactoryPostProcessor对象的扩展

  • 通过BeanPostProcessor对象的扩展

  • 然后根据BeanDefinition去初始化bean。

  • 最后实际进行初始化然后保存到容器中。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F8UZI0au-1670237214913)(https://oscimg.oschina.net/oscnet/up-4cea9217e477504a4eb3aa35c17f7ea6731.png)]

来实现各种不同的功能;IOC容器初始化大致的一个流程,主要是看AnnotationConfigApplicationContextrefresh

AnnotationConfigApplicationContext构造器分析

传入配置类的构造函数

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
    //初始化容器,创建bean工厂,加载各种内部重要类的bean定义,用于初始化我们或者其他引入类
    this();
    //注册我们配置类的bean定义,初始化容器,从这个类开始
    register(componentClasses);
    //准备工作做好后,开始初始化容器
    refresh();
}

先看下this()这一行代码

AnnotatedBeanDefinitionReader:主要用于读取相关内部的Spring容器的Bean对象。

public AnnotationConfigApplicationContext() {
    //初始化读取bean定义的读取器,完成Spring内部bean定义的注册
    this.reader = new AnnotatedBeanDefinitionReader(this);
    //初始化一个类扫描器,其实这个方法进来,是没有用到这个扫描器的
    this.scanner = new ClassPathBeanDefinitionScanner(this);
}

从上面创建bean定义读取器,看下构造方法

//从上面创建bean定义读取器,看下构造方法
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
    this(registry, getOrCreateEnvironment(registry));
}

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    Assert.notNull(environment, "Environment must not be null");
    //把ApplicationContext对象赋值给bean定义读取器
    this.registry = registry;
    this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
    //主要是看这个方法,注册Spring内部重要的bean定义
    AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}

到这里this(),这个方法流程就过完了,主要就是注册spring内部重要的bean定义,来看下register(componentClasses)方法

//此目的主要针对于上面注册的reader进行注册相关的bean
public void register(Class<?>... annotatedClasses) {
    Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
    //使用上面初始化的bean定义读取器,去注册我们配置类的bean定义
    this.reader.register(annotatedClasses);
}
//遍历去注册传入进来的注解相关的Bean对象
public void register(Class<?>... annotatedClasses) {
    for (Class<?> annotatedClass : annotatedClasses) {
        registerBean(annotatedClass);
    }
}
// 
public void registerBean(Class<?> annotatedClass) {
    doRegisterBean(annotatedClass, null, null, null);
}
//注册bean定义
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
        @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
        @Nullable BeanDefinitionCustomizer[] customizers) {
    //根据配置类创建一个bean定义
    AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
    if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
        return;
    }
    abd.setInstanceSupplier(supplier);
    //解析bean的作用域,如果没有设置,则默认是单例
    ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
    abd.setScope(scopeMetadata.getScopeName());
	// 创建bean对象的bean名称
    String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
    //解析该bean是否有Lazy,Primary,DependsOn,Description等注解,有则填充进去
    AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
    if (qualifiers != null) {
        for (Class<? extends Annotation> qualifier : qualifiers) {
			//判断是否是Primary
            if (Primary.class == qualifier) {
                abd.setPrimary(true);
            }
			// 判断是否属于懒惰加载
            else if (Lazy.class == qualifier) {
                abd.setLazyInit(true);
            }
            else {
                abd.addQualifier(new AutowireCandidateQualifier(qualifier));
            }
        }
    }
    if (customizers != null) {
        for (BeanDefinitionCustomizer customizer : customizers) {
            customizer.customize(abd);
        }
    }
	// 构建BeanDefinitionHolder对象去引用对象
    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
    definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
    //最后把该bean定义注册到Bean工厂中去
    BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}

register(componentClasses),方法到此结束,然后我们分析refresh();方法,该方法初始化了IOC容器。

public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        //设置容器状态,准备刷新容器
        prepareRefresh();
        //获取到容器的bean工厂
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
        //填充bean工厂的各种属性
        prepareBeanFactory(beanFactory);
        try {
            //留给子类实现,我们看的AnnotationConfigApplicationContext继承了GenericApplicationContext,该类主要是注册了ServletContextAwareProcessor
            postProcessBeanFactory(beanFactory);
            //主要调用bean工厂的后置处理器,把我们的类,注册成bean定义
            invokeBeanFactoryPostProcessors(beanFactory);
			  // 注册 BeanPostProcessor 的实现类
         // 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
         // 两个方法分别在 Bean 初始化之前和初始化之后得到执行。注意,到这里 Bean 还没初始化
            registerBeanPostProcessors(beanFactory);
            //初始化国际化资源(这个方法不重要)
            initMessageSource();
            //Spring事件相关,主要是创建一个事件多播器
            initApplicationEventMulticaster();
            //留给子类实现
            onRefresh();
            //把我们的事件注册到容器中
            registerListeners();
            //实例化我们需要的bean,放入IOC容器
            finishBeanFactoryInitialization(beanFactory);
            //完成容器IOC容器初始化,并且发布初始化完成事件
            finishRefresh();
        }
        catch (BeansException ex) {
            if (logger.isWarnEnabled()) {
                logger.warn("Exception encountered during context initialization - " +
                        "cancelling refresh attempt: " + ex);
            }
            destroyBeans();
            cancelRefresh(ex);
            throw ex;
        }
        finally {
            resetCommonCaches();
        }
    }
}

分析主要的步骤

  1. 首先 prepareRefresh():方法主要是为容器设置一个状态(准备工作,记录下容器的启动时间、标记“已启动”状态、处理配置文件中的占位符)
  2. 然后接下来是获取相应的工厂类,AnnotationConfigApplicationContext主要是获取到DefaultListableBeanFactory,但是如果是XML方式,会在该方法去加载bean定义,我们不分析这种方式
    • 这步比较关键,这步完成后,配置文件/配置类就会解析成一个Bean定义,注册到 BeanFactory 中,
    • 这里说的Bean还没有初始化,只是配置信息都提取出来了,
    • 注册也只是将这些信息都保存到了注册中心(说到底核心是一个 beanName-> beanDefinition 的 map)
prepareRefresh() 创建容器前的准备工作
protected void prepareRefresh() {
   // 记录启动时间,
   // 将 active 属性设置为 true,closed 属性设置为 false,它们都是 AtomicBoolean 类型
   this.startupDate = System.currentTimeMillis();
   this.closed.set(false);
   this.active.set(true);
   if (logger.isInfoEnabled()) {
      logger.info("Refreshing " + this);
   }
   // Initialize any placeholder property sources in the context environment
   initPropertySources();
   // 校验 xml 配置文件
   getEnvironment().validateRequiredProperties();
   this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}

obtainFreshBeanFactory() 创建 Bean 容器,加载并注册 Bean
IoC初始化里面最重要的部分。

关键是以下几步:

  • 初始化BeanFactory
  • 加载Bean
  • 注册Bean

注意:这步完成后,Bean 并没有完成初始化,实际的实例并没有被创建。

AbstractApplicationContext#obtainFreshBeanFactory()

   protected ConfigurableListableBeanFactory obtainFreshBeanFactory(){
        // 关闭旧的 BeanFactory (如果有),创建新的 BeanFactory,加载 Bean 定义、注册 Bean 等等
        refreshBeanFactory();
        // 返回上一步刚刚创建的BeanFactory
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        if (logger.isDebugEnabled()) {
            logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
        }
        return beanFactory;
    }

AbstractRefreshableApplicationContext#refreshBeanFactory()

protected final void refreshBeanFactory() throws BeansException {
        // 如果 ApplicationContext 已经加载过 BeanFactory,销毁所有的Bean,关闭BeanFactory
        // 注意点:应用中BeanFactory是可以有多个的,这里可不是说全局是否有BeanFactory
        // 而是说当前的ApplicationContext有没有BeanFactory!
        if (hasBeanFactory()) {
            destroyBeans();
            closeBeanFactory();
        }
        try {
            // 初始化一个 DefaultListableBeanFactory
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            // 用于 BeanFactory 的序列化,一般人应该用不到吧...
            beanFactory.setSerializationId(getId());
            // 下面是两个重点方法
            // 设置 BeanFactory 的两个重要属性
            // 是否允许 Bean 覆盖、是否允许循环引用
            customizeBeanFactory(beanFactory);
            // 加载BeanDefinition到BeanFactory  单独拉出来讲
            loadBeanDefinitions(beanFactory);
            synchronized (this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        }
        catch (IOException ex) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
        }
   }

可以感觉到一个设计思路,ApplicationContext 继承自 BeanFactory,但是它不应该被理解为 BeanFactory 的实现类,而是说其内部持有一个实例化的 BeanFactory(DefaultListableBeanFactory)。以后所有的 BeanFactory 相关的操作其实是委托给这个实例来处理的。

customizeBeanFactory

    protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
        if (this.allowBeanDefinitionOverriding != null) {
            beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
        }
        if (this.allowCircularReferences != null) {
            beanFactory.setAllowCircularReferences(this.allowCircularReferences);
        }
    }

BeanDefinition 的覆盖问题可能会有开发者碰到这个坑,就是在配置文件中定义 bean 时使用了相同的 id 或 name。

默认情况下,allowBeanDefinitionOverriding 属性为 null(Boolean类型),如果在同一配置文件中重复了,会抛错,但是如果不是同一配置文件中,会发生覆盖

  • 循环引用也很好理解:A 依赖 B,而 B 依赖 A。或 A 依赖 B,B 依赖 C,而 C 依赖 A。

  • 默认情况下,Spring 允许循环依赖,当然如果你在 A 的构造方法中依赖 B,在 B 的构造方法中依赖 A 是不行的

loadBeanDefinitions(beanFactory) 加载BeanDefinition

    /**
     * Load bean definitions into the given bean factory, typically through
     * delegating to one or more bean definition readers.
     * @param beanFactory the bean factory to load bean definitions into
     * @throws BeansException if parsing of the bean definitions failed
     * @throws IOException if loading of bean definition files failed
     * @see org.springframework.beans.factory.support.PropertiesBeanDefinitionReader
     * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
     */
    protected abstract void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)
            throws BeansException, IOException;

ClassPathXmlApplicationContext 是按照解析XML的加载方式。看javadoc的描述,是通过XmlBeanDefinitionReader来载入Bean Definitions。

    /**
     * Loads the bean definitions via an XmlBeanDefinitionReader.
     * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
     * @see #initBeanDefinitionReader
     * @see #loadBeanDefinitions
     */
    @Override
    protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
        // Create a new XmlBeanDefinitionReader for the given BeanFactory.
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
        // Configure the bean definition reader with this context's
        // resource loading environment.
        beanDefinitionReader.setEnvironment(this.getEnvironment());
        beanDefinitionReader.setResourceLoader(this);
        beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
        // Allow a subclass to provide custom initialization of the reader,
        // 初始化Reader 不重要,看下这个方法的javadoc就很好理解了
        initBeanDefinitionReader(beanDefinitionReader);
        // 真正重要的步骤!!
        // 用Reader去加载XML配置
        loadBeanDefinitions(beanDefinitionReader);
    }

loadBeanDefinitions(beanDefinitionReader)

    /**
     * Load the bean definitions with the given XmlBeanDefinitionReader.
     * 看这句注释:this method is just supposed to load and/or register bean definitions.
     */
    protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
        Resource[] configResources = getConfigResources();
        if (configResources != null) {
            reader.loadBeanDefinitions(configResources);
        }
        String[] configLocations = getConfigLocations();
        if (configLocations != null) {
            // 这个分支,通过路径名去获取Resource,会和上面的方法殊途同归
            reader.loadBeanDefinitions(configLocations);
        }
    }

AbstractBeanDefinitionReader#loadBeanDefinitions(Resource… resources)

    @Override
    public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
        Assert.notNull(resources, "Resource array must not be null");
        int counter = 0;
        for (Resource resource : resources) {
            // 遍历解析XML文件,加载 BeanDefinition
            counter += loadBeanDefinitions(resource);
        }
        return counter;
    }

接下去的源码不细讲,这里载入分为两大步,

  1. 就是通过调用XML的解析器获取到 document 对象,完成通用XML解析;

  2. 就是按照Spring的Bean规则进行解析

    • Spring的Bean规则进行解析这个过程是BeanDefinitionDocumentReader来实现的,里面包含了各种Spring Bean定义规则的处理。

    • 这里我觉得核心知识点就是Spring Bean规则的解析,简单点来说,里面包含了我们在XML配置的那些信息,怎么解析成容器中 BeanDefinition的规则和步骤。这部分由于和主要流程关系不大。

    • 在这因为Spring 的 Bean配置方式有很多,解析配置信息到BeanDefinition的实现方式也有很多,XML又是现在少用的方式,所以关于XML中的Spring Bean规则的解析的详细源码就先略过了。

我们来看下prepareBeanFactory(beanFactory)这个方法

设置 BeanFactory的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    //设置类加载器,为当前应用的application的类加载器
    beanFactory.setBeanClassLoader(getClassLoader());
    //为bean工厂设置一个标准的SPEL表达式解析器
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    //为bean工厂设置一个资源编辑器,为了后面bean初始化时,给bean对象赋值
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
    //忽略以下接口的bean,这些bean都有set方法,不会对这些bean进行属性赋值
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
    beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
    beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
    beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
    //注册了工厂实例,如果我们在程序中注入BeanFactory,就是从这里注册的获取到的
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);
    //注册事件监听器的bean后置处理接口
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
    //处理AOP的后置处理器
    if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }
    //注册bean工厂的环境属性
    if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
    }
}

接下来分析postProcessBeanFactory(beanFactory);

  • 这里需要知道BeanFactoryPostProcessor 这个知识点,Bean 如果实现了此接口, 那么在容器初始化以后,Spring 会负责调用里面的 postProcessBeanFactory 方法

    • 提供给子类的扩展点,到这里的时候,所有的Bean都加载、注册完成了,但是都还没有初始化。

    • 具体的子类可以在这步的时候添加一些特殊的 BeanFactoryPostProcessor 的实现类或做点什么事。

    • 该方法没有做实际的事情,主要是把ServletContextAwareProcessor后置处理器,给注册进去。

    • 实现ServletContextAware接口获取上下文容器,就是从这里注入的。


protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    if (this.servletContext != null) {
        beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext));
        beanFactory.ignoreDependencyInterface(ServletContextAware.class);
    }
    WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
    WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext);
}

接下来分析invokeBeanFactoryPostProcessors(beanFactory);

调用BeanFactoryPostProcessor实现类 postProcessBeanFactory(factory) 方法

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    //获取FactoryPostProcessors,Spring内置的和自己设置的,然后供接下来的调用
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
    if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }
}

public static void invokeBeanFactoryPostProcessors(
        ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
    //放入已经被处理过的bean
    Set<String> processedBeans = new HashSet<>();
    //当前bean工厂是否实现了BeanDefinitionRegistry,如果有的话,则可以注册bean定义
    if (beanFactory instanceof BeanDefinitionRegistry) {
        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
        List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
        List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
        //循环我们传入的bean工厂后置处理器,并加入到处理器集合中
        for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
            if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                BeanDefinitionRegistryPostProcessor registryProcessor =
                        (BeanDefinitionRegistryPostProcessor) postProcessor;
                registryProcessor.postProcessBeanDefinitionRegistry(registry);
                registryProcessors.add(registryProcessor);
            }
            else {
                regularPostProcessors.add(postProcessor);
            }
        }
        //保存当前实例化的BeanDefinitionRegistryPostProcessor
        List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
        //从bean工厂中获取到继承了BeanDefinitionRegistryPostProcessor的bean
        String[] postProcessorNames =
              beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        for (String ppName : postProcessorNames) {
            //实例化优先级最高的BeanDefinitionRegistryPostProcessor
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                //实例化出BeanDefinitionRegistryPostProcessor的类,我们正常初始化这里只有ConfigurationClassPostProcessor
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                processedBeans.add(ppName);
            }
        }
        //对实例化出来的BeanDefinitionRegistryPostProcessor进行排序
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        //把实例化出来的BeanDefinitionRegistryPostProcessor添加进总的集合中供后面调用
        registryProcessors.addAll(currentRegistryProcessors);
        //调用刚实例化出来的bean,注册bean定义
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
        //清空调用后的BeanDefinitionRegistryPostProcessor
        currentRegistryProcessors.clear();

        postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        for (String ppName : postProcessorNames) {
            //实例化实现了Ordered接口的BeanDefinitionRegistryPostProcessor
            if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                processedBeans.add(ppName);
            }
        }
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        registryProcessors.addAll(currentRegistryProcessors);
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
        currentRegistryProcessors.clear();
        //调用没有实现任何优先级接口的BeanDefinitionRegistryPostProcessor
        boolean reiterate = true;
        while (reiterate) {
            reiterate = false;
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                if (!processedBeans.contains(ppName)) {
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                    reiterate = true;
                }
            }
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            currentRegistryProcessors.clear();
        }
        //调用 BeanDefinitionRegistryPostProcessor.postProcessBeanFactory方法
        invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
        //调用自己实现的BeanDefinitionRegistryPostProcessor.postProcessBeanFactory方法
        invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
    }
    else {
        //没有实现BeanDefinitionRegistry接口的bean工厂,直接调用invokeBeanFactoryPostProcessors
        invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
    }
    //调用所有的BeanDefinitionRegistryPostProcessor完毕
    //获取容器中所有的 BeanFactoryPostProcessor
    String[] postProcessorNames =
            beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
    //执行所有BeanFactoryPostProcessor.postProcessBeanFactory方法,按照order接口排序
    List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    List<String> orderedPostProcessorNames = new ArrayList<>();
    List<String> nonOrderedPostProcessorNames = new ArrayList<>();
    for (String ppName : postProcessorNames) {
        if (processedBeans.contains(ppName)) {
        }
        else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
        }
        else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            orderedPostProcessorNames.add(ppName);
        }
        else {
            nonOrderedPostProcessorNames.add(ppName);
        }
    }

    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

    List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
    for (String postProcessorName : orderedPostProcessorNames) {
        orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    sortPostProcessors(orderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

    List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
    for (String postProcessorName : nonOrderedPostProcessorNames) {
        nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
    //执行完成所有BeanFactoryPostProcessor.postProcessBeanFactory方法,清除所有缓存信息
    beanFactory.clearMetadataCache();
}
//我们接下来主要是看ConfigurationClassPostProcessor调用postProcessBeanDefinitionRegistry方法
private static void invokeBeanDefinitionRegistryPostProcessors(
        Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
    for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
        postProcessor.postProcessBeanDefinitionRegistry(registry);
    }
}

接下来主要针对于,ConfigurationClassParser类进行解析操作处理

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
    int registryId = System.identityHashCode(registry);
    if (this.registriesPostProcessed.contains(registryId)) {
        throw new IllegalStateException(
                "postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
    }
    if (this.factoriesPostProcessed.contains(registryId)) {
        throw new IllegalStateException(
                "postProcessBeanFactory already called on this post-processor against " + registry);
    }
    this.registriesPostProcessed.add(registryId);
    processConfigBeanDefinitions(registry);
}

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
    List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
    String[] candidateNames = registry.getBeanDefinitionNames();
    //循环最开始初始化的所有bean定义
    for (String beanName : candidateNames) {
        BeanDefinition beanDef = registry.getBeanDefinition(beanName);
        //对配置类(带有@Configuration标签)进行标记,后续实例化时有用
        if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
            if (logger.isDebugEnable()) {
                logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
            }
        }
        //进行标记,添加到配置类,候选集合中
        else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
            configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
        }
    }
    if (configCandidates.isEmpty()) {
        return;
    }
    //对所有配置类进行排序
    configCandidates.sort((bd1, bd2) -> {
        int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
        int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
        return Integer.compare(i1, i2);
    });
    // 创建我们通过@ComponentScan导入进来的bean name的生成器
    // 创建我们通过@Import导入进来的bean的名称
    SingletonBeanRegistry sbr = null;
    if (registry instanceof SingletonBeanRegistry) {
        sbr = (SingletonBeanRegistry) registry;
        if (!this.localBeanNameGeneratorSet) {
            BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
                    AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
            if (generator != null) {
                this.componentScanBeanNameGenerator = generator;
                this.importBeanNameGenerator = generator;
            }
        }
    }
    if (this.environment == null) {
        this.environment = new StandardEnvironment();
    }
    //创建一个类解析器
    ConfigurationClassParser parser = new ConfigurationClassParser(
            this.metadataReaderFactory, this.problemReporter, this.environment,
            this.resourceLoader, this.componentScanBeanNameGenerator, registry);

    Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
    Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
    do {
        /**解析配置类,包括@Component、@ComponentScans等需要扫描的类,都会被解析出来放入bean定义容器
         *@Configuration配置类为full配置类,其他的为lite配置类
         **/
        parser.parse(candidates);
        parser.validate();
        //获取到解析出来的配置类
        Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
        configClasses.removeAll(alreadyParsed);
        if (this.reader == null) {
            this.reader = new ConfigurationClassBeanDefinitionReader(
                    registry, this.sourceExtractor, this.resourceLoader, this.environment,
                    this.importBeanNameGenerator, parser.getImportRegistry());
        }
        //把所有@Import、@Bean解析出来的bean定义放入容器
        this.reader.loadBeanDefinitions(configClasses);
        alreadyParsed.addAll(configClasses);
        candidates.clear();
        if (registry.getBeanDefinitionCount() > candidateNames.length) {
            String[] newCandidateNames = registry.getBeanDefinitionNames();
            Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
            Set<String> alreadyParsedClasses = new HashSet<>();
            for (ConfigurationClass configurationClass : alreadyParsed) {
                alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
            }
            for (String candidateName : newCandidateNames) {
                if (!oldCandidateNames.contains(candidateName)) {
                    BeanDefinition bd = registry.getBeanDefinition(candidateName);
                    if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
                            !alreadyParsedClasses.contains(bd.getBeanClassName())) {
                        candidates.add(new BeanDefinitionHolder(bd, candidateName));
                    }
                }
            }
            candidateNames = newCandidateNames;
        }
    }
    while (!candidates.isEmpty());
    if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
        sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
    }
    if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
        ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
    }
}
//我们再来看看ConfigurationClassPostProcessor.invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    int factoryId = System.identityHashCode(beanFactory);
    if (this.factoriesPostProcessed.contains(factoryId)) {
        throw new IllegalStateException(
                "postProcessBeanFactory already called on this post-processor against " + beanFactory);
    }
    this.factoriesPostProcessed.add(factoryId);
    if (!this.registriesPostProcessed.contains(factoryId)) {
        processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
    }
    //这里会修改@Configuration配置类的bean定义,到时候实例化bean时,会使用CGLIB创建动态代理,@Bean中调用获取的bean都是容器中的bean,其他配置类的bean,获取的都是new出来的
    enhanceConfigurationClasses(beanFactory);
    beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}

讲了bean定义的加载过程,现在我们来讲一下bean的实例化过程,bean的实例化,主要是finishBeanFactoryInitialization(beanFactory);这个方法

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    //bean工厂创建转化器
    if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
            beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
        beanFactory.setConversionService(
                beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
    }
    if (!beanFactory.hasEmbeddedValueResolver()) {
        beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
    }
    //实例化AOP相关的组件
    String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
    for (String weaverAwareName : weaverAwareNames) {
        //调用工厂实例化方法,这个方法我们后面来分析
        getBean(weaverAwareName);
    }
    beanFactory.setTempClassLoader(null);
    //冻结所有bean定义,在实例化时,不允许再修改bean定义
    beanFactory.freezeConfiguration();
    //实例化所有bean
    beanFactory.preInstantiateSingletons();
}

Spring IOC容器bean的实例化,到这基本就完成了,这次所有源代码的分析把重要的地方,大致流程都讲了一遍,但是有很多细节没有讲到,整体属于框架总体深入流程原理介绍。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/64945.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MongoDB 存储引擎

简单回顾 上次我们说到了关于 mongodb 的集群&#xff0c;分为主从集群和分片集群&#xff0c;对于分片集群中的分片这里需要注意如下几点&#xff0c;一起来回顾一下&#xff1a; 对于热点数据某些分片键&#xff08;分片键是集合中每个文档中存在的索引字段或复合索引字段&a…

qt历史数据管理模块(模块化程序)功能块复制直接使用不冲突

一、前言 qt对历史数据管理部分个人总结的模块化程序&#xff0c;直接按照步骤复制粘贴程序&#xff0c;直接实现历史数据管理功能&#xff0c;无需花费脑筋在理清各个思路&#xff0c;适合快速编写组装程序 二、环境 windows qt5.7 sqlite3 三、正文 建议参照前文&…

【uni-app】uni-app之云开发uniCloud跨全栈开发笔记总结,包括一个 schema自动生成代码小案例(附详细截图)

1- 前言 本文主要讲解如何使用uni-app 和 uniCloud 云开发&#xff0c;实现小案例&#xff0c;不需要后端&#xff0c;来实现全栈开发。 2- 概念 2.1 什么是uni-app uni-app 是一个使用Vue.js开发所有前端应用的框架&#xff0c;开发者编写一套代码&#xff0c;可发布到iOS、…

对信息系统生命周期各阶段进行风险评估的要点汇总

概述 风险评估应贯穿于评估对象生命周期 各阶段中。评估对象生命周期各阶段中涉及的风险评估原则和方法昆一致的&#xff0c;但由干各阶段实施内容对象、安全需求不同.使得风险评估的对象、目的、要求等各方面也有所不同。在规划设计阶段&#xff0c;通过风险评估以确定评估对…

pytorch笔记(九)转置卷积、膨胀卷积

Transposed Convolution (转置卷积) 别名:Fractionally Strided Convolution (小数步长的卷积)、Deconvolution(逆/反卷积) 作用:upsampling(上采样) 模拟: PS:不是恢复原始值(因为一般情况下矩阵不可逆,无法等式左右两边同乘矩阵的逆得到原始矩阵) 转置卷积的…

为什么分布式系统这么火?

做Java的升职空间有限&#xff0c;可以说如果不想一辈子做程序员&#xff0c;只能往其他方向进行拓展&#xff0c;比如做到产品经理之类的或者技术总监。 可如果还是想做和技术相关的职业&#xff0c;那么架构师是很好的一步。 可是要如何做一名优秀的架构师呢&#xff1f; …

每天五分钟机器学习:经典的机器学习PCA的核心——特征分解技术

本节重点 本节我们将学习特征分解,特征分解是矩阵分析中非常重要的概念,它也可以应用到PCA算法中,本节先讲解什么是特征分解,然后讲解特征分解在PCA算法中的应用。 数学知识准备 如上所示是方差的定义,方差是度量一组数据的分散程度 如上所示是方差的定义,协方差是…

BSP板机支持包、linux启动分析、ARM裸机编程

文章目录一、BSP二、驱动驱动的基本要素三、启动分析1.uboot2.uboot的作用3.uboot相关命令关键的内容&#xff1a;1&#xff09;bootargs&#xff0c;启动参数2&#xff09;启动命令3&#xff09;修改启动延时时间4&#xff09;复位开发板5&#xff09;修改本地IP地址6&#xf…

Matlab群体智能优化算法之大鲹鱼优化算法(GTO)

Giant Trevally Optimizer : A Novel Metaheuristic Algorithm for Global Optimization and Challenging 一、灵感来源二、算法的初始化三、GTO的数学模型  Phase1&#xff1a;广泛搜索  Phase2&#xff1a;选择区域  Phase3&#xff1a;攻击四、流程图五、伪代码六、实…

[附源码]计算机毕业设计四川景区管理系统Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

SWT Table列自适应大小

要实现列自适应大小首先需要保证Table根据窗口拖动而改变大小。 Window中提供setShellStyle可以设置外壳样式。 构造一个新的自定义器对话框&#xff0c;在构造函数中添加setShellStyle(getShellStyle() | SWT.RESIZE);即可改变自定义对话框大小&#xff0c;如&#xff1a; ge…

[附源码]Python计算机毕业设计SSM教师教学质量评价系统(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

数据卷(Data Volumes)dockerfile

目录一、宿主机与容器之间的文件拷贝1、利用MySQL镜像安装MySQL服务2、从容器中拷贝文件到宿主机3、从宿主机拷贝文件到容器二、数据卷三、数据卷容器四、Dockerfile1、自定义centos&#xff0c;具备vim及ifconfig作用2、自定义tomcat8一、宿主机与容器之间的文件拷贝 1、利用…

Linux虚拟化网络之vlan配置

问题描述&#xff1a; Linux主机划分两个vlan&#xff0c;服务器server1的物理网卡的IP地址为1.1.1.1/24&#xff0c;服务器server2的物理网卡的IP地址为1.1.1.2/24。物理网卡下要虚拟化出来两个Vlan子接口&#xff0c;vlan10中主机的IP地址分别为10.10.10.1/24和10.10.10.2/2…

99%的人都把三层架构和SpringMVC的关系搞错了

99%的人都把三层架构和SpringMVC的关系搞错了&#xff01;&#xff01;&#xff01; 先说结论&#xff0c; 三层架构和SpringMVC的关系就是没有关系。 很多人之前把SpringMVC中的M-Model当作三层架构中的servicedao&#xff08;包括我&#xff09;&#xff0c;这个是一个错误…

前端知识粉碎机

diff算法 Dep的作用是收集观察者以及当数据发生变动时通知观察者去更新。 Dep.notify()通知观察者去更新。 当数据改变时&#xff0c;就会触发setter&#xff0c;然后触发Dep.notify&#xff0c;通知订阅者&#xff0c;比对新旧虚拟节点&#xff0c;判断是否是同类标签&#xf…

Emlog博客文章图片自动加水印插件

内容目录一、详细介绍二、效果展示1.部分代码2.效果图展示三、学习资料下载一、详细介绍 给Emlog博客的上传图片添加水印可以有效地保护作品版权&#xff0c;有效地打击那些转载文件不留原作者地址的垃圾网站&#xff0c;部分Emlog博主通常都是手动给图片添加水印&#xff0c;…

MySQL学习记录(7)SQL优化

3. SQL优化 3.1、插入数据 3.1.1 insert 如果我们需要一次性往数据库表中插入多条记录&#xff0c;可以从以下三个方面进行优化 insert into tb_test values(1,tom); insert into tb_test values(2,cat); insert into tb_test values(3,jerry); .....&#xff08;1&#xf…

cartgrapher ukf 代码清晰属实不错

文章目录原理UKFSigma and weightUKF AlgorithmUT/UKF/EKF Summarycato_code外围函数检测是否为对称矩阵矩阵的开方根高斯分布UKF 代码实现类预测观测更新点评原理 UKF KF 系列求解&#xff1a; Kalman filter 需要线性模型EKF通过泰勒展开线性化更好的方式线性化 -> Unsc…

【OpenCV学习】第6课:图像模糊(中值滤波,高斯双边滤波)

仅自学做笔记用,后续有错误会更改 理论 中值滤波&#xff1a;对核内数值先进行排序&#xff0c;再取中间那个值 注1&#xff1a;中值滤波属于统计学的排序滤波器 注2&#xff1a;中值滤波对椒盐噪声有很好的抑制作用 高斯双边滤波(美颜磨皮效果一般都是用的这个)&#xff1a…