spring IoC 容器的加载过程

1.实例化容器:	AnnotationConfigApplicationContext
  1. 实例化工厂: DefauiltListableBeanFactory
  2. 实例化创建BeanDefinition 读取其: AnnotatedBeanDefinitionReader
  3. 创建BeanDefinition 扫描器: ClassPathBeanDefinitionScanner
  4. 注册配置类为BeanDefinition :register(annotatedClasses)
  5. refresh()
  6. invokeBeanFactoryPostProcessors(beanFactory)
  7. finishBeanFactoryInitialization(beanFactory)

AnnotationConfigApplicationContext

1.1 spring boot 实例化 ApplicationContext

	在 springBootApplication 启动进入 SpringApplication 类

public ConfigurableApplicationContext run(String... args) {
// 创建 ApplicationContext
context = this.createApplicationContext();
}

跟踪该方法:使用applicationContextFactory 创建 一个ApplicationContext

protected ConfigurableApplicationContext createApplicationContext() {
return this.applicationContextFactory.create(this.webApplicationType);
}

继续跟踪进入 ApplicationContextFactory 类,该类会根据项目的webApplicationType 创建不同的ApplicationContext 。

@FunctionalInterface
public interface ApplicationContextFactory {
ApplicationContextFactory DEFAULT = (webApplicationType) -> {
try {
switch(webApplicationType) {
case SERVLET:
return new AnnotationConfigServletWebServerApplicationContext();
case REACTIVE:
return new AnnotationConfigReactiveWebServerApplicationContext();
default:
return new AnnotationConfigApplicationContext();
}
} catch (Exception var2) {
throw new IllegalStateException("Unable create a default ApplicationContext instance, you may need a custom ApplicationContextFactory", var2);
}
}; ConfigurableApplicationContext create(WebApplicationType webApplicationType);
}

根据 ApplicationContextFactory 可知,springboot 会默认创建一个AnnotationConfigApplicationContext 的spring 容器。

这里解析AnnotationConfigApplicationContext 类的Ioc容器加载过程。

1.2 进入AnnotationConfigApplicationContext 类

1.1 中会根据webApplicationType创建一个对应的无参构造的AnnotationConfigApplicationContext实例对象:

public AnnotationConfigApplicationContext() {
StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");
// 进行初始化
this.reader = new AnnotatedBeanDefinitionReader(this);
createAnnotatedBeanDefReader.end();
this.scanner = new ClassPathBeanDefinitionScanner(this);
} 在实例化AnnotationConfigApplicationContext 对象时,会先调用父类GenericApplicationContext的构造函数。父类的构造函数里面就是初始化DefaultListableBeanFactory,并且赋值给beanFactory 。 public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
private final DefaultListableBeanFactory beanFactory;
@Nullable
private ResourceLoader resourceLoader;
private boolean customClassLoader;
private final AtomicBoolean refreshed; public GenericApplicationContext() {
// 实例化工厂:DefaultListableBeanFactory
// DefaultListableBeanFactory是相当重要的,用来生产 和获得Bean的。
this.beanFactory = new DefaultListableBeanFactory();
}
} 本类的构造函数里面,初始化了一个读取器:AnnotatedBeanDefinitionReader read,一个扫描器ClassPathBeanDefinitionScanner scanner。scanner的用处不是很大,它仅仅是在我们外部手动调用 .scan 等方法才有用,常规方式是不会用到scanner对象的。 让我们看看Spring在初始化 AnnotatedBeanDefinitionReader的时候做了什么: public class AnnotatedBeanDefinitionReader {
private final BeanDefinitionRegistry registry;
private BeanNameGenerator beanNameGenerator;
private ScopeMetadataResolver scopeMetadataResolver;
private ConditionEvaluator conditionEvaluator;
// 在AnnotationConfigApplicationContext 初始化 AnnotatedBeanDefinitionReader进入该构造方法,registry 为 在AnnotationConfigApplicationContext的实例
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
// 调用该类的其他构造方法
this(registry, getOrCreateEnvironment(registry));
} 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);
}
} 其中registerAnnotationConfigProcessors 会注册spring 内置的多个bean 。跟踪该方法,贴出最核心的代码: public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source) {
if (!registry.containsBeanDefinition("org.springframework.context.annotation.internalConfigurationAnnotationProcessor")) {
def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
// registerPostProcessor 注册Bean
beanDefs.add(registerPostProcessor(registry, def, "org.springframework.context.annotation.internalConfigurationAnnotationProcessor"));
} }
  1. 判断容器中是否已经存在了ConfigurationClassPostProcessor Bean

  2. 如果不存在(当然这里肯定是不存在的),就通过RootBeanDefinition的构造方法获得

