• 【Spring-3】ConfigurationClassPostProcessor解析配置类


    通过ConfigurationClassPostProcessor处理器,将我们自己编写的类注册到IOC容器中。

    直接看方法org.springframework.context.annotation.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);
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    ConfigurationClassPostProcessor#processConfigBeanDefinitions,见名知意,处理配置bd.

    	public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
    		List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
    		// 得到目前为止,所有注册的bd.
    		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));
    			}
    		}
    
    		// 目前为止筛选出所有@Configuration的bd.
    
    
    
    		// Return immediately if no @Configuration classes were found
    		if (configCandidates.isEmpty()) {
    			return;
    		}
    
    		// 进行了排序操作。
    		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
    		SingletonBeanRegistry sbr = null;
    		if (registry instanceof SingletonBeanRegistry) {
    			sbr = (SingletonBeanRegistry) registry;
    			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();
    		}
    
    		// 创建配置类解析器。
    		ConfigurationClassParser parser = new ConfigurationClassParser(
    				this.metadataReaderFactory, this.problemReporter, this.environment,
    				this.resourceLoader, this.componentScanBeanNameGenerator, registry);
    
    		Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
    		Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
    		do {
    			// 解析配置类集合
    			// 这里的解析是指解析配置类中的注解,然后解析为ConfigurationClass实例中属性信息
    			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
    			if (this.reader == null) {
    				this.reader = new ConfigurationClassBeanDefinitionReader(
    						registry, this.sourceExtractor, this.resourceLoader, this.environment,
    						this.importBeanNameGenerator, parser.getImportRegistry());
    			}
    			// 将这些配置类信息,变为bd中的信息,注册到ioc容器中
    			this.reader.loadBeanDefinitions(configClasses);
    			alreadyParsed.addAll(configClasses);
    
    			candidates.clear();	
    			
    			// 这里的循环,就是做到完全解析,没有漏掉的
    			
    			if (registry.getBeanDefinitionCount() > candidateNames.length) {
    				String[] newCandidateNames = registry.getBeanDefinitionNames();
    				Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
    				Set<String> alreadyParsedClasses = new HashSet<>();
    				for (ConfigurationClass configurationClass : alreadyParsed) {
    					alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
    				}
    				for (String candidateName : newCandidateNames) {
    					if (!oldCandidateNames.contains(candidateName)) {
    						BeanDefinition bd = registry.getBeanDefinition(candidateName);
    						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
    		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.
    			((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

    关于while循环解析的这块:
    怎么会有已经注册了bd但是没有解析的配置类呢?

    关于解析类的筛选条件。

    		Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
    		if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
    			beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
    		}
    		else if (config != null || isConfigurationCandidate(metadata)) {
    			beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
    		}
    		else {
    			return false;
    		}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    如果有Configuration注解,并且表标注的proxyBeanMethods是true,那么就重量级模式解析,什么是重量级模式呢?就是@Bean方法,调用本类中@bean的方法时,先从容器中取,没有的话在调用方法,这个实现是用代理实现的。
    如果没有Configuration注解,但是有Component,ComponentScan,Import,ImportResource,或者类中有@bean方法,则会用轻量级模式解析。也就是说,不用加一层代理了,调用方法就会直接调用本类的方法。

    主要是两块内容,
    1,将配置类解析为ConfigurationClass
    2,将ConfigurationClass注册到容器中。


    解析配置类为ConfigurationClass
    每一个配置类对应一个ConfigurationClass对象

    	protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
    		processConfigurationClass(new ConfigurationClass(metadata, beanName));
    	}
    
    	protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {	
    		// 解析配置的时候,检查顺序等问题,暂时方法
    		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);
    			}
    		}
    
    		// 又创建了一个SourceClass对象,是配置类的
    		SourceClass sourceClass = asSourceClass(configClass);
    		do {
    			sourceClass = doProcessConfigurationClass(configClass, sourceClass);
    		}
    		while (sourceClass != null);
    
    		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
    	protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
    			throws IOException {
    		
    		// 有内部类的,符合条件先解析内部类的
    		if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
    			// Recursively process any member (nested) classes first
    			processMemberClasses(configClass, sourceClass);
    		}
    
    		// 属性配置文件的解析,难度不大,不单独说了,就解析配置文件然后放到Environment中
    		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");
    			}
    		}
    
    		// 扫描包注解。
    		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) {
    				// 返回的是扫描得到的所有的bd。componentScanParser直接将扫描到的注册了
    				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();
    					}
    					if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
    						parse(bdCand.getBeanClassName(), holder.getBeanName());
    					}
    				}
    			}
    		}
    
    		// 解析Importh注解
    		processImports(configClass, sourceClass, getImports(sourceClass), 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;
    	}
    
    • 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

    解析内部类源码分析
    解析ComponentScans注解分析
    解析Import注解分析
    解析@Bean注解分析

    小结梳理:
    解析配置类,如果配置类中有内部配置类,先解析内部配置类。

    如果配置类PropertySource属性,会解析出文件中的属性-值,放入到环境变量中。

    如果有ComponentScan注解,会将扫描包中的类,如果有@Component注解类型的类,会作为候选类,封装为bd,注册进bean工厂。通过时在候选的类中,如果有配置类(@Configuration标注),会走解析配置类的逻辑。

    如果有Import注解,最后会将其作为配置类处理。

    如果类中有@Bean标注的方法,会找出所有方法,并封装成BeanMethod,放入配置类的缓存中。

    配置类解析完成之后,发现只有ComponentScan的逻辑有注册bean工厂的逻辑,其他的都是解析自己的部分,放入配置类中的缓存中。下面就看下如果从配置类的中加载出信息并封装为bd注册进bean工厂。


    根据ConfigurationClass的属性封装为bd,注册到容器中。


    org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions

    // 配置类解析得到所有的configurationClasses
    Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
    configClasses.removeAll(alreadyParsed);
    
    // Read the model and create bean definitions based on its content
    if (this.reader == null) {
    	this.reader = new ConfigurationClassBeanDefinitionReader(
    			registry, this.sourceExtractor, this.resourceLoader, this.environment,
    			this.importBeanNameGenerator, parser.getImportRegistry());
    }
    // 加载配置类。
    this.reader.loadBeanDefinitions(configClasses);
    alreadyParsed.addAll(configClasses);
    processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    	public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
    		TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
    		// 遍历每一个配置类
    		for (ConfigurationClass configClass : configurationModel) {
    			loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    	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的类。
    		if (configClass.isImported()) {
    			registerBeanDefinitionForImportedConfigurationClass(configClass);
    		}
    		// 处理@bean方法
    		for (BeanMethod beanMethod : configClass.getBeanMethods()) {
    			loadBeanDefinitionsForBeanMethod(beanMethod);
    		}
    		// 处理ImportedResources
    		loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
    		// 处理import中 ImportBeanDefinitionRegistrar类型的
    		loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#registerBeanDefinitionForImportedConfigurationClass

    	private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) {
    		AnnotationMetadata metadata = configClass.getMetadata();
    		// 在这里封装成了bd,
    		AnnotatedGenericBeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata);
    
    		ScopeMetadata scopeMetadata = scopeMetadataResolver.resolveScopeMetadata(configBeanDef);
    		configBeanDef.setScope(scopeMetadata.getScopeName());
    		String configBeanName = this.importBeanNameGenerator.generateBeanName(configBeanDef, this.registry);
    		AnnotationConfigUtils.processCommonDefinitionAnnotations(configBeanDef, metadata);
    
    		BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(configBeanDef, configBeanName);
    		definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
    		// 注册bd
    		this.registry.registerBeanDefinition(definitionHolder.getBeanName(), definitionHolder.getBeanDefinition());
    		configClass.setBeanName(configBeanName);
    
    		if (logger.isTraceEnabled()) {
    			logger.trace("Registered bean definition for imported class '" + configBeanName + "'");
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    处理Bean方法。
    org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForBeanMethod

    	private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
    		ConfigurationClass configClass = beanMethod.getConfigurationClass();
    		MethodMetadata metadata = beanMethod.getMetadata();
    		String methodName = metadata.getMethodName();
    
    		// Do we need to mark the bean as skipped by its condition?
    		if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) {
    			configClass.skippedBeanMethods.add(methodName);
    			return;
    		}
    		if (configClass.skippedBeanMethods.contains(methodName)) {
    			return;
    		}
    
    		AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);
    		Assert.state(bean != null, "No @Bean annotation attributes");
    
    		// 如果Bean没有配置name,会使用方法名
    		List<String> names = new ArrayList<>(Arrays.asList(bean.getStringArray("name")));
    		String beanName = (!names.isEmpty() ? names.remove(0) : methodName);
    
    		// Register aliases even when overridden
    		for (String alias : names) {
    			this.registry.registerAlias(beanName, alias);
    		}
    
    		// Has this effectively been overridden before (e.g. via XML)?
    		if (isOverriddenByExistingDefinition(beanMethod, beanName)) {
    			if (beanName.equals(beanMethod.getConfigurationClass().getBeanName())) {
    				throw new BeanDefinitionStoreException(beanMethod.getConfigurationClass().getResource().getDescription(),
    						beanName, "Bean name derived from @Bean method '" + beanMethod.getMetadata().getMethodName() +
    						"' clashes with bean name for containing configuration class; please make those names unique!");
    			}
    			return;
    		}
    		// 封装为bd信息
    		ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata, beanName);
    		beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));
    
    		// Bean标注的方法,类似于工厂方法,设置工厂实例的名称为配置类
    		if (metadata.isStatic()) {
    			// static @Bean method
    			if (configClass.getMetadata() instanceof StandardAnnotationMetadata) {
    				beanDef.setBeanClass(((StandardAnnotationMetadata) configClass.getMetadata()).getIntrospectedClass());
    			}
    			else {
    				beanDef.setBeanClassName(configClass.getMetadata().getClassName());
    			}
    			beanDef.setUniqueFactoryMethodName(methodName);
    		}
    		else {
    			// instance @Bean method
    			beanDef.setFactoryBeanName(configClass.getBeanName());
    			beanDef.setUniqueFactoryMethodName(methodName);
    		}
    
    		if (metadata instanceof StandardMethodMetadata) {
    			beanDef.setResolvedFactoryMethod(((StandardMethodMetadata) metadata).getIntrospectedMethod());
    		}
    		// 构造函数注入。
    		beanDef.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
    		beanDef.setAttribute(org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor.
    				SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);
    
    		AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);
    
    		Autowire autowire = bean.getEnum("autowire");
    		if (autowire.isAutowire()) {
    			beanDef.setAutowireMode(autowire.value());
    		}
    
    		boolean autowireCandidate = bean.getBoolean("autowireCandidate");
    		if (!autowireCandidate) {
    			beanDef.setAutowireCandidate(false);
    		}
    
    		String initMethodName = bean.getString("initMethod");
    		if (StringUtils.hasText(initMethodName)) {
    			beanDef.setInitMethodName(initMethodName);
    		}
    
    		String destroyMethodName = bean.getString("destroyMethod");
    		beanDef.setDestroyMethodName(destroyMethodName);
    
    		// Consider scoping
    		ScopedProxyMode proxyMode = ScopedProxyMode.NO;
    		AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(metadata, Scope.class);
    		if (attributes != null) {
    			beanDef.setScope(attributes.getString("value"));
    			proxyMode = attributes.getEnum("proxyMode");
    			if (proxyMode == ScopedProxyMode.DEFAULT) {
    				proxyMode = ScopedProxyMode.NO;
    			}
    		}
    
    		// Replace the original bean definition with the target one, if necessary
    		BeanDefinition beanDefToRegister = beanDef;
    		if (proxyMode != ScopedProxyMode.NO) {
    			BeanDefinitionHolder proxyDef = ScopedProxyCreator.createScopedProxy(
    					new BeanDefinitionHolder(beanDef, beanName), this.registry,
    					proxyMode == ScopedProxyMode.TARGET_CLASS);
    			beanDefToRegister = new ConfigurationClassBeanDefinition(
    					(RootBeanDefinition) proxyDef.getBeanDefinition(), configClass, metadata, beanName);
    		}
    
    		if (logger.isTraceEnabled()) {
    			logger.trace(String.format("Registering bean definition for @Bean method %s.%s()",
    					configClass.getMetadata().getClassName(), beanName));
    		}
    		this.registry.registerBeanDefinition(beanName, beanDefToRegister);
    	}
    
    • 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

    类似于工厂方法生产实例

    到此为止,spring自动注入的类,和自己写的类全部注入到容器中了,本片没有将spring自动注入类的逻辑,但看完import那块的逻辑,应该差不多能了解一点,其实就是调用selectImport方法,返回的都是类的全限定类名,而这些全限定类名就是从配置文件读取出来的(factory那个文件),而这些类会再次执行Processimport方法,再次作为配置类处理。

    从外部导入的和Componentscan不是一个逻辑,

    1. 从外部导入的会作为配置类,走解析配置类的逻辑,最后加载的时候注入到bean工厂中。
    2. Componentscan是用户自己扫描类,之后直接注入到bean工厂了。

    所以给别人使用的,类似于MybatisAutoConfiguration,需要注入到容器中的类都是通过@bean注解注入的,是不能用@Component,@service,@controller,这些注解的,这些注解应该是配合@ComponentScan使用的。是使用者用的。如果作为第三方,提供别人使用的(类似于MybatisAutoConfiguration),还是要通过一个配置类,需要注入的对象放在配置类中,通过@Bean放入容器。

  • 相关阅读:
    Vuex学习笔记
    【废话文学】各种概念混搭
    prompt 提示词如何写?
    QEMU模拟mini2440开发环境
    Taurus.MVC WebMVC 入门开发教程3:数据绑定Model
    408数据结构算法题目
    vite打包流程和原理
    [springboot]结合redis详述声明式缓存注解的使用-Cacheable、CacheEvict、CachePut、Caching
    vim以16进制打开和编辑文件
    数据集笔记:华盛顿共享单车OD数据
  • 原文地址:https://blog.csdn.net/qq_34501351/article/details/118364986