目录
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容器?
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做准备。