ConfigurationClassPostProcessor的BeanDefinition,RootBeanDefinition是BeanDefinition的子类

  1. 执行registerPostProcessor方法,registerPostProcessor方法内部就是注册Bean,当然这里注册

其他Bean也是一样的流程。

BeanDefinition它是用来描述Bean的,里面存放着关于Bean的一系列信息,比如Bean的作用域,Bean所对应的Class,是 否懒加载,是否Primary等等,这个BeanDefinition也相当重要,我们以后会常常和它打交道。

	继续追踪registerPostProcessor 方法,注册bean 

private static BeanDefinitionHolder registerPostProcessor(BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
definition.setRole(2);
registry.registerBeanDefinition(beanName, definition);
return new BeanDefinitionHolder(definition, beanName);
}

继续追踪registerBeanDefinition 方法,其中的核心实现是DefaultListableBeanFactory

//beanDefinitionMap是Map<String, BeanDefinition>,
//这里就是把beanName作为key,ScopedProxyMode作为value,推到map里面 this.beanDefinitionMap.put(beanName, beanDefinition);
//beanDefinitionNames就是一个List<String>,这里就是把beanName放到List中去 this.beanDefinitionNames.add(beanName);

从这里可以看出DefaultListableBeanFactory就是我们所说的容器了,里面放着beanDefinitionMap,**

beanDefinitionNames,beanDefinitionMap是一个hashMap,beanName作为Key,beanDefinition作

为Value,beanDefinitionNames是一个集合,里面存放了beanName。

	ConfigurationClassPostProcessor实现BeanDefinitionRegistryPostProcessor接口,

BeanDefinitionRegistryPostProcessor接口又扩展了BeanFactoryPostProcessor接口,

BeanFactoryPostProcessor是Spring的扩展点之一,ConfigurationClassPostProcessor是Spring极

为重要的一个类

4.创建BeanDefinition扫描器:ClassPathBeanDefinitionScanner

由于常规使用方式是不会用到AnnotationConfigApplicationContext里面的scanner的,这里的scanner

仅仅是为了程序员可以手动调用AnnotationConfigApplicationContext对象的scan方法。所以这里就不看

scanner是如何被实例化的了。

5.注册配置类为BeanDefinition: register(annotatedClasses);

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
this.register(componentClasses);
this.refresh();
}

一直跟踪 register 方法:

AnnotationConfigApplicationContext. register(Class<?>... componentClasses)

------>AnnotatedBeanDefinitionReader.register(Class<?>... componentClasses)

------>AnnotatedBeanDefinitionReader.registerBean(Class<?> beanClass)

------->AnnotatedBeanDefinitionReader.doRegisterBean

查看doRegisterBean 方法的实现

  private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier, @Nullable BeanDefinitionCustomizer[] customizers) {
//AnnotatedGenericBeanDefinition可以理解为一种数据结构,是用来描述Bean的,这里的作用就是把传入的标记了注解 的类
//转为AnnotatedGenericBeanDefinition数据结构,里面有一个getMetadata方法,可以拿到类上的注解
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
//判断是否需要跳过注解,spring中有一个@Condition注解,当不满足条件,这个bean就不会被解析
if (!this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
abd.setInstanceSupplier(supplier);
//解析bean的作用域,如果没有设置的话,默认为单例
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
String beanName = name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry);
//解析通用注解,填充到AnnotatedGenericBeanDefinition,解析的注解为Lazy,Primary,DependsOn,Role,Descri ption
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
int var10;
int var11;
if (qualifiers != null) {
Class[] var9 = qualifiers;
var10 = qualifiers.length; for(var11 = 0; var11 < var10; ++var11) {
Class<? extends Annotation> qualifier = var9[var11];
//Primary注解优先
if (Primary.class == qualifier) {
abd.setPrimary(true);
//Lazy注解
} else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
} else {
//其他,AnnotatedGenericBeanDefinition有个Map<String,AutowireCandidateQualifier>属性,直接push进去
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
} BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
//注册,最终会调用DefaultListableBeanFactory中的registerBeanDefinition方法去注册,
//DefaultListableBeanFactory维护着一系列信息,比如beanDefinitionNames,beanDefinitionMap
//beanDefinitionNames是一个List<String>,用来保存beanName
//beanDefinitionMap是一个Map,用来保存beanName和beanDefinition
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
}

重点跟踪 BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry)**该方法,该方法最终实现bean 的注册。

