Spring5源码分析-注册配置类

 上一篇:Spring5源码分析-容器自身初始化已经准备好容器,这一篇就是要本身的Java配置类注册到beanDefinitionMaps当中,好让ConfigurationCLassPostProcessor对Java配置类上面的注解进行分析,是否执行包路径下符合Spring规则的类进行扫描并完成注册和实例化等java

方法的调用栈:spring

doRegisterBean:254, AnnotatedBeanDefinitionReader (org.springframework.context.annotation)
registerBean:147, AnnotatedBeanDefinitionReader (org.springframework.context.annotation)
register:137, AnnotatedBeanDefinitionReader (org.springframework.context.annotation)
register:183, AnnotationConfigApplicationContext (org.springframework.context.annotation)
main:12, AutowiredAnnotationMain (com.jv.spring.autowiredannotation)

核心方法代码注释:数组

private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
			@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
			@Nullable BeanDefinitionCustomizer[] customizers) {
		//根据配置类生成的BeanDefinition
		AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
		//根据@Conditional是否要注册这个BeanDefinition  在SpringBoot中大量使用
		if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
			return;
		}

		abd.setInstanceSupplier(supplier);
		//获取类的Scope(ConfigurableBeanFactory中定义了范围--singlton/prototype )
		ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
		abd.setScope(scopeMetadata.getScopeName());
		//生成Bean的名称  若是注解中没有指定Bean的名称,则默认按照这种方式生成:类名-FooServiceImpl BeanName-fooServiceImpl
		String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
		//扫描并处理Bean的一些特性,好比Lazy Primary DependsON等等 ,如abd.setLazyInit(true)
		AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
		//目前只看了Spring的源码,默认传过来的qualifiers都是为NULL的,能够本身改一下Spring的代码,调用时传一个Annotation数组过来,数组里面包含@Primary@Lazy
		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);
			}
		}
		//一个BeanDefinition包装类,把AnnotatedGenericBeanDefinition和名称放到袋子中
		BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);

		/**
		 * 里面根据definitionHolder.getBeanDefinition复制了一个BeanDefinition,也就是proxyBeanDefinition
		 * 原来的BeanDefinition重置了两个参数:
		 * ——autowireCandidate=0 不能被用于自动注入
		 * ——primary=false 再也不是主Bean
		 *
		 * 说了这么多,我也不知道何时会用到,听说是SpringMVC很是有用,只是用Spring的话,还用不到,后面再关注具体的使用场景和细节
		 */
		definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
		//将自定义的配置类(XXXConfig.class)扫描、解析并放到beanDefinitionMap中
		BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
	}

总结:就是将我本身定义的AutowiredAnnotationConfig对应的BeanDefinition放到beanDefinitionMaps当中,其余的分支流程其实都进不去,好比qualifiers customizers都是null,因此涉及到的分支也不会被执行。app

截止到目前Spring尚未提供什么扩展点给开发人员使用,接下来就会慢慢开始接触到很是多的扩展点和咱们经常使用一些注解的逻辑实现。这里还有一个番外篇:使用register()直接注册一个非@Configuration修饰的Bean,能够直接getBean()源码分析

相关文章
相关标签/搜索