赞
踩
在前面的自动扫描bean原理这篇文章中,主要说的是spring是如何将@ComponentScan注解声明的包下,加了@Component注解的业务类扫描到spring容器中的;在这篇文章中,没有说明一个知识点,在这里说明一下:
spring将业务类转换为BeanDefinition的方式有三种
这个gif是我们今天要说的源码,前面的调用逻辑,这里其实就是要调用到
org.springframework.context.annotation.ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
这个方法的逻辑;该方法是什么时候执行到的,为什么要执行这个方法,我在上篇博客中有写到;这里我们只关心@Bean的处理逻辑:
我们来看上个gif最后调用的方法
org.springframework.context.annotation.ConfigurationClassParser#parse(java.util.Set<org.springframework.beans.factory.config.BeanDefinitionHolder>) public void parse(Set<BeanDefinitionHolder> configCandidates) { this.deferredImportSelectors = new LinkedList<>(); for (BeanDefinitionHolder holder : configCandidates) { BeanDefinition bd = holder.getBeanDefinition(); try { /** * 根据beanDefinition的不同来做不同的处理 * 如果bean是配置类(加了@Configuration注解的配置类),那这里就会走下面的第一个分支的判断条件 * 因为在将配置类放到beanDefinitionMap中的时候,是将配置类声明为了AnnotatedGenericBeanDefinition类型的 */ if (bd instanceof AnnotatedBeanDefinition) { /** * 如果将bean存入到beanDefinitionMap第四步 * * 在这里注入的只是普通的bean,普通的bean 就是指加了@Component注解的bean * 何为不普通的bean? @Bean 各种beanFactoryPostProcessor获取到的bean不在这里注入 但是是在这里解析 只是不是在这里put到BeanDefinitionMap中的 */ 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()); } } } processDeferredImportSelectors(); }
这里会根据beanDefinition的不同类型,来进行不同的处理;由于这里的configCandidates是配置类,所以是AnnotatedBeanDefinition,因为在前面调用AnnotationConfigApplicationContext构造方法的时候,会把配置类注入到BeanDefinitionMap中,创建的是AnnotatedGenericBeanDefinition类型的
在parse()方法中,会执行以下的调用链,中间的一些细节,我们暂时不做解析,我们来看doProcessConfigurationClass()方法
org.springframework.context.annotation.ConfigurationClassParser#parse(org.springframework.core.type.AnnotationMetadata, java.lang.String)
org.springframework.context.annotation.ConfigurationClassParser#processConfigurationClass
org.springframework.context.annotation.ConfigurationClassParser#doProcessConfigurationClass
@Nullable protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass) throws IOException { // Process any @ComponentScan annotations /** * 序号1: * 判断类中是否加了@ComponentScan注解 * 从matedata 里面拿出@ComponentScan注解的属性信息,在后面的方法中,从这个属性里面获取到value,也就是要扫描的包进行注入 */ 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 /** * 如果将bean存入到beanDefinitionMap第6步 * * 扫描所有的普通类 * 当这个方法执行完之后,将配置类上@ComponentScan要注入的bean已经注入到map中了 * 但是如果配置类有@Import的话,是在下面processImports()完成的 * * 这里是获取到当前配置类下的所有的要扫描的包路径信息 */ Set<BeanDefinitionHolder> scannedBeanDefinitions = this<
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。