Springboot启动流程分析(一):IOC容器初始化

目录

AnnotationConfigServletWebServerApplicationContext类是什么

IOC容器的组成

1 BeanFactory

2 ResourceLoader

3 AliasRegistry

4 小结

AnnotationConfigServletWebServerApplicationContext是如何实例化的

1 DefaultResourceLoader初始化

2 AbstractApplicationContext初始化

3 GenericApplicationContext初始化

3.1 beanFactory 实例化

4 GenericWebApplicationContext初始化

5 ServletWebServerApplicationContext初始化

6 AnnotationConfigServletWebServerApplicationContext初始化

6.1 初始化AnnotatedBeanDefinitionReader

6.2 初始化ClassPathBeanDefinitionScanner

结尾


我们对Springboot的启动程序想必都很熟悉:

public class BookstoreApplication {
    public static void main(String[] args) {
        SpringApplication.run(BookstoreApplication.class, args);
    }
}

可以看到,核心便是SpringApplication类中的run方法:

public ConfigurableApplicationContext run(String... args) {
        ......
        ConfigurableApplicationContext context = null;
        ......
            //1创建容器
            context = this.createApplicationContext();
            exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
            //2准备容器相关信息
            this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
            //3刷新容器,也就是通常我们说的bean的初始化
            this.refreshContext(context);
            //4完成初始化后处理
            this.afterRefresh(context, applicationArguments);
            ......
    }

通过run方法的具体代码,我们可以看到,其核心流程便是四步:

第一步,创建IOC容器

第二步,准备IOC容器相关信息

第三步,刷新IOC容器,也就是我们通常说的bean的初始化过程

第四步,刷新IOC容器完成后处理

当然从代码中,我们可以看到还有监听器,错误处理相关的内容,这些我们后续会讲到。

我们今天主要讲第一步,如何创建IOC容器。

其代码为:

context = this.createApplicationContext();

我们可以点击进去看看其具体是怎么做的:

protected ConfigurableApplicationContext createApplicationContext() {
        Class<?> contextClass = this.applicationContextClass;
        if (contextClass == null) {
            try {
                switch(this.webApplicationType) {
                case SERVLET:
                    contextClass = Class.forName("org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext");
                    break;
                case REACTIVE:
                    contextClass = Class.forName("org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext");
                    break;
                default:
                    contextClass = Class.forName("org.springframework.context.annotation.AnnotationConfigApplicationContext");
                }
            } catch (ClassNotFoundException var3) {
                throw new IllegalStateException("Unable create a default ApplicationContext, please specify an ApplicationContextClass", var3);
            }
        }

        return (ConfigurableApplicationContext)BeanUtils.instantiateClass(contextClass);
    }

可以看到,所谓的创建IOC容器就是通过全类名反射的方式,实例化了一个类:AnnotationConfigServletWebServerApplicationContext,后面的BeanUtils.instantiateClass(contextClass)其实就是通过Bean工具类对找到的类进行实例化。

那么便来到了问题的核心,AnnotationConfigServletWebServerApplicationContext类是什么,有什么作用,为什么说它就是IOC容器?

AnnotationConfigServletWebServerApplicationContext类是什么

要知道这个类是什么,我们可以先看一张UML类图:

 上面这张图就是AnnotationConfigServletWebServerApplicationContext的集成和实现的接口、类的集合,由于太过庞杂,我们挑最重要的说,也就是我们用红框框起来的三个接口:

BeanFactory
ResourceLoader
AliasRegistry

我们一个个分析,这3个接口的作用。

IOC容器的组成

1 BeanFactory

BeanFactory就是我们常说的bean工厂,这里说一句,我们这里说的BeanFactory不是实际的BeanFactory这个接口的具体作用,由于BeanFactory下面的实现类多而庞杂,无法一一列举,我们这里说的BeanFactory是虚指,表示BeanFactory极其实现接口和继承类的一系列功能。

当然如果有BeanFactory系列中比较重要的,也会列举出来。

先直接上代码,让我们对BeanFactory有一个较直观的理解:

public interface BeanFactory {
    String FACTORY_BEAN_PREFIX = "&";

    Object getBean(String var1) throws BeansException;

