AnnotationConfigApplicationContext启动探究

创建SpringBoot工程(2.7.3),创建一个AppConfig类

public class AppConfig {
    @Bean
    public Cat cat(){
        Cat cat = new Cat();
        cat.setName("tom");
        return cat;
    }
}

@Data
public class Cat {
    private String name;
}

主启动类中创建一个AnnotationConfigApplicationContext ,然后获取Bean
打印信息为tom

@SpringBootApplication
public class SpringSourceLearnApplication {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        Cat cat = context.getBean(Cat.class);
        System.out.println(cat.getName());
    }

}

分析一下以上代码执行流程

AnnotationConfigApplicationContext有参构造函数中调用无参构造函数,主要就是初始化reader和scanner

public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {

	public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
		this();
		register(componentClasses);
		refresh();
	}
	
	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);
	}

}

关于AnnotatedBeanDefinitionReaderClassPathBeanDefinitionScanner,两者的作用是一样的,都是将Bean注册为BeanDefinition,只是使用场景的区别。AnnotatedBeanDefinitionReader的源码注释也说明了这一点

/**
 * Convenient adapter for programmatic registration of bean classes.
 *
 * <p>This is an alternative to {@link ClassPathBeanDefinitionScanner}, applying
 * the same resolution of annotations but for explicitly registered classes only.
 *
 * @author Juergen Hoeller
 * @author Chris Beams
 * @author Sam Brannen
 * @author Phillip Webb
 * @since 3.0
 * @see AnnotationConfigApplicationContext#register
 */
public class AnnotatedBeanDefinitionReader {
}

在调用无参构造方法时,会首先调用父类的无参构造,因此接着看父类的无参构造方法

GenericApplicationContext 无参构造中初始化DefaultListableBeanFactory

public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {

	public GenericApplicationContext() {
		this.beanFactory = new DefaultListableBeanFactory();
	}

}

AbstractApplicationContext 无参构造中初始化ResourcePatternResolver,这就是一个资源加载器,继承自ResourceLoader

public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {

	public AbstractApplicationContext() {
		this.resourcePatternResolver = getResourcePatternResolver();
	}

}

DefaultResourceLoader无参构造中什么也没有,下面回到AnnotationConfigApplicationContext构造函数

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

@Override
public void register(Class<?>... componentClasses) {
	Assert.notEmpty(componentClasses, "At least one component class must be specified");
	StartupStep registerComponentClass = this.getApplicationStartup().start("spring.context.component-classes.register")
			.tag("classes", () -> Arrays.toString(componentClasses));
	this.reader.register(componentClasses);
	registerComponentClass.end();
}

register方法最终会调用AnnotatedBeanDefinitionReader的register方法
refresh调用的是父类AbstractApplicationContext中的refresh方法,执行容器的创建

梳理下整个过程

  1. 初始化资源加载器ResourcePatternResolver
  2. 初始化Bean工厂DefaultListableBeanFactory
  3. 初始化AnnotatedBeanDefinitionReaderClassPathBeanDefinitionScanner
  4. 使用AnnotatedBeanDefinitionReader注册Bean
  5. 创建容器

register方法分析

@Override
public void register(Class<?>... componentClasses) {
	Assert.notEmpty(componentClasses, "At least one component class must be specified");
	StartupStep registerComponentClass = this.getApplicationStartup().start("spring.context.component-classes.register")
			.tag("classes", () -> Arrays.toString(componentClasses));
	this.reader.register(componentClasses);
	registerComponentClass.end();
}

public void register(Class<?>... componentClasses) {
	for (Class<?> componentClass : componentClasses) {
		registerBean(componentClass);
	}
}

public void registerBean(Class<?> beanClass) {
	doRegisterBean(beanClass, null, null, null, null);
}

