创建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);
}
}
关于AnnotatedBeanDefinitionReader
和ClassPathBeanDefinitionScanner
,两者的作用是一样的,都是将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方法,执行容器的创建
梳理下整个过程
- 初始化资源加载器
ResourcePatternResolver
- 初始化Bean工厂
DefaultListableBeanFactory
- 初始化
AnnotatedBeanDefinitionReader
和ClassPathBeanDefinitionScanner
- 使用
AnnotatedBeanDefinitionReader
注册Bean - 创建容器
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();
}
}
}
总结一下:
AbstractApplicationContext
中属性的初始化BeanFactory
的初始化- 调用
BeanFactoryPostProcessor
- 注册
BeanPostProcessor
ApplicationEvent
相关设置- 初始化非懒加载Bean
- 发布上下文刷新完成事件
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;
}
进入ConfigurationClassPostProcessor
的postProcessBeanDefinitionRegistry
方法
@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));
}
那就需要接着往下看
回到ConfigurationClassPostProcessor
的processConfigBeanDefinitions
方法
下面要执行的是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对象
未完