    <T> T getBean(String var1, Class<T> var2) throws BeansException;

    ....

    <T> ObjectProvider<T> getBeanProvider(Class<T> var1);

    <T> ObjectProvider<T> getBeanProvider(ResolvableType var1);

    .....

    String[] getAliases(String var1);
}

如果有用过Spring自带工具类的小伙伴想必对词不太陌生,我们经常会通过实现接口

ApplicationContextAware

的方式来获取IOC容器,之后再通过getBean的方法来获取容器中的指定对象。

public interface ApplicationContextAware extends Aware {
    void setApplicationContext(ApplicationContext var1) throws BeansException;
}

其中的IOC容器便是ApplicationContext,通过上面的UML类图,我们可以看到ApplicationContext 其实是同时实现了BeanFactory和ResourceLoader这个两个接口的一个组合类。

然后它的getBean方法其实就是直接来自于BeanFactory,用以从IOC容器中获取对象。

还可以看到BeanFactory还有一些其他,诸如获取Bean别名、类型的、是否单例等方法,来获取Bean的一系列信息。

我们常说BeanFactory是一个工厂,它能够通过获取getBean等方法Bean的一系列信息。那么既然是一个工厂,肯定不只是能获取Bean信息,它必然也具备创建Bean或者说实例化Bean的能力。那么BeanFactory是如何实例化Bean的呢?

针对不同的业务需求,Bean的实例化方式其实有两种,单实例和多实例,实现方式呢?充分利用了面向对象的封装原则,默认的createBean方法是单例的,如果要创建多例的,在调用单例之前设置一下bean的定义信息为prototype即可。

创建多实例Bean

通过接口AutowireCapableBeanFactory对BeanFactory继承后扩展而来:


public interface AutowireCapableBeanFactory extends BeanFactory {

    <T> T createBean(Class<T> var1) throws BeansException;

    void autowireBean(Object var1) throws BeansException;

    Object configureBean(Object var1, String var2) throws BeansException;

    Object createBean(Class<?> var1, int var2, boolean var3) throws BeansException;

    Object autowire(Class<?> var1, int var2, boolean var3) throws BeansException;

创建单实例Bean

一图胜千言,我们可以看一段继承逻辑,核心在抽象类AbstractBeanFactory上:

 可以看到AbstractBeanFactory同时实现了AliasRegistry和BeanFactory两个接口的功能,并在他们的基础上又增加了一些新功能,比如:

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
    @Nullable
    private BeanFactory parentBeanFactory;
.......

 protected abstract boolean containsBeanDefinition(String var1);

    protected abstract BeanDefinition getBeanDefinition(String var1) throws BeansException;

    protected abstract Object createBean(String var1, RootBeanDefinition var2, @Nullable Object[] var3) throws BeanCreationException;
}

很明显了,通过名字就可以看出AbstractBeanFactory多做了些什么,它通过getBeanDefinition获取Bean生成Bean必要信息,最简单的就是例如全类名之类,然后再通过createBean来实例化Bean。

前面我们说了,多实例和单实例的实例化过程其实是一样的,仅仅是多实例新值了一个属性,那么是如何实现的呢?

这里得提到另一个重要的抽象类,AbstractAutowireCapableBeanFactory

 可以看到,它在继承AbstractBeanFactory的时候,实现了其单例的createBean方法,同时也实现了AutowireCapableBeanFactory用于多例创建的createBean方法。

那么AbstractAutowireCapableBeanFactory是如何把两者集成起来的呢?直接看代码:

  public <T> T createBean(Class<T> beanClass) throws BeansException {
        RootBeanDefinition bd = new RootBeanDefinition(beanClass);
        bd.setScope("prototype");
        bd.allowCaching = ClassUtils.isCacheSafe(beanClass, this.getBeanClassLoader());
        return this.createBean(beanClass.getName(), bd, (Object[])null);
    }

  protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
        if (this.logger.isTraceEnabled()) {
            this.logger.trace("Creating instance of bean '" + beanName + "'");
        }

....

可以看到,和我们说的一样,它通过实现public <T> T createBean方法,设置多态属性后直接带调用protected Object createBean方法,实现了在复用代码的基础上,灵活的创建多/单实例的Bean。

