• spring5.0源码解析 之 ConfigurationClassPostProcessor


    ConfigurationClassPostProcessor 的介绍

    在这里插入图片描述
    从图中可以看出 ConfigurationClassPostProcessor 的继承关系,首先 他 实现了一些Aware 可以获取到,环境和容器相关的属性,具体可以看这篇文章。

    spring5.0 源码解析 initializeBean
    同时 他实现了 BeanDefinitionRegistryPostProcessor
    BeanDefinitionRegistryPostProcessor 又继承了 BeanFactoryPostProcessor
    在容器启动阶段执行这两个方法,具体的执行顺序可以看这篇文章

    spring5.0 源码解析(day03) invokeBeanFactoryPostProcessors(beanFactory)

    	void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
    	
    	void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
    
    • 1
    • 2
    • 3

    postProcessBeanDefinitionRegistry

    在 postProcessBeanDefinitionRegistry 方法中可以获得 BeanDefinitionRegistry 对象,BeanDefinitionRegistry 保存了bean的注册信息 beanDefinition 的相关信息

    具体的方法实现

    // 获取 registry 的 hashCode
    		int registryId = System.identityHashCode(registry);
    		// 判断 这个 registry 已经执行过 或者正在执行
    		if (this.registriesPostProcessed.contains(registryId)) {
    			throw new IllegalStateException(
    					"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
    		}
    		// 判断 这个 registry 已经执行过 或者正在执行
    		if (this.factoriesPostProcessed.contains(registryId)) {
    			throw new IllegalStateException(
    					"postProcessBeanFactory already called on this post-processor against " + registry);
    		}
    		this.registriesPostProcessed.add(registryId);
    		// 从名称上可以看出 处理  BeanDefinitions 的配置
    		processConfigBeanDefinitions(registry);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    processConfigBeanDefinitions 对多个配置类的循环解析

    解析配置类相关信息 , 并把解析到的bean定义注册到 registry
    从下面的方法可以看出 具体的 candidate 的解析 是委托 ConfigurationClassParser 处理的 ,通过 配置类解析器的 parse 方法完成解析的

    	public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
    		List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
    		// 获取所有 的 BeanDefinition 全限名
    		String[] candidateNames = registry.getBeanDefinitionNames();
    		// 循环处理
    		for (String beanName : candidateNames) {
    			// 通过 registry 获取 BeanDefinition
    			BeanDefinition beanDef = registry.getBeanDefinition(beanName);
    			// 检验 BeanDefinition 的 属性中是否含有 configurationClass 属性  我认为这里是 标记 beanDef 的作用 已经被标记的代表已经处理完成
    			if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
    				if (logger.isDebugEnabled()) {
    					logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
    				}
    			}
    			// 检查 beanDef 是否是个配置类的候选者,如果是做个标记。
    			// beanDef 拥有 @Configuration 或 @Component 或 @ComponentScan 或 @Import 或 @ImportResource 其中的一个注解,那它就是配置类的候选者
    			else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
    				 // 保存  BeanDefinitionHolder 为一个 配置的候选者
    				configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
    			}
    		}
    
    		// Return immediately if no @Configuration classes were found
    		if (configCandidates.isEmpty()) {
    			return;
    		}
    
    		// Sort by previously determined @Order value, if applicable
    		// 按照优先级排序
    		configCandidates.sort((bd1, bd2) -> {
    			int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
    			int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
    			return Integer.compare(i1, i2);
    		});
    
    		// Detect any custom bean name generation strategy supplied through the enclosing application context
    		// 检查bean 的生成策略  是否为 singleton
    		SingletonBeanRegistry sbr = null;
    		if (registry instanceof SingletonBeanRegistry) {
    			sbr = (SingletonBeanRegistry) registry;
    			// 获取 一个 beanName 生成器
    			if (!this.localBeanNameGeneratorSet) {
    				BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
    						AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
    				if (generator != null) {
    					this.componentScanBeanNameGenerator = generator;
    					this.importBeanNameGenerator = generator;
    				}
    			}
    		}
    		// 保证环境变量不能为空
    		if (this.environment == null) {
    			this.environment = new StandardEnvironment();
    		}
    
    		// Parse each @Configuration class
    		// 获取 一个 Configuration 的解析器 主要为了解析  @Configuration 注解
    		ConfigurationClassParser parser = new ConfigurationClassParser(
    				this.metadataReaderFactory, this.problemReporter, this.environment,
    				this.resourceLoader, this.componentScanBeanNameGenerator, registry);
    		// 报错 所有的 cofing 获选者
    		Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
    		// 记录已经解析出来并已经读取完 BeanDefinition 的 ConfigurationClass
    		Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
    		// 循环解析
    		do {
    			StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
    			// 解析  candidates
    			parser.parse(candidates);
    			parser.validate();
    			// 获取所有解析到的
    			Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
    			configClasses.removeAll(alreadyParsed);
    
    			// Read the model and create bean definitions based on its content
    			// 初始化 BeanDefinitionReader 用来加载 解析到的 configClasses
    			if (this.reader == null) {
    				this.reader = new ConfigurationClassBeanDefinitionReader(
    						registry, this.sourceExtractor, this.resourceLoader, this.environment,
    						this.importBeanNameGenerator, parser.getImportRegistry());
    			}
    			// 加载  BeanDefinitions
    			this.reader.loadBeanDefinitions(configClasses);
    			// 记录已经解析完成 ConfigurationClass 并注册到  registry
    			alreadyParsed.addAll(configClasses);
    			processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();
    
    			candidates.clear();
    			// 如果 registry 中的bean定义 大于 candidateNames 的长度 说明有新的 ConfigurationClass 被加载进来
    			if (registry.getBeanDefinitionCount() > candidateNames.length) {
    				String[] newCandidateNames = registry.getBeanDefinitionNames();
    				Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
    				Set<String> alreadyParsedClasses = new HashSet<>();
    				// 记录以处理的  ConfigurationClass 的 class名称
    				for (ConfigurationClass configurationClass : alreadyParsed) {
    					alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
    				}
    				for (String candidateName : newCandidateNames) {
    					if (!oldCandidateNames.contains(candidateName)) {
    						BeanDefinition bd = registry.getBeanDefinition(candidateName);
    						// 把未处理的 放到 candidates 循环处理
    						if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
    								!alreadyParsedClasses.contains(bd.getBeanClassName())) {
    							candidates.add(new BeanDefinitionHolder(bd, candidateName));
    						}
    					}
    				}
    				candidateNames = newCandidateNames;
    			}
    		}
    		while (!candidates.isEmpty());
    
    		// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
    		// 将ImportRegistry注册为bean,以支持ImportAware@Configuration类
    		if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
    			sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
    		}
    
    		if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
    			// Clear cache in externally provided MetadataReaderFactory; this is a no-op
    			// for a shared cache since it'll be cleared by the ApplicationContext.
    			清除外部提供的MetadataReaderFactory中的缓存;这是一个无操作,因为它将被ApplicationContext清除
    			((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125

    ConfigurationClassParser.parse 方法 解析配置类

    parse 方法 用于根据不同的 BeanDefinition 定义选取不同的 parse 方法, 其实最终还是根据 processConfigurationClass 进行解析的。

    public void parse(Set<BeanDefinitionHolder> configCandidates) {
    		// 循环解析
    		for (BeanDefinitionHolder holder : configCandidates) {
    			BeanDefinition bd = holder.getBeanDefinition();
    			try {
    				// 根据把不同的 BeanDefinition 选择不同的解析方式  全是根据 processConfigurationClass 方法进行解析
    				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();
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    processConfigurationClass 方法 解析配置类

    这个方法主要判断 配置类是否被解析过 如果没有则 递归调用doProcessConfigurationClass解析 配置类的层次结构

    // 判断适应应该跳过该配置类
    		if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
    			return;
    		}
    		// 看这个类是否已经存在
    		ConfigurationClass existingClass = this.configurationClasses.get(configClass);
    		if (existingClass != null) {
    			// 判断配置类 是否被其他 配置类 import 如果是 直接合并
    			if (configClass.isImported()) {
    				if (existingClass.isImported()) {
    					// 将给定配置类中导入的by声明合并到此类中
    					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.
    				//找到显式bean定义,可能替换了导入。
    				//我们把旧的拿走,换新的。
    				this.configurationClasses.remove(configClass);
    				this.knownSuperclasses.values().removeIf(configClass::equals);
    			}
    		}
    
    		// Recursively process the configuration class and its superclass hierarchy.
    		// 递归处理 configClass 的 多层次结构
    		SourceClass sourceClass = asSourceClass(configClass, filter);
    		do {
    			sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
    		}
    		while (sourceClass != null);
    		// 保存 configClass
    		this.configurationClasses.put(configClass, configClass);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    doProcessConfigurationClass

    1. 处理@Component注解:
      如果当前配置类上存在@Component以及派生注解,包括@Repository、@Service、@Controller、@Configuration等注解,那么调用processMemberClasses方法递归内部类配置类。

    2. 处理属性资源文件,加了@PropertySource注解。
      解析出来的本地属性源会存入environment环境变量中。

    3. 处理@ComponentScans、@ComponentScan注解
      依靠ClassPathBeanDefinitionScanner的doScan方法 注册到 register 中

    4. 处理@Import注解。
      将扫描到的 Import 的类 保存到 ImportStack的imports 中 在上面说的processConfigBeanDefinitions方法中 read

    5. 处理@ImportResource注解
      这里仅仅对于@ImportResource注解引入的配置文件路径进行占位符的替换(从environment环境变量中查找),并方法替换后的路径和reader读取器通过addImportedResource方法存入configClass的importedResources缓存中,

    6. 处理加了@Bean注解的方法。
      用于通过方法引入bean定义,类似于工厂方法。这里同样将解析后的方法元数据通过addBeanMethod方法存入configClass的beanMethods缓存中,后续再继续处

    7. 通过processInterfaces()处理接口的默认方法,
      从JDK8开始,接口中的方法可以有自己的默认实现,因此,如果这个接口中的方法也加了@Bean注解,也需要被解析。(很少用)

    8. 解析父类,如果被解析的配置类继承了某个类,那么也会递归解析父类

    9. 如果没有符合规则的父类或者都解析完毕,那么返回null,将会在外层的processConfigurationClass中跳出循环,进行后续步骤

    该方法对于通过@ComponentScans、@ComponentScan注解引入的bean定义会添加到了容器中,但是对于@Import、@Bean、@ImportResource注解引入的bean定义并没有注册到容器中,而是在后面的processConfigBeanDefinitions 方法 调用 this.reader.loadBeanDefinitions()方法中才会真正的解析和注册。

    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注释
    		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");
    			}
    		}
    
    		// 处理 @ComponentScan 注解
    		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());
    					}
    				}
    			}
    		}
    
    		// 处理 @Import annotations
    		processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
    
    		// 处理 @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);
    			}
    		}
    
    		// 处理 @Bean methods
    		Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
    		for (MethodMetadata methodMetadata : beanMethods) {
    			configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
    		}
    
    		// 处理接口上的默认方法
    		processInterfaces(configClass, sourceClass);
    
    		// 处理超类,如果有的话
    		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();
    			}
    		}
    
    		// 没有超类->处理完成
    		return null;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82

    postProcessBeanFactory

    在执行完 postProcessBeanDefinitionRegistry 之后 会执行 postProcessBeanFactory
    ConfigurationClassPostProcessor 的 postProcessBeanFactory 主要作用 准备配置类,以便在运行时为bean请求提供服务通过用CGLIB增强的子类替换它们。

    @Override
    	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    		// 获取 hash值
    		int factoryId = System.identityHashCode(beanFactory);
    		// 查看是否以处理过 或正在处理
    		if (this.factoriesPostProcessed.contains(factoryId)) {
    			throw new IllegalStateException(
    					"postProcessBeanFactory already called on this post-processor against " + beanFactory);
    		}
    		this.factoriesPostProcessed.add(factoryId);
    		// 判断 registriesPostProcess 是否被执行过
    		if (!this.registriesPostProcessed.contains(factoryId)) {
    			// BeanDefinitionRegistryPostProcessor hook apparently not supported...
    			// Simply call processConfigurationClasses lazily at this point then.
    			processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
    		}
    		// 对加了@Configuration注解的配置类进行Cglib代理
    		enhanceConfigurationClasses(beanFactory);
    		// 添加一个BeanPostProcessor后置处理器
    		beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    在代码中可以看到 后置处理通过 enhanceConfigurationClasses 对加了@Configuration注解的配置类进行Cglib代理
    在此方法中 调用 配置类增强器 进行代理操作

    // 新建一个 配置类增强器
    		ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
    		// 遍历所有 配置类
    		for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
    			AbstractBeanDefinition beanDef = entry.getValue();
    			// If a @Configuration class gets proxied, always proxy the target class
    			// 如果@Configuration类被代理,则始终代理目标类
    			beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
    			// Set enhanced subclass of the user-specified bean class
    			// 设置用户指定bean类的增强子类
    			Class<?> configClass = beanDef.getBeanClass();
    			// 对配置类进行 增强
    			Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
    			if (configClass != enhancedClass) {
    				if (logger.isTraceEnabled()) {
    					logger.trace(String.format("Replacing bean definition '%s' existing class '%s' with " +
    							"enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName()));
    				}
    				beanDef.setBeanClass(enhancedClass);
    			}
    		}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    在 enhance 增强中 会设置 两个过滤器

    • BeanMethodInterceptor拦截器,将会拦截配置类中的@Bean方法 保证在单例情况下 调用bean方法只返回一个相同的实例
      对于被@Configuration注解及其派生注解标注的proxyBeanMethods属性的值为true(默认就是true)的配置类,内部的单例@Bean方法仅仅会被调用一次,用于创建对象,后续如果存在任何@Bean方法之间的调用,或者外部对象对@Bean方法的调用(这要求该对象交给Spring容器管理),都会是从容器中直接查找已创建的对象返回,不会再调用@Bean方法,能够保证是同一个实例,即都指向IoC内的单例。

    • BeanFactoryAwareMethodInterceptor拦截器,将会拦截setBeanFactory方法。
      拦截BeanFactoryAware的setBeanFactory方法回调,为"$$beanFactory"属性赋值,这里的拦截早于@Bean方法的拦截,在创建对象之后就马上调用了该方法

    ImportAwareBeanPostProcessor

    postProcessBeforeInitialization方法则是在initializeBean初始化bean的时候被调用 , 其作用是为EnhanceConfiguration类的beanFactory属性赋值。

    @Override
    		public Object postProcessBeforeInitialization(Object bean, String beanName) {
    			//如果是ImportAware类型
    			if (bean instanceof ImportAware) {
    				//获取IMPORT_REGISTRY_BEAN_NAME的bean实例,在前面的processConfigBeanDefinitions方法最后就注册了该名字的bean实例
    				ImportRegistry ir = this.beanFactory.getBean(IMPORT_REGISTRY_BEAN_NAME, ImportRegistry.class);
    				//获取引入当前类的类元数据的最后一个,当前类就是被@Import注解引入的普通类,引入类就是添加@Import注解的类
    				AnnotationMetadata importingClass = ir.getImportingClassFor(ClassUtils.getUserClass(bean).getName());
    				//设置到setImportMetadata方法参数中
    				if (importingClass != null) {
    					((ImportAware) bean).setImportMetadata(importingClass);
    				}
    			}
    			return bean;
    		}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    public PropertyValues postProcessProperties(@Nullable PropertyValues pvs, Object bean, String beanName) {
    			// Inject the BeanFactory before AutowiredAnnotationBeanPostProcessor's
    			// postProcessProperties method attempts to autowire other configuration beans.
    			//对于EnhancedConfiguration类型的代理对象注入beanFactory实例
    			if (bean instanceof EnhancedConfiguration) {
    				((EnhancedConfiguration) bean).setBeanFactory(this.beanFactory);
    			}
    			return pvs;
    		}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
  • 相关阅读:
    type=“text/javascript“的作用
    设计模式之十:状态模式
    ik分词器的基本使用
    Zuul、Gateway、nginx的区别
    PHP 发送电子邮件
    Java框架最全面试攻略,吃透这些问题,面试官奈你不何
    利用pytorch自定义CNN网络(四):损失函数和优化器
    LeetCode_前缀和_困难_862.和至少为 K 的最短子数组
    EPB功能开发与测试(基于ModelBase实现)
    二十三、设计模式之组合模式![
  • 原文地址:https://blog.csdn.net/qq_44808472/article/details/126310437