目录
AnnotationConfigServletWebServerApplicationContext类是什么
AnnotationConfigServletWebServerApplicationContext是如何实例化的
2 AbstractApplicationContext初始化
3 GenericApplicationContext初始化
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容器?
要知道这个类是什么,我们可以先看一张UML类图:
上面这张图就是AnnotationConfigServletWebServerApplicationContext的集成和实现的接口、类的集合,由于太过庞杂,我们挑最重要的说,也就是我们用红框框起来的三个接口:
BeanFactory
ResourceLoader
AliasRegistry
我们一个个分析,这3个接口的作用。
BeanFactory就是我们常说的bean工厂,这里说一句,我们这里说的BeanFactory不是实际的BeanFactory这个接口的具体作用,由于BeanFactory下面的实现类多而庞杂,无法一一列举,我们这里说的BeanFactory是虚指,表示BeanFactory极其实现接口和继承类的一系列功能。
当然如果有BeanFactory系列中比较重要的,也会列举出来。
先直接上代码,让我们对BeanFactory有一个较直观的理解:
- public interface BeanFactory {
- String FACTORY_BEAN_PREFIX = "&";
-
- Object getBean(String var1) throws BeansException;
-
-
T getBean(String var1, Class var2) throws BeansException; -
- ....
-
-
ObjectProvider getBeanProvider(Class var1) ; -
-
ObjectProvider 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 createBean(Class 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 createBean(Class 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
要理解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类似,获取一个统一的加载器,为后面的加载类做准备。
要理解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的定义信息之类。
通过对上面三个类型接口的分析,我们可以大概了解到IOC容器的组成,能够看出,整个IOC其实是围绕BeanFactory来做文章的,就像工厂一样:来料加工,利用机器生产产品。IOC也是通过Bean的定义信息,利用类加载器,来生产Bean的实例。整个大略的流程基本类似,当然我们这里还没有开始进行实例化,仅仅是对IOC的整体进行概览。
通过上文的分析,我们了解了IOC的基本组成部分,同时可以看出整个IOC容器的初始化,其实就是方法createApplicationContext()调用AnnotationConfigServletWebServerApplicationContext这个类的实例化过程。
那么AnnotationConfigServletWebServerApplicationContext是如何实例化的呢?
在此之前,我们要回顾一下最开始的那张UML类图的部分内容,在此我们简单文字说明一下,整张UML类图,基本就是在继承接口信息,但是多数的接口信息仅仅是对接口功能进行了定义,其实在实例化的时候并无多少意义,除非实例化的过程中又去调用了接口的实现方法。
对于UML类图中的接口继承来说,更多的是继承其定义,以便于后面引用。
真正对初始化来说有意义的,其实是AnnotationConfigServletWebServerApplicationContext这个类的父类,及其父类的父类。
我们知道,对于Java来说,一个类的实例化,如果它有继承关系的话,它会一直向上去寻找到它的初始父类,然后初始化,然后转到下一层再初始化,一直到我们实际初始化的类:
可以看到,是和前面的UML类图的继承类是一脉相承的,其从上往下的继承顺序为:
DefaultResourceLoader
AbstractApplicationContext
GenericApplicationContext
GenericWebApplicationContext
ServletWebServerApplicationContext
AnnotationConfigServletWebServerApplicationContext
其实严格意义上来说AbstractApplicationContext作为顶层的父类之一,还是一个抽象类,是不能够实例化的,这里更多的是一种父类信息的初始化。
换一种方式来说,其实可以认为AnnotationConfigServletWebServerApplicationContext这个类是在取得了它所有继承类的所有信息之后进行的初始化,这样就能够获取到IOC容器初始化的所有必要信息了。
而继承的方式,更多的是为了减少代码的复用,虽然这样对初始化这件事的理解会稍微麻烦点,但是总归利大于弊。
到这里,我们认为AnnotationConfigServletWebServerApplicationContext的实例化,是对上面六个从上往下依次继承类,所有信息的一次实例化。
那么其具体做了什么呢?我们按顺序,一个个来看,它们分别都做了什么。
- public DefaultResourceLoader() {
- this.classLoader = ClassUtils.getDefaultClassLoader();
- }
可以看到,第一步就是获取了系统默认的类加载器。
- 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();
- }
第二步,可以看到基本都是一些信息的初始化。
- public GenericApplicationContext() {
- this.customClassLoader = false;
- this.refreshed = new AtomicBoolean();
- this.beanFactory = new DefaultListableBeanFactory();
- }
第三步,可以看到也是一些信息初始化,还有最重要的一点,初始化了beanFactory,这个就是用于后续创建bean的。
这里可以看到Spring框架设计很巧妙的一点,其实严格意义上来说,AnnotationConfigServletWebServerApplicationContext也是一个beanFactory,因为也实现了BeanFactory接口,那为什么要用组合的方式,来实例化一个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的初始化全过程。
基本就是仅仅设置了一系列初始化参数。
- public GenericWebApplicationContext() {
- }
略过。
- public ServletWebServerApplicationContext() {
- }
略过。
- 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实例。
- 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
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
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
- private AutowireCandidateResolver autowireCandidateResolver = new SimpleAutowireCandidateResolver();
- public DefaultListableBeanFactory() {
- }
- ......
- public AutowireCandidateResolver getAutowireCandidateResolver() {
- return this.autowireCandidateResolver;
- }
- @Nullable
- public Comparator
- 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
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中。
上面我们说到了,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做准备。