2 ResourceLoader

要理解ResourceLoader,最简单的,直接看接口定义:

public interface ResourceLoader {
    String CLASSPATH_URL_PREFIX = "classpath:";

    Resource getResource(String var1);

    @Nullable
    ClassLoader getClassLoader();
}

可以看到,它的三个属性,基本就代表了这个类的作用:

1 String CLASSPATH_URL_PREFIX = "classpath:"是什么

classpath指的是java代码经过编译后,生成的target文件夹下的classes下的路径,具体如下

2  Resource getResource(String var1)是什么

Resource就是在基于classpath路径的基础上,classes文件夹下的真是文件路径,例如我们要取application.yml的路径,在基于classpath的基础上直接getResource("application.yml")即可。

3 ClassLoader getClassLoader()是什么

ClassLoader 就是类加载器,根据JVM的知识,我们知道,即使是对于同一个全限定类名完全相同的类,如果采用了不同的类加载器,那它就可以认为是两个完全不相等的类。

所以呢,此处获取类加载器的作用和上文获取classpath类似,获取一个统一的加载器,为后面的加载类做准备。

3 AliasRegistry

要理解AliasRegistry要和它的继承接口BeanDefinitionRegistry一起看,其实从接口名就可以看出它是做什么的,Bean定义信息注册:

public interface AliasRegistry {
    void registerAlias(String var1, String var2);
    void removeAlias(String var1);
    ......
}
public interface BeanDefinitionRegistry extends AliasRegistry {
    void registerBeanDefinition(String var1, BeanDefinition var2) throws BeanDefinitionStoreException;
    void removeBeanDefinition(String var1) throws NoSuchBeanDefinitionException;
    BeanDefinition getBeanDefinition(String var1) throws NoSuchBeanDefinitionException;
    boolean containsBeanDefinition(String var1);
    String[] getBeanDefinitionNames();
    .........
}

依旧是顾名思义,从他们的接口方法就可以看出来,无非就是注册Bean的定义信息,获取bean的定义信息之类。

4 小结

通过对上面三个类型接口的分析,我们可以大概了解到IOC容器的组成,能够看出,整个IOC其实是围绕BeanFactory来做文章的,就像工厂一样:来料加工,利用机器生产产品。IOC也是通过Bean的定义信息,利用类加载器,来生产Bean的实例。整个大略的流程基本类似,当然我们这里还没有开始进行实例化,仅仅是对IOC的整体进行概览。

AnnotationConfigServletWebServerApplicationContext是如何实例化的

通过上文的分析,我们了解了IOC的基本组成部分,同时可以看出整个IOC容器的初始化,其实就是方法createApplicationContext()调用AnnotationConfigServletWebServerApplicationContext这个类的实例化过程。

那么AnnotationConfigServletWebServerApplicationContext是如何实例化的呢?

在此之前,我们要回顾一下最开始的那张UML类图的部分内容,在此我们简单文字说明一下,整张UML类图,基本就是在继承接口信息,但是多数的接口信息仅仅是对接口功能进行了定义,其实在实例化的时候并无多少意义,除非实例化的过程中又去调用了接口的实现方法。

对于UML类图中的接口继承来说,更多的是继承其定义,以便于后面引用。

真正对初始化来说有意义的,其实是AnnotationConfigServletWebServerApplicationContext这个类的父类,及其父类的父类。

我们知道,对于Java来说,一个类的实例化,如果它有继承关系的话,它会一直向上去寻找到它的初始父类,然后初始化,然后转到下一层再初始化,一直到我们实际初始化的类:

  可以看到,是和前面的UML类图的继承类是一脉相承的,其从上往下的继承顺序为:

DefaultResourceLoader
AbstractApplicationContext
GenericApplicationContext
GenericWebApplicationContext
ServletWebServerApplicationContext
AnnotationConfigServletWebServerApplicationContext

其实严格意义上来说AbstractApplicationContext作为顶层的父类之一,还是一个抽象类,是不能够实例化的,这里更多的是一种父类信息的初始化。

换一种方式来说,其实可以认为AnnotationConfigServletWebServerApplicationContext这个类是在取得了它所有继承类的所有信息之后进行的初始化,这样就能够获取到IOC容器初始化的所有必要信息了。

