这篇博客是对Spring(5.0.7)的ioc容器建立过程的解析,也是博主不断debug几天的成果。内容可能有点多,讲的也可能比较枯燥。不过我相信个人分析对你们理解spring容器的整个工做原理仍是有一些帮助的。php
先是调用它的无参构造函数,初始化一些信息。
无参构造函数中new
了AnnotatedBeanDefinitionReader
和ClassPathBeanDefiitionScanner
赋值给reader
context的scanner
属性。java
new
AnnotatedBeanDefinitionReader对象: 将该容器对象做为BeanDefinitionRegistry
赋值给registry
属性,而且new
了一个ConditionEvaluator
赋值给conditionEvaluator
属性。以后调用registerAnnotationConfigProcessors
方法将全部的annotation处理器注册进容器。web
这是spring对该类的描述Internal class used to evaluate {@link Conditional} annotations.
。能够看出这个类是@Conditional
注解的一个解析器。在建立该类的时候利用deduceBeanFactory
给该对象初始化了一个DefaultListableBeanFactory
,而且该类是从容器中获取的。spring
该方法先是给容器的beanFactory
初始化了private Comparator<Object> dependencyComparator;
和private AutowireCandidateResolver autowireCandidateResolver
两个属性;他们分别是用于bean的排序和解析自动注入@Autowired
的;以后便开始注册一些spring内部的bean对象: 缓存
//spring检查容器中是否注入了这些bean 没有就建立简单的含有基本信息的BeanDefiintion对象注册
// The bean name of the internally managed Configuration annotation processor.
public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalConfigurationAnnotationProcessor";
// The bean name of the internally managed Autowired annotation processor.
public static final String AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalAutowiredAnnotationProcessor";
// The bean name of the internally managed Required annotation processor.
public static final String REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalRequiredAnnotationProcessor";
// The bean name of the internally managed JSR-250 annotation processor.
public static final String COMMON_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalCommonAnnotationProcessor";
// The bean name of the internally managed JPA annotation processor.
public static final String PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalPersistenceAnnotationProcessor";
private static final String PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME =
"org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor";
// The bean name of the internally managed @EventListener annotation processor.
public static final String EVENT_LISTENER_PROCESSOR_BEAN_NAME =
"org.springframework.context.event.internalEventListenerProcessor";
// The bean name of the internally managed EventListenerFactory.
public static final String EVENT_LISTENER_FACTORY_BEAN_NAME =
"org.springframework.context.event.internalEventListenerFactory";
//注册过程以下 详见DefaultListableBeanFactory的registerBeanDefinition
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
//do some thing ....
}
}
BeanDefinition oldBeanDefinition;
// get beanDefinintion from cache
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
// if cache alredy has this beanName beanDefinition break
// some warn message or throw exception
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
// determine if create bean has started
//(判断方法很简单benaFactory中的Set<String>alreadyCreated是否已经被填充过)
if (hasBeanCreationStarted()) {
//lock beanDefinitionMap and put this beanDefinition to map
//这里有个小细节他在添加元素进beanDefinitionNames时是直接建立了一个原先cache size+1的list
//而后再将this beanDefinition name 放入list,最终改变beanDefinitionNames的为新建立list
//if this beanDefinition is in manualSingletonNames,remove from list. why?
}
else {
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (oldBeanDefinition != null || containsSingleton(beanName)) {
// 若是这个bean已经存在了单实例的对象则将其销毁
resetBeanDefinition(beanName);
}
复制代码
至此AnnotatedBeanDefinitionReaderd
对象建立完成markdown
new
ClassPathBeanDefinitionScanner对象:先是调用这个构造方法:app
registerDefaultFilters
,
setEnvironment
,
setResourceLoader
从名字咱们不难看出这是建立默认过滤器的方法;
其实是往该对象中添加了一个匹配@Component
注解的AnnotationTypeFilter。spring对该类的解释以下:
A simple filter which matches classes with a given annotation,checking inherited annotations as well.
框架
//代码以下:
this.includeFilters.add(new AnnotationTypeFilter(Component.class));
ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
try {
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
}
try {
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
}
复制代码
同样看名字咱们就能知道这是设置环境信息的。就是将以前建立AnnotatedBeanDefinitionReader
对象时获取的StandardEnvironment
设置给该对象的environment
属性。异步
该方法分别给该对象的resourcePatternResolver
,metadataReaderFactory
,componentsIndex
属性初始化。resourcePatternResolver
对象其实就是容器对象.... metadataReaderFactory
是一个从容器resourceCaches
属性拷贝过来的ConcurrentHashMap
。resourcePatternResolver
多是在加载META-INF/spring.components
这个配置文件吧。具体我也不太清楚。
至此spring容器的无参构造函数终于时调用完成了(😓)这只是简单的一步并且不少地方即便是知道了它在干什么仍是不清楚他为何这么作若是有更了解的大佬还望指教编辑器
将Config类注册进来,其实就是调用以前建立的AnnotatedBeanDefinitionReader
对象的register
方法将咱们所传入的配置类注册到容器当中。咱们能够直接看AnnotatedBeanDefinitionReader
对象的doRegisterBean
方法:
该方法先是建立了Config对象的定义信息AnnotatedGenericBeanDefinition
。以后调用如下方法shouldSkip
,resolveScopeMetadata
,generateBeanName
,processCommonDefinitionAnnotations
,applyScopedProxyMode
,registerBeanDefinition
该方法先经过isAnnotated
判断有没有@Conditional
注解若是有则判断该类是否符合注入要求。
咱们先来看下他是如何判断有没有该注解的:
首先是searchWithGetSemantics
方法来查出该类全部注解。searchWithGetSemanticsInAnnotations
来作判断。若是该注解不是java包中的注解。则判断它是不是@Conditional
注解或者任什么时候候都忽略的process。以后递归调用searchWithGetSemantics
来看元注解有没有包含@Conditional
的。如下为判断源码:
Class<? extends Annotation> currentAnnotationType = annotation.annotationType();
if (!AnnotationUtils.isInJavaLangAnnotationPackage(currentAnnotationType)) {
if (currentAnnotationType == annotationType ||
currentAnnotationType.getName().equals(annotationName) ||
processor.alwaysProcesses()) {
T result = processor.process(element, annotation, metaDepth);
if (result != null) {
if (processor.aggregates() && metaDepth == 0) {
processor.getAggregatedResults().add(result);
}
else {
return result;
}
}
}
// Repeatable annotations in container?
else if (currentAnnotationType == containerType) {
for (Annotation contained : getRawAnnotationsFromContainer(element, annotation)) {
T result = processor.process(element, contained, metaDepth);
if (result != null) {
// No need to post-process since repeatable annotations within a
// container cannot be composed annotations.
processor.getAggregatedResults().add(result);
}
}
}
}
复制代码
获取该bean的scope(这里就不细讲spring bean的做用域了不懂的自行百度),ScopeMetadata对象的值默认为singleton
,因此若是该类没有@Scope
注解默认为单例的。
获取该bean的@Component
注解标注的beanName,若是没有默认为类sortName。 获取类上的@Component
注解步骤与第一步时获取@Conditional
注解相似(递归获取注解-排除java注解)这里就不细讲了。
对@Lazy
,@Primary
,@DependsOn
,@Role
,@Description
的解析(这里提一下若是@Lazy
没有的话默认是false,以前看到有人说默认懒加载显然时不正确的~)。丰富beanDefinition。比较简单不详细分析了,贴下源码:
AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);
if (lazy != null) {
abd.setLazyInit(lazy.getBoolean("value"));
}
else if (abd.getMetadata() != metadata) {
lazy = attributesFor(abd.getMetadata(), Lazy.class);
if (lazy != null) {
abd.setLazyInit(lazy.getBoolean("value"));
}
}
if (metadata.isAnnotated(Primary.class.getName())) {
abd.setPrimary(true);
}
AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);
if (dependsOn != null) {
abd.setDependsOn(dependsOn.getStringArray("value"));
}
if (abd instanceof AbstractBeanDefinition) {
AbstractBeanDefinition absBd = (AbstractBeanDefinition) abd;
AnnotationAttributes role = attributesFor(metadata, Role.class);
if (role != null) {
absBd.setRole(role.getNumber("value").intValue());
}
AnnotationAttributes description = attributesFor(metadata, Description.class);
if (description != null) {
absBd.setDescription(description.getString("value"));
}
}
复制代码
判断是否须要建立代理对象。若是须要调用ScopedProxyCreator.createScopedProxy
方法建立。(待补全代理对象的建立过程...)
从方法名能够看出这部是真正的注册beanDefinition。真正调用的是容器中的BeanFactory(这里是DefaultListableBeanFactory
)的registerBeanDefinition
方法。首先验证beanDefinition的信息(具体我也没看懂在干什么)。以后判断该beanDefinition是否被注册过(若注册过符合条件覆盖以前的beanDefinition)。以后就是第一次注册该bean的操做(和调用无参构造函数注册过程一致详情。)
register
方法分析到这里就结束了,其实作的事情就是将配置类注册到容器当中。
refresh
是最重要的一步,进行了容器刷新以及bean建立。执行步骤比较多。
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
复制代码
进行容器的预刷新工做。这步仍是比较简单的。先是将容器置为启动状态。以后调用initPropertySources
(该方法为空方法,提供给子类的覆盖) 最后调用validateRequiredProperties
来验证是否包含一些必要参数(这里必要参数依旧为空)。
对beanFactory
进行刷新工做。先是调用refreshBeanFactory
,使用CAS判断工厂是否已经刷新(已刷新抛异常),以后给工厂bean一个序列化id, 并将工厂对象放入缓存(由序列化id映射)。最后返回工厂bean(调用容器无参构造函数建立的DefaultListableBeanFactory
对象);
进行beanFactory
的准备工做:
beanFactory
添加类加载器,表达式解析器,属性编辑器注册器, ApplicationContextAwareProcessor
。BeanFactory
,ResourceLoader
,ApplicationEventPublisher
,ApplicationContext
这些类型自动注入时的类(除beanFactory
为当前beanFactory
其他都为当前容器) 该方法时BeanFactory初始化以后再进行后续的一些BeanFactory操做。对于AnnotationConfigApplicationContext
这是父类的一个空方法。在SpringBoot建立的另外两个web容器的时候(AnnotationConfigServletWebServerApplicationContext
、AnnotationConfigReactiveWebServerApplicationContext
)会重写该方法。之后可能会出个SpringBoot原理分析系列详细会讲到这两个容器的建立及准备。
invokeBeanFactoryPostProcessors
方法比较关键。该方法作了如下步骤:
@Configuration
注解的完整配置类),主要用于注册bean。该方法主要执行了步骤:
ConfigurationClassParser
的parse方法:
@PropertySource
注解信息(以后全部的获取注解信息都是分析shouldSkip
提到的searchWithGetSemantics方法完成的),使用processPropertySource解析添加配置文件信息。处理过程大体是先建立PropertySource(建立的时候调用loadProperties读取配置文件信息)。以后将该配置文件信息添加到beanFactory的environment
bean对象中去。@ComponentScans
注解信息(若未获取到则为配置类的目录)。使用ComponentScanAnnocationParser
来解析须要注册的bean,以后调用ClassPathBeanDefinitionScanner
的doScan来将beanDefinition注册进容器。doScan作的事情就是扫包获取指定包的全部class文件并筛选有@Component
而且@Conditional
匹配的class。BeanDefinition注册过程就是以前提到的registerBeanDefinition方法。以后遍历获取到的BeanDefinitions执行parse。 操做将注册进来的Bean里的@PropertySource
,@ComponentScans
等注解的信息注册进来(递归注册)。@Import
注解解析。processImports方法来执行该操做。将全部该注解引入的类注册到容器当中。使用collectImports方法递归查找该类下全部的注解中包含的@Import
引入的对象。以后即是遍历处理操做:
ImportSelector
实现类,实例化该类。若是该类实现了Aware
接口先给该类初始化这些属性(包含BeanClassLoaderAware
,BeanFactoryAware
,EnvironmentAware
,ResourceLoaderAware
)。以后判断若是该类实现类DeferredImportSelector接口就将其放入deferredImportSelectors
后续处理。不然调用selectImports获取import对象并执行processImports递归。ImportBeanDefinitionRegistrar
实现类,和以前同样先实例化再根据Aware
初始化。最后将实例化后的类添加到带有@Import
类的ConfigurationClass
的importBeanDefinitionRegistrars
属性中以便后续操做。ConfigurationClassParser
的importStack
的imports
缓存(用于判断该类是否须要解析)。生成该类的ConfigurationClass
(带有importedBy
属性)。@ImportResource
和第一步相似这个引入的是spring的配置类。往带有该注解的ConfigurationClass
的importedResources
属性添加该retrieveBeanMethodMetadata
,解析该类全部带有@Bean
的方法将其添加到该类的ConfigurationClass。processInterfaces
,解析注入类中的全部接口中的default方法是否包含@Bean
的,若是有就建立一个BeanMethod添加到该类的ConfigurationClass以便下一步来注册该对象。这两个方法查找了全部的@Bean
Method。ConfigurationClass
放入ConfigurationClassParser
的configurationClasses属性中,为以后解析作准备。processDeferredImportSelectors
处理3中放入deferredImportSelectors
缓存中的DeferredImportSelector。调用全部的selectors的selectImports方法来获取全部导入类并封装成SourceClass
列表再去调用processImports来递归。(这么多操做实际目的就是将全部的@Import生成ConfigurationClass
或者放入importBeanDefinitionRegistrars
为以后loadBeanDefinitions作准备)ConfigurationClassBeanDefinitionReader
的loadBeanDefinitions:
ConfigurationClass
执行loadBeanDefinitionsForConfigurationClass。ConfigurationClass
是不是导入的(带有importedBy
属性),若是是将给类注册到beanFactoryConfigurationClass
带有@Bean
的方法生成beanDefinition(该定义信息除了有Lazy等属性外还有factoryBeanName和factoryMethodName)并注册到容器当中。importBeanDefinitionRegistrars
属性中调用ImportBeanDefinitionRegistrar的registerBeanDefinitions直接注册到容器中。BeanFactoryPostProcessor排序执行:
mergedBeanDefinitions
的未建立对象的定义信息。添加BeanPostProcessors:
getBean
建立处理器对象。执行顺序:
国际化配置的信息。
初始化容器的事件广播器。若是容器中没有applicationEventMulticaster
bean对象,建立一个SimpleApplicationEventMulticaster时间广播器并注册进beanFactory。
能够重写的模板方法,以添加特定于上下文的刷新工做。对于AnnotationConfigApplicationContext这是个空方法。
检查监听器bean并注册它们:
将实例化的beanDefinition进行实例化:
preInstantiateSingletons
来实例化全部的beanDefinition。
以上就是AnnotationConfigApplicationContext的建立过程。这里解析的都是基于注解的解析方式,由兴趣的小伙伴还能够看下基于xml的解析(应该只有Resource读取有所差别),以后我会本身实现一个能够扩展的简单容器(项目名字已经起好了叫seed😁),应该还会整合这个容器和netty(还在学习中...)实现一个异步的Controller层的框架,但愿个人文章能帮到你们。