最终会调用DefaultListableBeanFactory中的registerBeanDefinition方法去注册:

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {

	BeanDefinition existingDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
// 是否对已存在的bean 进行重写
if (!this.isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
} else {
// 如果注册的bean 不存在,则进行注册
if (this.hasBeanCreationStarted()) {
synchronized(this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
this.removeManualSingletonName(beanName);
}
} else {
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.removeManualSingletonName(beanName);
} this.frozenBeanDefinitionNames = null;
} }

到这里注册配置类也分析完毕了。

  1. refresh()

大家可以看到其实到这里,Spring还没有进行扫描,只是实例化了一个工厂,注册了一些内置的Bean和我

们传进去的配置类,真正的大头是在第三行代码

    public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
this.register(componentClasses);
this.refresh();
}

这个方法做了很多事情,让我们点开这个方法:

 public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
//刷新预处理,和主流程关系不大,就是保存了容器的启动时间,启动标志等
this.prepareRefresh();
//和主流程关系也不大,最终获得了DefaultListableBeanFactory,
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
//还是一些准备工作,添加了两个后置处理器:ApplicationContextAwareProcessor,ApplicationListenerDetector
//还设置了 忽略自动装配 和 允许自动装配 的接口,如果不存在某个bean的时候,spring就自动注册singleton bean
//还设置了bean表达式解析器 等
this.prepareBeanFactory(beanFactory); try {
//这是一个空方法,用于扩展
this.postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process"); //执行自定义的 BeanFactoryProcessor 和内置的 BeanFactoryProcessor
this.invokeBeanFactoryPostProcessors(beanFactory);
// 注册BeanPostProcessor
this.registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
this.initMessageSource();
this.initApplicationEventMulticaster();
// 空方法
this.onRefresh();
this.registerListeners();
// 实例化所有剩余的(非懒加载)单例
this.finishBeanFactoryInitialization(beanFactory);
this.finishRefresh();
} catch (BeansException var10) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var10);
} this.destroyBeans();
this.cancelRefresh(var10);
throw var10;
} finally {
this.resetCommonCaches();
contextRefresh.end();
} }
}

6.1 跟踪prepareBeanFactory 方法,该方法用于添加一些解析器和自动装配的配置,比较重要

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
beanFactory.setBeanClassLoader(this.getClassLoader());
if (!shouldIgnoreSpel) {
//设置bean表达式解析器
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
}
//属性编辑器支持
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, this.getEnvironment()));
//添加一个后置处理器:ApplicationContextAwareProcessor,此后置处理处理器实现了BeanPostProcessor接口
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.ignoreDependencyInterface(ApplicationStartup.class);
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
if (!IN_NATIVE_IMAGE && beanFactory.containsBean("loadTimeWeaver")) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
} if (!beanFactory.containsLocalBean("environment")) {
beanFactory.registerSingleton("environment", this.getEnvironment());
} if (!beanFactory.containsLocalBean("systemProperties")) {
beanFactory.registerSingleton("systemProperties", this.getEnvironment().getSystemProperties());
} if (!beanFactory.containsLocalBean("systemEnvironment")) {
beanFactory.registerSingleton("systemEnvironment", this.getEnvironment().getSystemEnvironment());
} if (!beanFactory.containsLocalBean("applicationStartup")) {
beanFactory.registerSingleton("applicationStartup", this.getApplicationStartup());
} }

以上方法做的主要操作如下:

  1. 设置了一个类加载器

  2. 设置了bean表达式解析器

  3. 添加了属性编辑器的支持

  4. 添加了一个后置处理器:ApplicationContextAwareProcessor,此后置处理器实现了BeanPostProcessor接口

  5. 设置了一些忽略自动装配的接口

  6. 设置了一些允许自动装配的接口,并且进行了赋值操作

  7. 在容器中还没有XX的bean的时候,帮我们注册beanName为XX的singleton bean