private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
		@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
		@Nullable BeanDefinitionCustomizer[] customizers) {
		
	// 创建BeanDefinition
	// AnnotatedGenericBeanDefinition 继承自GenericBeanDefinition 继承自 AbstractBeanDefinition 实现了BeanDefinition
	AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
	
	// 判断Confitional相关注解,是否应该跳过
	if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
		return;
	}

	abd.setInstanceSupplier(supplier);

	// Scope元数据
	ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
	abd.setScope(scopeMetadata.getScopeName());
 
 	// 生成一个名称
	String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

	// 处理 @Lazy, @DependsOn,@Primary等注解,设置BeanDefinition的相关属性
	AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
	if (qualifiers != null) {
		for (Class<? extends Annotation> qualifier : qualifiers) {
			if (Primary.class == qualifier) {
				abd.setPrimary(true);
			}
			else if (Lazy.class == qualifier) {
				abd.setLazyInit(true);
			}
			else {
				abd.addQualifier(new AutowireCandidateQualifier(qualifier));
			}
		}
	}
	if (customizers != null) {
		for (BeanDefinitionCustomizer customizer : customizers) {
			customizer.customize(abd);
		}
	}

	// 创建holder,下面两个方法会用到
	BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);

	// 如果有@Scope注解,会向BeanFactory中加入一个代理对象BeanDefinition
	definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);

	// 注册Bean
	BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}

如果将AppConfig加上@Scope注解,如下

@Scope(value = "singleton", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class AppConfig {
    @Bean
    public Cat cat(){
        Cat cat = new Cat();
        cat.setName("tom");
        return cat;
    }
}

使用断点调试
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);这行代码执行完后,beanDefinitionMap中会多一个scopedTarget.appConfig
在这里插入图片描述
最后一行代码执行完后,beanDefinitionMap中会多一个appConfig

在这里插入图片描述

refresh方法分析

refresh方法在ConfigurableApplicationContext中定义,在AbstractApplicationContext中实现
在这里插入图片描述

@Override
public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

		// Prepare this context for refreshing.
		// 属性初始化
		prepareRefresh();

		// Tell the subclass to refresh the internal bean factory.
		// 获取BeanFactory(DefaultListableBeanFactory是ConfigurableListableBeanFactory实现类)
		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.
			// 依然可以看作工厂的准备阶段,是个protected方法,由子类实现
			postProcessBeanFactory(beanFactory);

			StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
			// Invoke factory processors registered as beans in the context.
			// 调用BeanFactoryPostProcessor
			invokeBeanFactoryPostProcessors(beanFactory);

			// Register bean processors that intercept bean creation.
			// 注册BeanPostProcessor
			registerBeanPostProcessors(beanFactory);
			beanPostProcess.end();

			// Initialize message source for this context.
			// 国际化
			initMessageSource();

			// Initialize event multicaster for this context.
			// 事件广播
			initApplicationEventMulticaster();

			// Initialize other special beans in specific context subclasses.
			// 同postProcessBeanFactory,由子类实现
			onRefresh();

			// Check for listener beans and register them.
			// 注册事件监听器
			registerListeners();

			// Instantiate all remaining (non-lazy-init) singletons.
			// 所有非懒加载bean的实例化
			finishBeanFactoryInitialization(beanFactory);

			// Last step: publish corresponding event.
			// 发布上下文刷新完成事件
			finishRefresh();
		}

		catch (BeansException ex) {
			if (logger.isWarnEnabled()) {
				logger.warn("Exception encountered during context initialization - " +
						"cancelling refresh attempt: " + ex);
			}

			// Destroy already created singletons to avoid dangling resources.
			destroyBeans();

			// Reset 'active' flag.
			cancelRefresh(ex);

			// Propagate exception to caller.
			throw ex;
		}

		finally {
			// Reset common introspection caches in Spring's core, since we
			// might not ever need metadata for singleton beans anymore...
			resetCommonCaches();
			contextRefresh.end();
		}
	}
}

总结一下:

  1. AbstractApplicationContext中属性的初始化
  2. BeanFactory的初始化
  3. 调用BeanFactoryPostProcessor
  4. 注册BeanPostProcessor
  5. ApplicationEvent相关设置
  6. 初始化非懒加载Bean
  7. 发布上下文刷新完成事件

BeanDefinition扫描

回到一开始的示例代码,想要从上下文中获取Cat对象,那么一定会先有BeanDefiniton定义,下面探讨Cat的BeanDefinition是何时创建的