而继承的方式,更多的是为了减少代码的复用,虽然这样对初始化这件事的理解会稍微麻烦点,但是总归利大于弊。

到这里,我们认为AnnotationConfigServletWebServerApplicationContext的实例化,是对上面六个从上往下依次继承类,所有信息的一次实例化。

那么其具体做了什么呢?我们按顺序,一个个来看,它们分别都做了什么。

1 DefaultResourceLoader初始化

public DefaultResourceLoader() {
        this.classLoader = ClassUtils.getDefaultClassLoader();
    }

可以看到,第一步就是获取了系统默认的类加载器。

2 AbstractApplicationContext初始化

public AbstractApplicationContext() {
        this.logger = LogFactory.getLog(this.getClass());
        this.id = ObjectUtils.identityToString(this);
        this.displayName = ObjectUtils.identityToString(this);
        this.beanFactoryPostProcessors = new ArrayList();
        this.active = new AtomicBoolean();
        this.closed = new AtomicBoolean();
        this.startupShutdownMonitor = new Object();
        this.applicationListeners = new LinkedHashSet();
        this.resourcePatternResolver = this.getResourcePatternResolver();
    }

第二步,可以看到基本都是一些信息的初始化。

3 GenericApplicationContext初始化

public GenericApplicationContext() {
        this.customClassLoader = false;
        this.refreshed = new AtomicBoolean();
        this.beanFactory = new DefaultListableBeanFactory();
    }

第三步,可以看到也是一些信息初始化,还有最重要的一点,初始化了beanFactory,这个就是用于后续创建bean的。

这里可以看到Spring框架设计很巧妙的一点,其实严格意义上来说,AnnotationConfigServletWebServerApplicationContext也是一个beanFactory,因为也实现了BeanFactory接口,那为什么要用组合的方式,来实例化一个beanFactory作为自己的属性呢?

3.1 beanFactory 实例化

为什么要选DefaultListableBeanFactory作为beanFactory呢?依旧是通过UML类图来看:

 可以看到DefaultListableBeanFactory在实现和继承AliasRegistry接口信息,能够获取bean定义信息的基础上,也实现了BeanFactory下面的一系列接口。使他能够通过bean定义信息来创建bean。

那么DefaultListableBeanFactory又是如何实力话的呢?不能单看它本身,得从它的顶层父类开始,一层层看,才知道它做了什么,通过上图的蓝色继承箭头,我们可以找到它的顶层父类SimpleAliasRegistry开始,通过它们的空参构造器,一层层往下看:

public SimpleAliasRegistry() {
    }

public DefaultSingletonBeanRegistry() {
    }

public FactoryBeanRegistrySupport() {
    }

public AbstractBeanFactory() {
    }

public AbstractAutowireCapableBeanFactory() {
        this.instantiationStrategy = new CglibSubclassingInstantiationStrategy();
        this.parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
        this.allowCircularReferences = true;
        this.allowRawInjectionDespiteWrapping = false;
        this.ignoredDependencyTypes = new HashSet();
        this.ignoredDependencyInterfaces = new HashSet();
        this.currentlyCreatedBean = new NamedThreadLocal("Currently created bean");
        this.factoryBeanInstanceCache = new ConcurrentHashMap();
        this.factoryMethodCandidateCache = new ConcurrentHashMap();
        this.filteredPropertyDescriptorsCache = new ConcurrentHashMap();
        this.ignoreDependencyInterface(BeanNameAware.class);
        this.ignoreDependencyInterface(BeanFactoryAware.class);
        this.ignoreDependencyInterface(BeanClassLoaderAware.class);
    }

public DefaultListableBeanFactory() {
    }

可以看到,除了AbstractAutowireCapableBeanFactory初始化了一系列信息,包括初始化策略,忽略依赖类型等等,再加上一个实例化当前对象。这就是beanFactory的初始化全过程。

基本就是仅仅设置了一系列初始化参数。

4 GenericWebApplicationContext初始化

public GenericWebApplicationContext() {
    }

略过。

5 ServletWebServerApplicationContext初始化

public ServletWebServerApplicationContext() {
    }