6.2 invokeBeanFactoryPostProcessors该方法也比较重要,执行自定义的BeanFactoryProcessor和内置的BeanFactoryProcessor 。其体现了spring 的可扩展性及热插拔属性。该方法会查找实现了BeanFactoryPostProcessor的后置处理器,并且执行后置处理器中的方法。

	查看ConfigurationClassPostProcessor中对BeanDefinitionRegistryPostProcessor。postProcessBeanDefinitionRegistry方法的实现

    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
// 生成一个注册的Id
int registryId = System.identityHashCode(registry);
// 判断是否已注册
if (this.registriesPostProcessed.contains(registryId)) {
throw new IllegalStateException("postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
} else if (this.factoriesPostProcessed.contains(registryId)) {
throw new IllegalStateException("postProcessBeanFactory already called on this post-processor against " + registry);
} else {
// 没有注册则进行注册
this.registriesPostProcessed.add(registryId);
this.processConfigBeanDefinitions(registry);
}
}

继续跟踪processConfigBeanDefinitions(registry)方法,并解析该方法的实现逻辑

	该方法主要用于解析带有 @Configuration 的每一个注解类: 

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList();
//获得所有的BeanDefinition的Name
String[] candidateNames = registry.getBeanDefinitionNames();
String[] var4 = candidateNames;
int var5 = candidateNames.length; for(int var6 = 0; var6 < var5; ++var6) {
String beanName = var4[var6];
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
if (this.logger.isDebugEnabled()) {
this.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()) {
//处理排序
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
});
SingletonBeanRegistry sbr = null;
// DefaultListableBeanFactory最终会实现SingletonBeanRegistry接口,所以可以进入到这个if
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry)registry;
if (!this.localBeanNameGeneratorSet) {
BeanNameGenerator generator = (BeanNameGenerator)sbr.getSingleton("org.springframework.context.annotation.internalConfigurationBeanNameGenerator");
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);
HashSet alreadyParsed = new HashSet(configCandidates.size()); do {
StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
//解析配置类(传统意义上的配置类或者是普通bean,核心来了)
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 @ImportRosource 转换 成BeanDefinition
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
processConfig.tag("classCount", () -> {
return String.valueOf(configClasses.size());
}).end();
candidates.clear();
//获得注册器里面BeanDefinition的数量 和 candidateNames进行比较
//如果大于的话,说明有新的BeanDefinition注册进来了
if (registry.getBeanDefinitionCount() > candidateNames.length) {
String[] newCandidateNames = registry.getBeanDefinitionNames();
Set<String> oldCandidateNames = new HashSet(Arrays.asList(candidateNames));
Set<String> alreadyParsedClasses = new HashSet();
Iterator var13 = alreadyParsed.iterator();
} while(!candidates.isEmpty()); }
}

该方法中的ConfigurationClassUtils.checkConfigurationClassCandidate 这个方法会对添加有Full 与Lite 两个标记位的注解进行解析判断:

当我们注册配置类的时候,可以不加Configuration注解,直接使用Component ComponentScan Import ImportResou rce注解,称之为Lite配置类 。 

如果加了Configuration注解,就称之为Full配置类。

重点跟踪上面方法中的parser.parse(candidates) 方法,一直点击进去直到 ConfigurationClassParser 。doProcessConfigurationClass 方法

