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:
- Create BeanDefinitionReader, bean definition reader. The reader reads the corresponding ioc container instance. Obtain the beanFactory.
- Calculate the conditions that need to be injected into the IOC container bean
- Set up dependencies and automatic resolution procedures for beanFactory.
- Provide post-processing procedures for the IOC container, including the scope of bena, the role of beans, etc.
- Complete the registration of IOC internal beans. Registered to the registry holder BeanDefinitionHolder
- 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.