略过。

6 AnnotationConfigServletWebServerApplicationContext初始化

public AnnotationConfigServletWebServerApplicationContext() {
        this.annotatedClasses = new LinkedHashSet();
        this.reader = new AnnotatedBeanDefinitionReader(this);
        this.scanner = new ClassPathBeanDefinitionScanner(this);
    }

可以看到,初始化了beanFactory以后,最重要的工作就是初始化reader和scanner了。

在进入下一步之前,我们先看看此时的this包含了哪些内容,首先就是代表自身的实例了,根据其继承关系,它既可以是一个BeanFactory实例,也可以是一个AliasRegistry实例。

其在初始化的过程中,还通过组合的方式,添加了一些附加属性,例如ClassLoader、BeanFactory。再说直白点就是可以通过get的方式来获取ClassLoader或者DefaultListableBeanFactory生成的BeanFactory实例。

6.1 初始化AnnotatedBeanDefinitionReader

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

可以看到,在reader的实例化过程中,AnnotationConfigServletWebServerApplicationContext把自身实例化后的bean当作了BeanDefinitionRegistry(AliasRegistry的直接继承接口),作为参数传递给reader,供reader实例化。

这样肯定也没问题,毕竟上文说了AnnotationConfigServletWebServerApplicationContext既可以是BeanFactory,也可以被当作AliasRegistry。

获取环境信息Environment

在进入reader的有参构造器后,我们发现还执行了一个getOrCreateEnvironment(registry)方法,依然是把AnnotationConfigServletWebServerApplicationContext当作BeanDefinitionRegistry来用:

private static Environment getOrCreateEnvironment(BeanDefinitionRegistry registry) {
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        return (Environment)(registry instanceof EnvironmentCapable ? ((EnvironmentCapable)registry).getEnvironment() : new StandardEnvironment());
    }

简单来说就是获取Environment环境信息,为什么可以通过BeanDefinitionRegistry获取Environment呢?

依旧是在最开始的UML类图中,只不过没有标注出来:

可以看到是由于ApplicationContext继承了EnvironmentCapable接口:

public interface EnvironmentCapable {
    Environment getEnvironment();
}

 而Environment 其实我们应该也很熟悉:

public interface Environment extends PropertyResolver {
    String[] getActiveProfiles();

    String[] getDefaultProfiles();
......
}

就是获取当前的可用的ActiveProfiles的,这个在我们的yml配置很常见。

继续实例化AnnotatedBeanDefinitionReader

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
        this.beanNameGenerator = AnnotationBeanNameGenerator.INSTANCE;
        this.scopeMetadataResolver = new AnnotationScopeMetadataResolver();
        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, (ResourceLoader)null);
        AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
    }

一个个说:

beanNameGenerator,用来获取实例化的beanName。

scopeMetadataResolver,用来获取注解里面的属性,类似于value之类。

conditionEvaluator,用来评估当前的beanFactory处于什么环境:

public ConditionContextImpl(@Nullable BeanDefinitionRegistry registry, @Nullable Environment environment, @Nullable ResourceLoader resourceLoader) {
            this.registry = registry;
            this.beanFactory = this.deduceBeanFactory(registry);
            this.environment = environment != null ? environment : this.deduceEnvironment(registry);
            this.resourceLoader = resourceLoader != null ? resourceLoader : this.deduceResourceLoader(registry);
            this.classLoader = this.deduceClassLoader(resourceLoader, this.beanFactory);
        }

主要也是做的一些准备工作,其中需要注意的是

this.beanFactory = this.deduceBeanFactory(registry);

 这个获取beanFactory的方法:

private ConfigurableListableBeanFactory deduceBeanFactory(@Nullable BeanDefinitionRegistry source) {
            if (source instanceof ConfigurableListableBeanFactory) {
                return (ConfigurableListableBeanFactory)source;
            } else {
                return source instanceof ConfigurableApplicationContext ? ((ConfigurableApplicationContext)source).getBeanFactory() : null;
            }
        }

也就是说你这个被当作registry的AnnotationConfigServletWebServerApplicationContext到底是属于ConfigurableListableBeanFactory还是ConfigurableApplicationContext 。

