Spring Boot 之 BeanDefinitionLoader 详解
入口
BeanDefinitionLoader顾名思义是用来加载bean定义的。在spring boot启动过程中的准备上下文件阶段会进行source关联资源的bean定义加载,为后续bean的实例化做准备。关键代码如下:
//SpringApplication public class SpringApplication { //... private void prepareContext(...) { //... f (!AotDetector.useGeneratedArtifacts()) { // Load the sources Set<Object> sources = getAllSources(); Assert.notEmpty(sources, "Sources must not be empty"); load(context, sources.toArray(new Object[0])); } //.... } protected void load(ApplicationContext context, Object[] sources) { if (logger.isDebugEnabled()) { logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources)); } BeanDefinitionLoader loader = createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources); if (this.beanNameGenerator != null) { loader.setBeanNameGenerator(this.beanNameGenerator); } if (this.resourceLoader != null) { loader.setResourceLoader(this.resourceLoader); } if (this.environment != null) { loader.setEnvironment(this.environment); } loader.load(); } //... }构造函数
上面代码主要包含BeanDefinitionLoader实例的创建、设置一些属性、最后的装载。先让我看看BeanDefinitionLoader的构造函数。
BeanDefinitionLoader(BeanDefinitionRegistry registry, Object... sources) { Assert.notNull(registry, "Registry must not be null"); Assert.notEmpty(sources, "Sources must not be empty"); this.sources = sources; this.annotatedReader = new AnnotatedBeanDefinitionReader(registry); this.xmlReader = new XmlBeanDefinitionReader(registry); this.groovyReader = (isGroovyPresent() ? new GroovyBeanDefinitionReader(registry) : null); this.scanner = new ClassPathBeanDefinitionScanner(registry); this.scanner.addExcludeFilter(new ClassExcludeFilter(sources)); }从构造函数中可以看出,bean定义的加载主要有四种方式,分别为:注解的方式、xml配置方式、groovy脚本方式和路径扫描方式。在构造函数中提前构建好四种加载工具,在后续真正load()的地方再根据sources的类型来判断具体使用哪种 reader 来完成bean定义的加载。
Spring boot 默认通过AnnotatedBeanDefinitionReader方式来加载bean定义。这里需要注意下在AnnotatedBeanDefinitionReader构造函数中会实例化ConditionEvaluator条件评估器,ConditionEvaluator内部又会构造一个ConditionContextImpl实例。然后会将注解配置处理器注册到bean工厂中。
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) { 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, null); AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry); }让我们通过源码的方式详细分析下 registerAnnotationConfigProcessors 做了什么操作。
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors( BeanDefinitionRegistry registry, @Nullable Object source) { //从上下文中取出 beanFactory DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry); if (beanFactory != null) { //注意这里设置dependencyComparator、autowireCandidateResolver 只有在首次实例化AnnotatedBeanDefinitionReader //时才会赋值,而首次实例化是在‘AnnotationConfigServletWebServerApplicationContext’上下文创建阶段。 if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) { beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); } if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) { beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); } } Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8); //同理只在AnnotatedBeanDefinitionReader首次实例化时,才会注册以下相关后置处理器 if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)); } if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)); } // Check for Jakarta Annotations support, and if present add the CommonAnnotationBeanPostProcessor. if ((jakartaAnnotationsPresent || jsr250Present) && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)); } // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor. if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(); try { def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, AnnotationConfigUtils.class.getClassLoader())); } catch (ClassNotFoundException ex) { throw new IllegalStateException( "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex); } def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)); } if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME)); } if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME)); } return beanDefs; }注意:在registerPostProcessor内部实际会调用DefaultListableBeanFactory.registerPostProcessor方法进行bean定义的注册,这里不详细介绍。大概的逻辑就是判断集合是否包含要注册的BeanDefinition,无就加入,存在就根据情况抛异常或者覆盖。具体逻辑可以阅读相关代码。
load() 加载
接下来让我们看看load()加载的具体实现。
void load() { for (Object source : this.sources) { load(source); } } private void load(Object source) { Assert.notNull(source, "Source must not be null"); if (source instanceof Class<?> clazz) { load(clazz); return; } if (source instanceof Resource resource) { load(resource); return; } if (source instanceof Package pack) { load(pack); return; } if (source instanceof CharSequence sequence) { load(sequence); return; } throw new IllegalArgumentException("Invalid source type " + source.getClass()); }load的加载会判断source的类型,不同的类型走不同的处理逻辑。一般 source 是 Class类型,默认走以下方法进行处理。
private void load(Class<?> source) { if (isGroovyPresent() && GroovyBeanDefinitionSource.class.isAssignableFrom(source)) { // Any GroovyLoaders added in beans{} DSL can contribute beans here GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source, GroovyBeanDefinitionSource.class); ((GroovyBeanDefinitionReader) this.groovyReader).beans(loader.getBeans()); } if (isEligible(source)) { this.annotatedReader.register(source); } }可以看到,在isEligible(source) == true的情况,最终是通过AnnotatedBeanDefinitionReader来完成bean定义的注册。让我继续看看register(source)的实现。
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier, @Nullable BeanDefinitionCustomizer[] customizers) { //创建AnnotatedGenericBeanDefinition实例对象, AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass); //判断是否跳过bean的注册,根据条件判断(通常是被@Conditional注解)如果要跳过,则不进行bean定义的注册 if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) { return; } // 设置属性 org.springframework.context.annotation.ConfigurationClassPostProcessor.candidate = true abd.setAttribute(ConfigurationClassUtils.CANDIDATE_ATTRIBUTE, Boolean.TRUE); // 设置实例supplier abd.setInstanceSupplier(supplier); // 解析bean的作用域,并将作用域信息绑定到当前bean定义上 ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd); abd.setScope(scopeMetadata.getScopeName()); //生成bean名称 String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry)); //处理通用定义注解,包含@Lazy、@Primary、@DependsOn、@Role、@Description,将其对应的值设置到AnnotatedGenericBeanDefinition中 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); } } //构建bean定义holder对象 BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName); //根据bean定义的代理模式,确定是否生成一个代理的bean定义,决定后续生成bean的时候是否生成代理对象 definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); //最后将bean定义注册到beanFactory中 BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry); }经过以上的流程处理,我们最终识别出sources关联的注解并将他们解析成BeanDefinition注册到beanFactory中,为后续bean的实例化做准备。
注:spring boot 版本为3.2.3