通过断点调试,定位到refresh方法中invokeBeanFactoryPostProcessors
在这里插入图片描述

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {

		// 这里不用猜,一定是这句代码
		PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

		// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
		// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
		if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}
	}

在这里插入图片描述

private static void invokeBeanDefinitionRegistryPostProcessors(
		Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry, ApplicationStartup applicationStartup) {

	for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
		StartupStep postProcessBeanDefRegistry = applicationStartup.start("spring.context.beandef-registry.post-process")
				.tag("postProcessor", postProcessor::toString);
				
		// 关注这个方法
		postProcessor.postProcessBeanDefinitionRegistry(registry);
		postProcessBeanDefRegistry.end();
	}
}

BeanDefinitionRegistryPostProcessor 是一个接口,最终传进来的是ConfigurationClassPostProcessor

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {

	/**
	 * Modify the application context's internal bean definition registry after its
	 * standard initialization. All regular bean definitions will have been loaded,
	 * but no beans will have been instantiated yet. This allows for adding further
	 * bean definitions before the next post-processing phase kicks in.
	 * @param registry the bean definition registry used by the application context
	 * @throws org.springframework.beans.BeansException in case of errors
	 */
	void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;

}

进入ConfigurationClassPostProcessorpostProcessBeanDefinitionRegistry方法

@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
	int registryId = System.identityHashCode(registry);
	if (this.registriesPostProcessed.contains(registryId)) {
		throw new IllegalStateException(
				"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
	}
	if (this.factoriesPostProcessed.contains(registryId)) {
		throw new IllegalStateException(
				"postProcessBeanFactory already called on this post-processor against " + registry);
	}
	this.registriesPostProcessed.add(registryId);

	processConfigBeanDefinitions(registry);
}

processConfigBeanDefinitions方法中有个关键注释,处理@Configuration类
在这里插入图片描述

进入ConfigurationClassParser的parse方法

public void parse(Set<BeanDefinitionHolder> configCandidates) {

	// 这里只有一个AppConfig对应的BeanDefinitionHolder 
	for (BeanDefinitionHolder holder : configCandidates) {
		BeanDefinition bd = holder.getBeanDefinition();
		try {
			// 还记得一开始doRegisterBean中创建的AnnotatedGenericBeanDefinition 吗
			// 就是AnnotatedBeanDefinition的实现类
			// 会进入这个if
			if (bd instanceof AnnotatedBeanDefinition) {
				parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
			}
			else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
				parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
			}
			else {
				parse(bd.getBeanClassName(), holder.getBeanName());
			}
		}
		catch (BeanDefinitionStoreException ex) {
			throw ex;
		}
		catch (Throwable ex) {
			throw new BeanDefinitionStoreException(
					"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
		}
	}

	this.deferredImportSelectorHandler.process();
}
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
	processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
}
protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {

	// 处理@Contional注解,是否应该跳过
	if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
		return;
	}

	ConfigurationClass existingClass = this.configurationClasses.get(configClass);
	if (existingClass != null) {
		if (configClass.isImported()) {
			if (existingClass.isImported()) {
				existingClass.mergeImportedBy(configClass);
			}
			// Otherwise ignore new imported config class; existing non-imported class overrides it.
			return;
		}
		else {
			// Explicit bean definition found, probably replacing an import.
			// Let's remove the old one and go with the new one.
			this.configurationClasses.remove(configClass);
			this.knownSuperclasses.values().removeIf(configClass::equals);
		}
	}

	// Recursively process the configuration class and its superclass hierarchy.
	// 关注这个方法,核心逻辑一定在这里面
	// 这里要有个认知
	// Spring源码中有个特点,xxx方法中会调用doXXX方法,那么核心逻辑一般在doXXX方法里
	SourceClass sourceClass = asSourceClass(configClass, filter);
	do {
		sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
	}
	while (sourceClass != null);

	this.configurationClasses.put(configClass, configClass);
}

这个方法就比较精彩了,通过注释可以知道
@PropertySource@ComponentScan@Import@ImportResource@Bean都是在这里面处理的
这个例子中,我们要关注的就是@Bean