通过前面DefaultListableBeanFactory类生成beanFactory的过程,我们可以看出,其实DefaultListableBeanFactory是实现了ConfigurableListableBeanFactory接口,而AnnotationConfigServletWebServerApplicationContext则实现了ConfigurableApplicationContext接口。

而由于DefaultListableBeanFactory类生成beanFactory作为一个属性赋予了当前参数名为register的AnnotationConfigServletWebServerApplicationContext,所以此时返回的beanFactory就是DefaultListableBeanFactory。

简单来说就是此时的beanFactory就是register里面的属性之一,要用就直接get。

那么现在reader的实例化还剩最后一步。

AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);

 

public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
        registerAnnotationConfigProcessors(registry, (Object)null);
    }

    public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source) {
        //第一步,获取beanFactory 
        DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
        //第二步,设置beanFactory的属性
        if (beanFactory != null) {
            if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
                beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
            }

            if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
                beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
            }
        }

        //第三步,在beanFactory中,注册
        Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet(8);
        RootBeanDefinition def;
        if (!registry.containsBeanDefinition("org.springframework.context.annotation.internalConfigurationAnnotationProcessor")) {
            def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, "org.springframework.context.annotation.internalConfigurationAnnotationProcessor"));
        }

        if (!registry.containsBeanDefinition("org.springframework.context.annotation.internalAutowiredAnnotationProcessor")) {
            def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, "org.springframework.context.annotation.internalAutowiredAnnotationProcessor"));
        }

        if (jsr250Present && !registry.containsBeanDefinition("org.springframework.context.annotation.internalCommonAnnotationProcessor")) {
            def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, "org.springframework.context.annotation.internalCommonAnnotationProcessor"));
        }

        if (jpaPresent && !registry.containsBeanDefinition("org.springframework.context.annotation.internalPersistenceAnnotationProcessor")) {
            def = new RootBeanDefinition();

            try {
                def.setBeanClass(ClassUtils.forName("org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor", AnnotationConfigUtils.class.getClassLoader()));
            } catch (ClassNotFoundException var6) {
                throw new IllegalStateException("Cannot load optional framework class: org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor", var6);
            }

            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, "org.springframework.context.annotation.internalPersistenceAnnotationProcessor"));
        }

        if (!registry.containsBeanDefinition("org.springframework.context.event.internalEventListenerProcessor")) {
            def = new RootBeanDefinition(EventListenerMethodProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, "org.springframework.context.event.internalEventListenerProcessor"));
        }

        if (!registry.containsBeanDefinition("org.springframework.context.event.internalEventListenerFactory")) {
            def = new RootBeanDefinition(DefaultEventListenerFactory.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, "org.springframework.context.event.internalEventListenerFactory"));
        }

        return beanDefs;
    }

对照代码,一步步分析:

 第一步,获取beanFactory:

DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
private static DefaultListableBeanFactory unwrapDefaultListableBeanFactory(BeanDefinitionRegistry registry) {
        if (registry instanceof DefaultListableBeanFactory) {
            return (DefaultListableBeanFactory)registry;
        } else {
            return registry instanceof GenericApplicationContext ? ((GenericApplicationContext)registry).getDefaultListableBeanFactory() : null;
        }
    }

可以看到,基本和上面判断获取beanFactory的方式意义,由于beanFactory是以组合的方式放在register里面,所以通过getDefaultListableBeanFactory()返回beanFactory。

第二步,设置beanFactory的属性。

if (beanFactory != null) {
            if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
                beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
            }

            if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
                beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
            }
        }

由于当前的beanFactory是DefaultListableBeanFactory实例化而来,所以这2属性都得去DefaultListableBeanFactory里面看,到底是什么,根据其初始化值我们可以判断其instanceof:

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
    ......
    @Nullable
    private Comparator<Object> dependencyComparator;
    private AutowireCandidateResolver autowireCandidateResolver = new SimpleAutowireCandidateResolver();
public DefaultListableBeanFactory() {
    }
......
public AutowireCandidateResolver getAutowireCandidateResolver() {
        return this.autowireCandidateResolver;
    }
@Nullable
    public Comparator<Object> getDependencyComparator() {
        return this.dependencyComparator;
    }

