Spring扫描
最近在学习Spring源码,但是我现在不太想把自己的整个学习笔记贴出来,还是要精炼,学习笔记几千上万字不太利于读者阅读
spring的版本是当时的最新版6.1.x
抽取其中觉得有必要分享的点写一篇博客记录一下,顺便总结提炼.这篇博客内容主要介绍的是spring中invokeBeanFactoryPostProcessors方法和ConfigurationClassPostProcessor类的代码的执行,是比较简单的部分
会使用到的接口
提前说明一下涉及到的接口
BeanFactoryPostProcessor
这里就要先说一下spring内部的各种PostProcessor,我们最常用的就是BeanPostProcessor,他是spring构建Bean时的后置处理器.然而BeanFactoryPostProcessor,是spring构建BeanFactory的后置处理器
spring首先构建BeanFactory,所以BeanFactoryPostProcessor的生命周期在BeanPostProcessor之前
源码会涉及到的2个接口,分别是:
BeanFactoryPostProcessor,继承该接口需要实现postProcessBeanFactory
BeanDefinitionRegistryPostProcessor,是BeanFactoryPostProcessor的子接口,需要实现postProcessBeanDefinitionRegistry,可以调用该接口创建BeanDefinition
@Component
public class MengnanBeanFactoryPostProcessor
// implements BeanFactoryPostProcessor {
// (BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的子接口)
implements BeanDefinitionRegistryPostProcessor {
@Override
// 可以通过该方法注册BeanDefinition
// 先执行
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClassName("info.mengnan.User");
beanDefinition.setLazyInit(false);
registry.registerBeanDefinition("user", beanDefinition);
}
@Override
// 能拿到BeanDefinition但是不能注册BeanDefinition
// 可以调用BeanFactory的接口
// 后执行
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
beanFactory.registerSingleton("member", new MemberService());
// 一般只能拿到BeanDefinition
// 因为BeanFactoryPostProcessor的在spring生命周期时还没有创建Bean
// 可以看refresh方法的invokeBeanFactoryPostProcessors
// 要最后才会执行finishBeanFactoryInitialization
BeanDefinition beanDefinition = beanFactory.getBeanDefinition("userService");
}
}
Ordered
同样也会涉及到2个接口
Ordered,需要实现getOrder方法
PriorityOrdered,Ordered的子接口,也需要实现getOrder方法
都和Bean执行顺序有关,不过PriorityOrdered的优先级大于Ordered,在以下源码中也有体现
ImportSelector
执行ConfigurationClassPostProcessor会调用的接口,会将数组内的类进行导入为配置类
@Component
public class MengnanImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{MemberService.class.getName()};
}
}
正文
如果你学习了Spring,你也就必然知道Spring的使用方式
// 传递一个类,一般情况下是配置类
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
在其中会执行refresh方法,spring的扫描注册等操作都放在其中
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
// 注册reader和scanner
this();
// 注册配置类
register(componentClasses);
refresh();
}
执行refresh方法,其中会执行invokeBeanFactoryPostProcessors
因为代码太长我就直接截图了
这里我备注一下这篇博文的重点是invokeBeanFactoryPostProcessors,不过内部执行逻辑和下面的registerBeanPostProcessors方法极为类似
最终内部会执行
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
// 此时getBeanFactoryPostProcessors()只能拿到执行refresh方法之前存储的BeanFactoryPostProcessor
// 重点方法
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
}
在此处debug会发现getBeanFactoryPostProcessors返回的是一个空数组,因为spring还没有开始扫描,除非你使用以下特殊方式
// 使用无参构造后手动refresh
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.addBeanFactoryPostProcessor(new MengnanBeanFactoryPostProcessor());
context.refresh();
invokeBeanFactoryPostProcessors主要做的就是扫描、不断注册、创建、排序BeanFactoryPostProcessors,注册BeanDefinition
构造BeanFactoryPostProcessor
源码很长,但是仔细阅读发现并不复杂,以下代码可以分为3个部分,以下内容建议对照源码阅读
外部传入创建
通过方法参数传递进来的BeanFactoryPostProcessor,默认情况下是空数组,也就是说如果你不使用上述的特殊方式,这段代码永远不会执行
这里的代码和之后的代码有显著区别,会立刻执行postProcessBeanDefinitionRegistry方法,不过postProcessBeanFactory却会存储起来之后执行
这里声明了一个名为processedBeans的Set集合,processedBeans的作用是存储所有处理过的PostProcessor,防止重复执行
但是有一块疑点,通过我前面说的
特殊方式
传入的PostProcessor不会存入processedBeans,所以会导致重复执行.不知道为什么spring要这么设计
外部传入的postProcessBeanDefinitionRegistry优先级最高
执行通过外部传入的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法
// 存储的是执行过的Bean
Set<String> processedBeans = new HashSet<>();
if (beanFactory instanceof BeanDefinitionRegistry registry) {
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
// 先处理外部传递的beanFactoryPostProcessors
// beanFactoryPostProcessors一般情况下都是空数组的,除非在手动refresh之前执行了addBeanFactoryPostProcessor方法
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
// 对于BeanDefinitionRegistryPostProcessor对象,会执行postProcessBeanDefinitionRegistry
// 执行全部的postProcessBeanDefinitionRegistry方法
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor registryProcessor) {
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
// BeanFactoryPostProcessor的生命周期比较靠后,所以此处没有直接执行postProcessBeanFactory
regularPostProcessors.add(postProcessor);
}
}
BeanDefinitionRegistryPostProcessor
不断调用getBeanNamesForType,获取postProcessorNames,为什么要不断获取呢,因为调用beanDefinitionRegistryPostProcessor会创建新的BeanDefinition,所以要不断获取直到获取不到为止
第一次获取时postProcessorNames中一般情况只有一个元素:org.springframework.context.annotation.internalConfigurationAnnotationProcessor
,这个类非常重要,它就是ConfigurationClassPostProcessor
我这里说的一般情况指的是使用AnnotationConfigApplicationContext(Class<?>... componentClasses)这个构造方法来创建spring
ConfigurationClassPostProcessor这个类在spring构造方法中创建AnnotatedBeanDefinitionReader时就已经注册为BeanDefinition
通过代码可以看到有以下生命周期进行执行,整理一下发现代码本身并不复杂,只是spring设置了非常复杂的生命周期
执行继承了BeanDefinitionRegistryPostProcessor和PriorityOrdered的postProcessBeanDefinitionRegistry方法
执行继承了BeanDefinitionRegistryPostProcessor和Ordered的postProcessBeanDefinitionRegistry方法
执行其他的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法
执行目前方法内获取的所有BeanDefinitionRegistryPostProcessor的processBeanFactory方法
执行通过外部传入的BeanDefinitionRegistryPostProcessor的processBeanFactory方法
每次执行过后都会存储到processedBeans中
// 当此循环的RegistryProcessors
// 以下会经过多次循环,每次循环都会将RegistryPostProcessor暂时放入
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// 没有开始扫描所以依然拿不到自己定义的PostProcessor
// (除非创建AnnotationConfigApplicationContext传了包名则会调用scan方法提前扫描)
// 但是可以拿到提前放入的PostProcessor的BeanDefinition
// 此处可以拿到ConfigurationClassPostProcessor(在refresh之前就已经放入了)
// ConfigurationClassPostProcessor的主要作用就是扫描
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// 判断是否实现了PriorityOrdered接口
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
// 获取ConfigurationClassPostProcessor的BeanDefinition并创建为Bean
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
// 排序@Ordered指定的数字进行排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// 执行所有的RegistryProcessors的postProcessBeanDefinitionRegistry
// 解析配置了,执行扫描操作(如有ComponentScan)
// 特别是ConfigurationClassPostProcessor
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();
// 再一次拿到所有的BeanDefinitionRegistryPostProcessor
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// 再一次执行,不过这次要过滤已经执行过的
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
// 再一次排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();
boolean reiterate = true;
while (reiterate) {
reiterate = false;
// 因为RegistryPostProcessor会产生新的RegistryPostProcessor,所以要不断循环,直到拿不到新的为止
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// 所有postProcessorNames都存储在processedBeans中,reiterate为false,退出while循环
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
// 拿到新的设置为true继续while循环
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup(
currentRegistryProcessors.clear();
}
// 执行完成所有postProcessBeanDefinitionRegistry后开始执行postProcessBeanFactory
// 此处也有先后顺序,先执行直接实现子接口(BeanDefinitionRegistryPostProcessor)的
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
// 最后执行手动添加的BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
BeanFactoryPostProcessor
以下代码变的简单,因为BeanFactoryPostProcessor无法生产BeanDefinition所以只需要一次循环分类PriorityOrdered、Ordered,排序后依次执行,最后再执行剩余的BeanFactoryPostProcessor
此处代码也包含以下生命周期
执行继承了BeanFactoryPostProcessor和PriorityOrdered的processBeanFactory方法
执行继承了BeanFactoryPostProcessor和Ordered的processBeanFactory方法
执行其他的BeanFactoryPostProcessor的processBeanFactory方法
// 代码执行到这里就把所有的BeanDefinitionRegistryPostProcessor执行完了,这就说明不会产生新的BeanDefinition了
// 现开始获取BeanFactoryPostProcessor
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
// 因为不会产生新的BeanDefinition
// 所以实现变得更简单,执行逻辑和BeanDefinitionRegistryPostProcessor一样
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// 跳过
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// 排序
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
// 执行postProcessBeanFactory
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// 依次执行并排序
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
beanFactory.clearMetadataCache();
ConfigurationClassPostProcessor
开始解析配置类
会执行2步,会先注册BeanDefinition,之后才会执行postProcessBeanFactory
@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);
// 解析配置类
// 扫描得到BeanDefinition
processConfigBeanDefinitions(registry);
}
配置类的定义
这里先要知道什么是配置类,我们可以在ConfigurationClassUtils.checkConfigurationClassCandidate
看到spring对于配置类中的明确定义
static boolean checkConfigurationClassCandidate(
BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
String className = beanDef.getBeanClassName();
if (className == null || beanDef.getFactoryMethodName() != null) {
return false;
}
// 拿到该BeanDefinition对应的注解元信息
AnnotationMetadata metadata;
if (beanDef instanceof AnnotatedBeanDefinition annotatedBd &&
className.equals(annotatedBd.getMetadata().getClassName())) {
metadata = annotatedBd.getMetadata();
}
else if (beanDef instanceof AbstractBeanDefinition abstractBd && abstractBd.hasBeanClass()) {
Class<?> beanClass = abstractBd.getBeanClass();
if (BeanFactoryPostProcessor.class.isAssignableFrom(beanClass) ||
BeanPostProcessor.class.isAssignableFrom(beanClass) ||
AopInfrastructureBean.class.isAssignableFrom(beanClass) ||
EventListenerFactory.class.isAssignableFrom(beanClass)) {
return false;
}
metadata = AnnotationMetadata.introspect(beanClass);
}
else {
try {
MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className);
metadata = metadataReader.getAnnotationMetadata();
}
catch (IOException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Could not find class file for introspecting configuration annotations: " +
className, ex);
}
return false;
}
}
// 判断是否有@Configuration
Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
// 如果加了@Configuration并且proxyBeanMethods设置为不为false(默认是true)
if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
// FULL配置类
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
}
// 加了@Configuration
else if (config != null || Boolean.TRUE.equals(beanDef.getAttribute(CANDIDATE_ATTRIBUTE)) ||
isConfigurationCandidate(metadata)) {
// LITE配置类
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
}
else {
return false;
}
Integer order = getOrder(metadata);
if (order != null) {
beanDef.setAttribute(ORDER_ATTRIBUTE, order);
}
return true;
}
我们可以看到spring将配置类分为FULL配置类和LITE配置类
类上添加了@Configuration并且proxyBeanMethods为true为FULL配置类
类上添加了@Configuration并且proxyBeanMethods为false,或者isConfigurationCandidate方法执行为true则为LITE配置类
static boolean isConfigurationCandidate(AnnotationMetadata metadata) {
// 配置类不能是接口
if (metadata.isInterface()) {
return false;
}
// 配置类只要包含@Component、@ComponentScan、@Import、@ImportResource中的一个
for (String indicator : candidateIndicators) {
if (metadata.isAnnotated(indicator)) {
return true;
}
}
// 或者有加了@Bean的方法
return hasBeanMethods(metadata);
}
两者的区别,如果是FULL配置类,spring会基于这个类创建代理类
有兴趣的可以参照ConfigurationClassEnhancer的intercept方法
@Configuration(proxyBeanMethods = true)
public class AppConfig {
@Bean
public MemberService memberService() {
return new MemberService();
}
@Bean
// 如果proxyBeanMethods为true,2个memberService执行结果一致
// 内部执行的时候会去getBean,所以返回的都是同一个对象
public UserService userService() {
System.out.println(memberService());
System.out.println(memberService());
return new UserService();
}
}
解析配置类
让我们具体看一下ConfigurationClassPostProcessor到底干了什么
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
// 拿到目前为止所有的BeanDefinition字符串数组
String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
// 如果已经做了配置类处理,忽略
if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
if (logger.isDebugEnabled()) {
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()) {
return;
}
// 通过@Order进行排序
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
});
SingletonBeanRegistry singletonRegistry = null;
if (registry instanceof SingletonBeanRegistry sbr) {
singletonRegistry = sbr;
if (!this.localBeanNameGeneratorSet) {
BeanNameGenerator generator = (BeanNameGenerator) singletonRegistry.getSingleton(
AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
// 设置Bean名称的生成器
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);
Set<ConfigurationClass> alreadyParsed = CollectionUtils.newHashSet(configCandidates.size());
// 解析配置类,可能通过一个配置类得到多个配置类
do {
StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
// 进行解析配置类,并收集deferredImportSelectorHandler
// 最后解析完所有配置类后执行deferredImportSelectorHandler中的延迟处理的配置
// 参照 [开始解析]
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());
}
// 把所有配置类解析为BeanDefinition,具体参见下面[loadBeanDefinitionsForConfigurationClass的方法说明]
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();
candidates.clear();
// 如果BeanDefinition增加了,说明增加了配置类
if (registry.getBeanDefinitionCount() > candidateNames.length) {
String[] newCandidateNames = registry.getBeanDefinitionNames();
Set<String> oldCandidateNames = Set.of(candidateNames);
Set<String> alreadyParsedClasses = CollectionUtils.newHashSet(alreadyParsed.size());
for (ConfigurationClass configurationClass : alreadyParsed) {
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
for (String candidateName : newCandidateNames) {
if (!oldCandidateNames.contains(candidateName)) {
BeanDefinition bd = registry.getBeanDefinition(candidateName);
// 检查多出来的BeanDefinition是否是配置类,需不需要解析
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
!alreadyParsedClasses.contains(bd.getBeanClassName())) {
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
candidateNames = newCandidateNames;
}
}
while (!candidates.isEmpty());
if (singletonRegistry != null && !singletonRegistry.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
singletonRegistry.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
this.propertySourceDescriptors = parser.getPropertySourceDescriptors();
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory cachingMetadataReaderFactory) {
cachingMetadataReaderFactory.clearCache();
}
}
spring会解析3种注解@Import、@Bean、@ImportResource
这里分别介绍一下这3个注解的区别
@Import 将内部的类解析出来进行处理
@Bean 执行被@Bean标注的方法,拿到它的返回值
@ImportResource 处理xml文件中的Bean对象
private void loadBeanDefinitionsForConfigurationClass(
ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
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;
}
// 处理@Import的类并将它转换为BeanDefinition
if (configClass.isImported()) {
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
// 处理@Bean并生成BeanDefinition
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
loadBeanDefinitionsForBeanMethod(beanMethod);
}
// 处理@ImportResource并生成BeanDefinition
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
// 处理@Import中的ImportBeanDefinitionResister的registerBeanDefinitions生成的BeanDefinition
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
开始解析
public void parse(Set<BeanDefinitionHolder> configCandidates) {
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {
// 将不同类型的BeanDefinition进行封装后执行同一个parse方法
if (bd instanceof AnnotatedBeanDefinition annotatedBeanDef) {
parse(annotatedBeanDef, holder.getBeanName());
}
else if (bd instanceof AbstractBeanDefinition abstractBeanDef && abstractBeanDef.hasBeanClass()) {
parse(abstractBeanDef.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);
}
}
// 循环执行parse结束后
// 处理deferredImportSelectors
// 当批所有配置解析完了以后才会执行(spring解析配置可以理解为是一批批执行的)
// deferredImportSelectors表示推迟处理的ImportSelector
this.deferredImportSelectorHandler.process();
}
private void parse(AnnotatedBeanDefinition beanDef, String beanName) {
processConfigurationClass(
new ConfigurationClass(beanDef.getMetadata(), beanName, (beanDef instanceof ScannedGenericBeanDefinition)),
DEFAULT_EXCLUSION_FILTER);
}
解析好配置类后会将结果存储在configurationClasses这个map中
protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) {
// 看看是否符合@Condition注解的条件
if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
return;
}
ConfigurationClass existingClass = this.configurationClasses.get(configClass);
if (existingClass != null) {
// 2个类同时@Import了同一个配置类,将该配置合并
if (configClass.isImported()) {
if (existingClass.isImported()) {
existingClass.mergeImportedBy(configClass);
}
return;
}
else if (configClass.isScanned()) {
String beanName = configClass.getBeanName();
if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
this.registry.removeBeanDefinition(beanName);
}
return;
}
else {
this.configurationClasses.remove(configClass);
removeKnownSuperclass(configClass.getMetadata().getClassName(), false);
}
}
SourceClass sourceClass = null;
try {
sourceClass = asSourceClass(configClass, filter);
do {
// 开始真正解析配置类
sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
}
while (sourceClass != null);
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"I/O failure while processing configuration class [" + sourceClass + "]", ex);
}
// 解析好的配置信息存储到configurationClasses,稍后会使用
this.configurationClasses.put(configClass, configClass);
}
开始真正解析配置类
并处理不同类型的注解,将内部的类转换为ConfigurationClass
类上存在@Component,则递归执行解析它的内部类
类上存在@PropertySource添加到PropertySourceProcessor的environment中
类上存在@ComponentScan,进行扫描(内部最终会执行doScan方法)并获取一系列BeanDefinition,如果是配置类则继续解析
类上存在@Import,这个比较复杂后续说明
类上存在@ImportResource,会将资源路径中的xml文件存储到importedResources中
方法上存在@Bean,会将这个方法封装为BeanMethod对象并存储在beanMethods中
如果配置类存在父类,还会对父类进行解析
protected final SourceClass doProcessConfigurationClass(
ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
throws IOException {
// 是否包含@Component
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
// 获取所有内部类
processMemberClasses(configClass, sourceClass, filter);
}
// 判断是否包含@PropertySource
// Process any @PropertySource annotations
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), org.springframework.context.annotation.PropertySource.class,
PropertySources.class, true)) {
if (this.propertySourceRegistry != null) {
this.propertySourceRegistry.processPropertySource(propertySource);
}
else {
logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
"]. Reason: Environment must implement ConfigurableEnvironment");
}
}
// 判断是否包含@ComponentScan
// 如果包含该注解,就会触发扫描操作
// Search for locally declared @ComponentScan annotations first.
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScan.class, ComponentScans.class,
MergedAnnotation::isDirectlyPresent);
// Fall back to searching for @ComponentScan meta-annotations (which indirectly
// includes locally declared compnmosed annotations).
if (componentScans.isEmpty()) {
componentScans = AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(),
ComponentScan.class, ComponentScans.class, MergedAnnotation::isMetaPresent);
}
if (!componentScans.isEmpty()) {
List<Condition> registerBeanConditions = collectRegisterBeanConditions(configClass);
if (!registerBeanConditions.isEmpty()) {
throw new ApplicationContextException(
"Component scan for configuration class [%s] could not be used with conditions in REGISTER_BEAN phase: %s".formatted(configClass.getMetadata().getClassName(), registerBeanConditions));
}
for (AnnotationAttributes componentScan : componentScans) {
// 扫描得到BeanDefinition
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
// 检查扫描出来的BeanDefinition是不是配置类
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
// 如果是解析(递归)
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
// 处理@Import
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
// 处理@ImportResource,将xml文件路径添加到importedResources中
// @ImportResource("spring.xml")
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);
}
}
// 找出配置类中的标注了@Bean方法(暂时只是找出来并未处理),添加到beanMethods属性中
// 例如配置类实现了default修饰的方法上添加了@Bean
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
if (methodMetadata.isAnnotated("kotlin.jvm.JvmStatic") && !methodMetadata.isStatic()) {
continue;
}
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// 将BeanMethod封装到beanMethods中
processInterfaces(configClass, sourceClass);
// 解析父类
if (sourceClass.getMetadata().hasSuperClass()) {
String superclass = sourceClass.getMetadata().getSuperClassName();
if (superclass != null && !superclass.startsWith("java")) {
boolean superclassKnown = this.knownSuperclasses.containsKey(superclass);
this.knownSuperclasses.add(superclass, configClass);
if (!superclassKnown) {
return sourceClass.getSuperClass();
}
}
}
return null;
}
@Import
如果配置类存在@Import
如果导入的类只是普通的类就执行常规的导入
如果导入的类实现了ImportSelector,实例化
如果是普通ImportSelector,直接调用selectImports需要返回一个数组进行批量导入,然后把这些类调用processImports(不断递归执行,直到解析的类全部都是普通的配置类为止)
如果是DeferredImportSelector,暂存在deferredImportSelectors,最后在processConfigBeanDefinitions方法循环中解析完当前批的配置最后才解析存储在这个list里的配置
如果导入的类实现了ImportBeanDefinitionRegistrar,实例化并将该类存储到importBeanDefinitionRegistrars中(实现ImportBeanDefinitionRegistrar也可以创建BeanDefinition,但是这里并没有直接调用registerBeanDefinitions)
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, Predicate<String> filter, boolean checkForCircularImpor
if (importCandidates.isEmpty()) {
return;
}
// 循环导入会导致异常
if (checkForCircularImports && isChainedImportOnStack(configClass)) {
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
}
else {
this.importStack.push(configClass);
try {
for (SourceClass candidate : importCandidates) {
// 通过@Import导入的类是否包含ImportSelector
if (candidate.isAssignable(ImportSelector.class)) {
Class<?> candidateClass = candidate.loadClass();
// 实例化并且转换为ImportSelector
ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, Import
this.environment, this.resourceLoader, this.registry);
Predicate<String> selectorFilter = selector.getExclusionFilter();
if (selectorFilter != null) {
filter = filter.or(selectorFilter);
}
if (selector instanceof DeferredImportSelector deferredImportSelector) {
// 如果import的是DeferredImportSelector
// 将DeferredImportSelector类型的临时存储到deferredImportSelectors
this.deferredImportSelectorHandler.handle(configClass, deferredImportSelector);
}
else {
// 解析selectImports方法,并且递归执行
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, f
processImports(configClass, currentSourceClass, importSourceClasses, filter, fals
}
}
// 通过@Import导入的类是否包含ImportBeanDefinitionRegistrar
// ImportBeanDefinitionRegistrar也可以注册BeanDefinition
else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
Class<?> candidateClass = candidate.loadClass();
ImportBeanDefinitionRegistrar registrar =
ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegi
this.environment, this.resourceLoader, this.registry);
// 并没有直接调用registerBeanDefinitions而是存储到importBeanDefinitionRegistrars
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadat
}
// 是否没加上以上2个接口
else {
// 直接把该类当作配置类
this.importStack.registerImport(
currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
processConfigurationClass(candidate.asConfigClass(configClass), filter);
}
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to process import candidates for configuration class [" +
configClass.getMetadata().getClassName() + "]: " + ex.getMessage(), ex);
}
finally {
this.importStack.pop();
}
}
}
总结
Spring的生命周期中会执行BeanFactoryPostProcessor,它会对BeanFactory进行加工.我们可以实现BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor接口来实现这个功能.拿到BeanFactory并对BeanDefinition进行创建或修改.因为是在创建Bean实例之前,所以对BeanDefinition的修改是会生效的
其中就包含最重要的ConfigurationClassPostProcessor,它也是spring中第一个被创建的BeanDefinition.获取类上的注解,并判断是否是配置类,如果包含@ComponentScan还会进行doScan操作
最终将以下信息封装为ConfigurationClass对象,最后存储在存储在configurationClasses中
如果包含@Bean会把方法封装到beanMethods属性中
如果包含@ImportResource会将资源路径存储在importedResources属性中
如果包含@Import会将内部的类加载为配置类
如果包含@Component,会解析它的内部类是否为配置类