@Nullable
protected final ConfigurationClassParser.SourceClass doProcessConfigurationClass(ConfigurationClass configClass, ConfigurationClassParser.SourceClass sourceClass, Predicate<String> filter) throws IOException {
//递归处理内部类,一般不会写内部类
this.processMemberClasses(configClass, sourceClass, filter); //处理@PropertySource注解,@PropertySource注解用来加载properties文件
Iterator var4 = AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), PropertySources.class, PropertySource.class).iterator(); AnnotationAttributes importResource;
while(var4.hasNext()) {
importResource = (AnnotationAttributes)var4.next();
if (this.environment instanceof ConfigurableEnvironment) {
this.processPropertySource(importResource);
} else {
this.logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() + "]. Reason: Environment must implement ConfigurableEnvironment");
}
} //获得ComponentScan注解具体的内容,ComponentScan注解除了最常用的basePackage之外,还有includeFilters,excludeFilters等
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
//如果没有打上ComponentScan,或者被@Condition条件跳过,就不再进入这个if
if (!componentScans.isEmpty() && !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
Iterator var14 = componentScans.iterator();
//循环处理componentScans
while(var14.hasNext()) {
AnnotationAttributes componentScan = (AnnotationAttributes)var14.next();
Set<BeanDefinitionHolder> scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
Iterator var8 = scannedBeanDefinitions.iterator(); while(var8.hasNext()) {
BeanDefinitionHolder holder = (BeanDefinitionHolder)var8.next();
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
} if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
this.parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
} //处理@Import注解
//@Import注解是spring中很重要的一个注解,Springboot大量应用这个注解
//@Import三种类,一种是Import普通类,一种是Import ImportSelector,还有一种是Import ImportBeanDefinitionR egistrar
this.processImports(configClass, sourceClass, this.getImports(sourceClass), filter, true);
importResource = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
if (importResource != null) {
String[] resources = importResource.getStringArray("locations");
Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
String[] var20 = resources;
int var22 = resources.length; for(int var23 = 0; var23 < var22; ++var23) {
String resource = var20[var23];
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
configClass.addImportedResource(resolvedResource, readerClass);
}
}
//处理@Bean的方法,可以看到获得了带有@Bean的方法后,不是马上转换成BeanDefinition,而是先用一个set接收
Set<MethodMetadata> beanMethods = this.retrieveBeanMethodMetadata(sourceClass);
Iterator var18 = beanMethods.iterator(); while(var18.hasNext()) {
MethodMetadata methodMetadata = (MethodMetadata)var18.next();
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
} this.processInterfaces(configClass, sourceClass);
if (sourceClass.getMetadata().hasSuperClass()) {
String superclass = sourceClass.getMetadata().getSuperClassName();
if (superclass != null && !superclass.startsWith("java") && !this.knownSuperclasses.containsKey(superclass)) {
this.knownSuperclasses.put(superclass, configClass);
return sourceClass.getSuperClass();
}
} return null;
}

实现的逻辑顺序:

  1. 递归处理内部类,一般不会使用内部类。

  2. 处理@PropertySource注解,@PropertySource注解用来加载properties文件。

  3. 获得ComponentScan注解具体的内容,ComponentScan注解除了最常用的basePackage之外,还有includeFilters,

excludeFilters等。

  1. 判断有没有被@ComponentScans标记,或者被@Condition条件带过,如果满足条件的话,进入if,进行如下操作:

    4.1 执行扫描操作,把扫描出来的放入set,这个方法稍后再详细说明。

    4.2 循环set,判断是否是配置类,是的话,递归调用parse方法,因为被扫描出来的类,还是一个配置类,有@ComponentScans注解,

或者其中有被@Bean标记的方法 等等,所以需要再次被解析。

  1. 处理@Import注解,@Import是Spring中很重要的一个注解,正是由于它的存在,让Spring非常灵活,不管是Spring内部,还 是与Spring整合的第三方技术,都大量的运用了@Import注解,@Import有三种情况,一种是Import普通类,一种是ImportSelector,还有一种是Import ImportBeanDefinitionRegistrar,getImports(sourceClass)是获得import的内容,返回的 是一个set。

  2. 处理@ImportResource注解。

  3. 处理@Bean的方法,可以看到获得了带有@Bean的方法后,不是马上转换成BeanDefinition,而是先用一个set接收。

6.6-registerBeanPostProcessors(beanFactory);

实例化和注册beanFactory中扩展了BeanPostProcessor的bean。

例如:

AutowiredAnnotationBeanPostProcessor(处理被@Autowired注解修饰的bean并注入)

RequiredAnnotationBeanPostProcessor(处理被@Required注解修饰的方法)

CommonAnnotationBeanPostProcessor(处理@PreDestroy、@PostConstruct、@Resource等多个注解的作用)等。

6-11-finishBeanFactoryInitialization(beanFactory);

实例化所有剩余的(非懒加载)单例