可以看到,由于DefaultListableBeanFactory是使用空参构造器实例化的,其dependencyComparator为null,而autowireCandidateResolver也是一个类型为SimpleAutowireCandidateResolver的空参实例。

可以看出,这里是给beanFactory设置两个属性,分别是依赖的优先级属性和注解的解析器。

第三步,注册bean信息

第三步代码看上去很复杂,其实主要就做了一件事:

registry.registerBeanDefinition(beanName, definition);

把bean的信息,以map的形式维护到IOC容器中。其主要实现形式便是put:

this.beanDefinitionMap.put(beanName, beanDefinition);
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap(256);

beanDefinitionMap也是当前beanFactory实例化时,初始化的一个map属性。

这里再额外说一下,那么当前状态下,放入的bean定义信息又是些什么呢?通过上面的源码我们可以看到,主要是bean工程的后置处理器接口BeanFactoryPostProcessor、bean的初始化时后置处理器接口BeanPostProcessor、监听器工厂EventListenerFactory接口的一些实现类的bean定义信息,后面我们用到了会详细讲解。这里先对这几个接口有一个直观的认识:

@FunctionalInterface
public interface BeanFactoryPostProcessor {
    void postProcessBeanFactory(ConfigurableListableBeanFactory var1) throws BeansException;
}

public interface BeanPostProcessor {
    @Nullable
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Nullable
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

public interface EventListenerFactory {
    boolean supportsMethod(Method var1);

    ApplicationListener<?> createApplicationListener(String var1, Class<?> var2, Method var3);
}

小结

通过上面的代码分析可以看到,其实reader实例化的过程,主要就是为了把一些指定的bean定义信息放入到AnnotationConfigServletWebServerApplicationContext的beanDefinitionMap中。

6.2 初始化ClassPathBeanDefinitionScanner

上面我们说到了,AnnotationConfigServletWebServerApplicationContext中的初始化主要就是reader和scanner的对象构造,上面讲完了reader,下面我们开始说scanner。

要想知道scanner是做什么的,首先我们要知到ClassPathBeanDefinitionScanner是个什么?

 EnvironmentCapable前面我们已经看过了,就是获取Environment信息的一个接口,那么Aware又是什么呢?

public interface Aware {
}

可以看到,其是一个空接口,一般通过继承它的方式来给指定类做自定义增强。

public interface ResourceLoaderAware extends Aware {
    void setResourceLoader(ResourceLoader var1);
}

通过EnvironmentCapable和ResourceLoaderAware这2个接口,我们可以看出ClassPathBeanDefinitionScanner这个类,应该是主要是关于类加载器和系统环境有关的一些信息。

通过其初始化代码,我们也能看到:

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
        this(registry, true);
    }

    public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
        this(registry, useDefaultFilters, getOrCreateEnvironment(registry));
    }

    public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters, Environment environment) {
        this(registry, useDefaultFilters, environment, registry instanceof ResourceLoader ? (ResourceLoader)registry : null);
    }

    public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters, Environment environment, @Nullable ResourceLoader resourceLoader) {
        this.beanDefinitionDefaults = new BeanDefinitionDefaults();
        this.beanNameGenerator = AnnotationBeanNameGenerator.INSTANCE;
        this.scopeMetadataResolver = new AnnotationScopeMetadataResolver();
        this.includeAnnotationConfig = true;
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        this.registry = registry;
        if (useDefaultFilters) {
            this.registerDefaultFilters();
        }
        this.setEnvironment(environment);
        this.setResourceLoader(resourceLoader);
    }

可以看到,也是把register中的信息拆分后,对ClassPathBeanDefinitionScanner进行初始化,再给其属性赋值,主要是把环境变量和类加载器一起传递过去。

结尾

可以看到,在Springboot的启动过程中,所谓的IOC容器便是由类AnnotationConfigServletWebServerApplicationContext初始化的一个实例,其中包含了bean工厂、类加载器、bean定义信息和环境变量等主要信息。

通过AnnotationConfigServletWebServerApplicationContext的初始化,IOC容器初始化了一些属性,设置了一些特定的bean定义信息。其主要的作用,还是为后续的IOC容器创建Bean做准备。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值