@Nullable
protected final SourceClass doProcessConfigurationClass(
		ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
		throws IOException {

	if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
		// Recursively process any member (nested) classes first
		processMemberClasses(configClass, sourceClass, filter);
	}

	// Process any @PropertySource annotations
	for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
			sourceClass.getMetadata(), PropertySources.class,
			org.springframework.context.annotation.PropertySource.class)) {
		if (this.environment instanceof ConfigurableEnvironment) {
			processPropertySource(propertySource);
		}
		else {
			logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
					"]. Reason: Environment must implement ConfigurableEnvironment");
		}
	}

	// Process any @ComponentScan annotations
	Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
			sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
	if (!componentScans.isEmpty() &&
			!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
		for (AnnotationAttributes componentScan : componentScans) {
			// The config class is annotated with @ComponentScan -> perform the scan immediately
			Set<BeanDefinitionHolder> scannedBeanDefinitions =
					this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
			// Check the set of scanned definitions for any further config classes and parse recursively if needed
			for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
				BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
				if (bdCand == null) {
					bdCand = holder.getBeanDefinition();
				}
				if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
					parse(bdCand.getBeanClassName(), holder.getBeanName());
				}
			}
		}
	}

	// Process any @Import annotations
	processImports(configClass, sourceClass, getImports(sourceClass), filter, true);

	// Process any @ImportResource annotations
	AnnotationAttributes importResource =
			AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
	if (importResource != null) {
		String[] resources = importResource.getStringArray("locations");
		Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
		for (String resource : resources) {
			String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
			configClass.addImportedResource(resolvedResource, readerClass);
		}
	}

	// Process individual @Bean methods
	Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
	for (MethodMetadata methodMetadata : beanMethods) {
		configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
	}

	// Process default methods on interfaces
	processInterfaces(configClass, sourceClass);

	// Process superclass, if any
	if (sourceClass.getMetadata().hasSuperClass()) {
		String superclass = sourceClass.getMetadata().getSuperClassName();
		if (superclass != null && !superclass.startsWith("java") &&
				!this.knownSuperclasses.containsKey(superclass)) {
			this.knownSuperclasses.put(superclass, configClass);
			// Superclass found, return its annotation metadata and recurse
			return sourceClass.getSuperClass();
		}
	}

	// No superclass -> processing is complete
	return null;
}

不过,对@Bean的处理,只是调用了addBeanMethod方法,相当于只是填充了一个属性,并没有创建BeanDefinition

// Process individual @Bean methods
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
	configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}

那就需要接着往下看
回到ConfigurationClassPostProcessorprocessConfigBeanDefinitions方法
下面要执行的是this.reader.loadBeanDefinitions(configClasses);

在这里插入图片描述

public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
	TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
	// 这里只有一个AppConfig
	for (ConfigurationClass configClass : configurationModel) {
		// 不用说,一定是这个方法了
		// 见名知意,加载配置类中的BeanDefiniton
		loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
	}
}
private void loadBeanDefinitionsForConfigurationClass(
			ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {

		//  同样是先判断@Conditional注解
		if (trackedConditionEvaluator.shouldSkip(configClass)) {
			String beanName = configClass.getBeanName();
			if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
				this.registry.removeBeanDefinition(beanName);
			}
			this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
			return;
		}

		if (configClass.isImported()) {
			registerBeanDefinitionForImportedConfigurationClass(configClass);
		}

		// 还记得前面调用了addBeanMethod吗
		// 这里才是真正的使用
		for (BeanMethod beanMethod : configClass.getBeanMethods()) {
		    // 下面关注这个方法
			loadBeanDefinitionsForBeanMethod(beanMethod);
		}

		loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
		loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
	}

判断了下静态还是非静态,设置不同的属性
在这里插入图片描述
处理@Bean的属性
在这里插入图片描述
最终在方法最后,注册BeanDefiniton

在这里插入图片描述
这里register,就是DefaultListableBeanFactory(实现了BeanDefinitionRegistry
所谓注册,核心就是向map中put一个元素
在这里插入图片描述
到此,就完整实现了将AppConfig以及AppConfig中使用@Bean定义的BeanDefinition放入缓存中
后面就是由这些BeanDefinition创建Bean对象

未完

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值