Spring IOC source code analysis (based on annotations)

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
		this();
		register(componentClasses);
		refresh();
}

review

Review the basic process in the previous section.

The main function of this() method is to complete the initialization operation of the SpringIOC container. This includes the following points:

  1. Create BeanDefinitionReader, bean definition reader. The reader reads the corresponding ioc container instance. Obtain the beanFactory.
  2. Calculate the conditions that need to be injected into the IOC container bean
  3. Set up dependencies and automatic resolution procedures for beanFactory.
  4. Provide post-processing procedures for the IOC container, including the scope of bena, the role of beans, etc.
  5. Complete the registration of IOC internal beans. Registered to the registry holder BeanDefinitionHolder
  6. Create BeanDefinitionScanner, bean definition scanner. Scan the beans inside the IOC container. Then filter out beans that do not need to be scanned at this time. Such as @Service, @Controller, etc. Because this is the initialization of IOC internal beans.

Next, let's look at the register(componentClasses) method, at this time we get the bean defined by ourselves. componentClasses=AppConfig.class.

register(componentClasses)

	public void register(Class<?>... componentClasses) {
		Assert.notEmpty(componentClasses, "At least one component class must be specified");
		StartupStep registerComponentClass = this.getApplicationStartup().start("spring.context.component-classes.register")
				.tag("classes", () -> Arrays.toString(componentClasses));
		this.reader.register(componentClasses);
		registerComponentClass.end();
	}

Registration is done in the reader. The above is just a facade method. The register() method of AnnotatedBeanDefinitionReader is called. This is actually a facade method.

public void register(Class<?>... componentClasses) {
		for (Class<?> componentClass : componentClasses) {
			registerBean(componentClass);
		}
	}

The final implementation is in the doRegisterBean method.

private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
			@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
			@Nullable BeanDefinitionCustomizer[] customizers) {
		//1 创建了通用的bean定义实例。
		AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
		if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
			//2 这里判断要不要将该bean添加到IOC容器当中。一般和@Conditional注解有关
			return;
		}

		abd.setInstanceSupplier(supplier);
		ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
		//3 scopeMetadata.getScopeName()=singleton 在这里设置了单例模式。默认为单例
		abd.setScope(scopeMetadata.getScopeName());
		//4 获取bean的名称,默认首字母小写
		String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
		//这里对bean做一些处理。设置是否懒加载、是否私有、设置依赖关系、设置bean角色以及bean的描述。此时的设置保存在abd中
		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定义持有者。bean的描述
		BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
		//根据bean的作用域设置代理模式,获取代理之后的definitionHolder。
		definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
		BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
	}

Finally, the registration of the bean is completed in the registerBeanDefinition() method of BeanDefinitionReaderUtils. In fact, it is also a facade method. Completed in DeaultListableFactory.

In the end, the bean information is mainly in the following collection:

this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
There are two fields in DeaultListableFactory 
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256); key=beanName,value=BeanDefinition 
priate volatile List<String> beanDefinitionNames = new ArrayList<>(256); this List collection It mainly stores all the names of the beans.

 

Guess you like

Origin blog.csdn.net/GoSaint/article/details/109996871