比如invokeBeanFactoryPostProcessors方法中根据各种注解解析出来的类,在这个时候都会被初始化。

实例化的过程各种BeanPostProcessor开始起作用。

finishBeanFactoryInitialization(beanFactory);

这个方法是用来实例化懒加载单例Bean的,也就是我们的Bean都是在这里被创建出来的

一直跟踪该方法,该方法也非常重要:

finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory)

----〉 AbstractApplicationContext.getBean(String name)

------> 直到AbstractBeanFactory。doGetBean (AbstractBeanFactory也是核心类,非常重要)

if (mbd.isSingleton()) {
sharedInstance = this.getSingleton(beanName, () -> {
try {
return this.createBean(beanName, mbd, args);
} catch (BeansException var5) {
this.destroySingleton(beanName);
throw var5;
}
});
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
bean = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);

继续跟踪其中的createBean 方法直到doCreateBean 方法。

// 1.创建bean的实例。核心
instanceWrapper = createBeanInstance(beanName, mbd, args);
// 2。填充属性
populateBean(beanName, mbd, instanceWrapper);//填充属性,炒鸡重要
// 3.进行aware系列接口的回调,并进行初始化方法
exposedObject = initializeBean(beanName, exposedObject, mbd);
// 4. 执行BeanPostProcessor的postProcessBeforeInitialization方法
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
//5. afterPropertiesSet init-method位于initializeBean中的
invokeInitMethods(beanName, wrappedBean, mbd);

Spring Bean的生命周期

  1. 实例化Bean对象,这个时候Bean的对象是非常低级的,基本不能够被我们使用,因为连最基本的属性都没有设置,可以理解为 连Autowired注解都是没有解析的;

  2. 填充属性,当做完这一步,Bean对象基本是完整的了,可以理解为Autowired注解已经解析完毕,依赖注入完成了;

  3. 如果Bean实现了BeanNameAware接口,则调用setBeanName方法;

  4. 如果Bean实现了BeanClassLoaderAware接口,则调用setBeanClassLoader方法;

  5. 如果Bean实现了BeanFactoryAware接口,则调用setBeanFactory方法;

  6. 调用BeanPostProcessor的postProcessBeforeInitialization方法;

  7. 如果Bean实现了InitializingBean接口,调用afterPropertiesSet方法;

  8. 如果Bean定义了init-method方法,则调用Bean的init-method方法;

  9. 调用BeanPostProcessor的postProcessAfterInitialization方法;当进行到这一步,Bean已经被准备就绪了,一直停留在应用的

上下文中,直到被销毁;

  1. 如果应用的上下文被销毁了,如果Bean实现了DisposableBean接口,则调用destroy方法,如果Bean定义了destory-method

声明了销毁方法也会被调用。

6-12-finishRefresh();

refresh做完之后需要做的其他事情。

清除上下文资源缓存(如扫描中的ASM元数据)

初始化上下文的生命周期处理器,并刷新(找出Spring容器中实现了Lifecycle接口的bean并执行start()方法)。

发布ContextRefreshedEvent事件告知对应的ApplicationListener进行响应的操作

Spring IOC源码解析(10)AbstractBeanFactory

https://www.jianshu.com/p/ef6a92ce25b3

Spring源码6:createApplicationContext()实例AnnotationConfigServletWebServerApplicationContext

https://www.jianshu.com/p/17c8b15dd595

spring IoC 源码的更多相关文章

  1. 深入Spring IOC源码之ResourceLoader

    在<深入Spring IOC源码之Resource>中已经详细介绍了Spring中Resource的抽象,Resource接口有很多实现类,我们当然可以使用各自的构造函数创建符合需求的Re ...

  2. Spring IOC 源码之ResourceLoader

    转载自http://www.blogjava.net/DLevin/archive/2012/12/01/392337.html 在<深入Spring IOC源码之Resource>中已经 ...

  3. Spring IOC 源码分析

    Spring 最重要的概念是 IOC 和 AOP,本篇文章其实就是要带领大家来分析下 Spring 的 IOC 容器.既然大家平时都要用到 Spring,怎么可以不好好了解 Spring 呢?阅读本文 ...

  4. spring IoC源码分析 (3)Resource解析

    引自 spring IoC源码分析 (3)Resource解析 定义好了Resource之后,看到XmlFactoryBean的构造函数 public XmlBeanFactory(Resource  ...

  5. Spring IoC源码解析之invokeBeanFactoryPostProcessors

    一.Bean工厂的后置处理器 Bean工厂的后置处理器:BeanFactoryPostProcessor(触发时机:bean定义注册之后bean实例化之前)和BeanDefinitionRegistr ...

  6. Spring IoC源码解析之getBean

    一.实例化所有的非懒加载的单实例Bean 从org.springframework.context.support.AbstractApplicationContext#refresh方法开发,进入到 ...

  7. Spring系列(三):Spring IoC源码解析

    一.Spring容器类继承图 二.容器前期准备 IoC源码解析入口: /** * @desc: ioc原理解析 启动 * @author: toby * @date: 2019/7/22 22:20 ...

  8. Spring IoC 源码分析 (基于注解) 之 包扫描

    在上篇文章Spring IoC 源码分析 (基于注解) 一我们分析到,我们通过AnnotationConfigApplicationContext类传入一个包路径启动Spring之后,会首先初始化包扫 ...

  9. Spring Ioc源码分析系列--Ioc的基础知识准备

    Spring Ioc源码分析系列--Ioc的基础知识准备 本系列文章代码基于Spring Framework 5.2.x Ioc的概念 在Spring里,Ioc的定义为The IoC Containe ...

  10. Spring Ioc源码分析系列--前言

    Spring Ioc源码分析系列--前言 为什么要写这个系列文章 首先这是我个人很久之前的一个计划,拖了很久没有实施,现在算是填坑了.其次,作为一个Java开发者,Spring是绕不开的课题.在Spr ...

随机推荐

  1. MySQL日期时间加|减法

    日期加法 select date_add(curdate(), interval N SECOND); -- 加N秒 select date_add(curdate(), interval N MIN ...

  2. 15、string

    1.string是什么? Go中的字符串是一个字节的切片,可以通过将其内容封装起在""中来创建字符串.Go中的的字符串是Unicode兼容的并且是UTF-8编码的. 2.strin ...

  3. java之switch用法

    多条件判断,判断条件是等值判断时,可以用switch 比如: 变量level=0时,输出"非会员" 变量level=1时,输出"打9折" 变量level=2时, ...

  4. AutoGPT实战

    1.概述 人工智能(AI)的能力持续在全球范围内引起轰动,并对我们日常生活和职业生涯带来重大变革.随着像ChatGPT这样的先进生成型AI模型以及从GPT-3到GPT-4的加速,我们在高级推理.理解更 ...

  5. SQL优化案例(1):隐式转换

    MySQL是当下最流行的关系型数据库之一,互联网高速发展的今天,MySQL数据库在电商.金融等诸多行业的生产系统中被广泛使用. 在实际的开发运维过程中,想必大家也常常会碰到慢SQL的困扰.一条性能不好 ...

  6. 让 sdk 包静默升级的 SAO 操作,你见过几种?

    拓展阅读 让 sdk 包静默升级的 SAO 操作,你见过几种? 业务背景 有时候为业务方提供了基础的 sdk 包,为了保证稳定性,一般都是 release 包. 但是每一次升级都非常痛苦,也不可能写一 ...

  7. DVWA Cross Site Scripting (XSS) 跨站脚本攻击

    文章目录 DVWA_XSS(Stored) 存储性XSS 1.Low 2.Medium 3.High 4.Impossible XSS平台 DVWA_XSS(Stored) 存储性XSS 一句话概括: ...

  8. 劫持最新版 QQNT / QQ / TIM 客户端 ClientKeys

    针对 腾讯官网 最新发布的 QQNT 9.9.6 与 QQ 9.7.21 新版本客户端全面更新截取代码 大伙应该都知道自从 QQ 9.7.20 版本起就已经不能通过模拟网页快捷登录来截取 Uin 跟 ...

  9. win11 右击还原 win10的

    以管理员身份 打开 powershell, 然后输入如下代码 .\reg.exe add "HKCU\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a ...

  10. CSS 基础 5 - CSS 选择器

    基础 #id{} ID 选择器 .class{} 类选择器 tag{} 标签选择器,tag 可以是 h1, p, div, span, img, nav, footer... *{} 通用选择器,选择 ...