Skip to content

Commit

Permalink
doc: personal interpretation and comments on the newly added Spring S…
Browse files Browse the repository at this point in the history
…can process in Chinese
  • Loading branch information
Yangushan committed Mar 17, 2024
1 parent 6d949bd commit 550059c
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,9 @@ public void setAbstract(boolean abstractFlag) {
/**
* Return whether this bean is "abstract", i.e. not meant to be instantiated
* itself but rather just serving as parent for concrete child bean definitions.
* 如果是一个抽象的BeanDefinition,则不会生成真正的bean,设置为abstract的BeanDefiintion一般是给子类定义一些公共的属性
* 如果一个类的parent设置了这个类就是它的子类,而父类中定义的一些属性会被子类继承,比如子类没有设置scope,父类定义了则子类会继承父类的scope
* abstract的BeanDefinition一般是可以这么使用的
*/
@Override
public boolean isAbstract() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,14 @@ public class AnnotationBeanNameGenerator implements BeanNameGenerator {
@Override
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
if (definition instanceof AnnotatedBeanDefinition) {
// 从我们的注解上拿
String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition);
if (StringUtils.hasText(beanName)) {
// Explicit bean name found.
return beanName;
}
}
// 如果注解没有设置,则从我们的类的名字上首字母小写的方式(如果第一个第二个字母都是大写则直接返回)
// Fallback: generate a unique default bean name.
return buildDefaultBeanName(definition, registry);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,10 @@ public class AnnotationConfigApplicationContext extends GenericApplicationContex
*/
public AnnotationConfigApplicationContext() {
StartupStep createAnnotatedBeanDefReader = getApplicationStartup().start("spring.context.annotated-bean-reader.create");
// BeanDefinition 的读取器
this.reader = new AnnotatedBeanDefinitionReader(this);
createAnnotatedBeanDefReader.end();
// 扫描器
this.scanner = new ClassPathBeanDefinitionScanner(this);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,10 +230,19 @@ else if (registry instanceof GenericApplicationContext) {
}
}

/**
* 解析@Lazy, @DependsOn @Role @Primary @Description注解
* @param abd
*/
public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) {
processCommonDefinitionAnnotations(abd, abd.getMetadata());
}

/**
* 解析@Lazy, @DependsOn @Role @Primary @Description注解
* @param abd
* @param metadata
*/
static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);
if (lazy != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean u
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
this.registry = registry;

// 注册默认的includeFilters,也就是@Component
if (useDefaultFilters) {
registerDefaultFilters();
}
Expand Down Expand Up @@ -273,22 +274,34 @@ protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
for (String basePackage : basePackages) {
// 获取包路径下所有的BeanDefinition
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
// 遍历
for (BeanDefinition candidate : candidates) {
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
// 获取beanName
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);

// 给BeanDefinition对象里面的一些字段设置一些默认的值
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}

if (candidate instanceof AnnotatedBeanDefinition) {
// 解析@Lazy, @DependsOn @Role @Primary @Description注解
// 设置到BeanDefinition里面
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}

// 再次检查,判断beanName是否重复了
if (checkCandidate(beanName, candidate)) {
// 如果校验通过,则把beanDefinition包装成BeanDefinitionHolder
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
// 注册,也就是放入Map
registerBeanDefinition(definitionHolder, this.registry);
}
}
Expand Down Expand Up @@ -341,6 +354,8 @@ protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition)
if (originatingDef != null) {
existingDef = originatingDef;
}
// 是否兼容,如果兼容返回false表示不会重新注册spring容器,否则抛出冲突异常
// 比如有可能相同的一个类被扫描2次
if (isCompatible(beanDefinition, existingDef)) {
return false;
}
Expand All @@ -361,6 +376,7 @@ protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition)
* new definition to be skipped in favor of the existing definition
*/
protected boolean isCompatible(BeanDefinition newDef, BeanDefinition existingDef) {
// 两个类是否兼容,是否可能是同一个类被扫描多次
return (!(existingDef instanceof ScannedGenericBeanDefinition) || // explicitly registered overriding bean
(newDef.getSource() != null && newDef.getSource().equals(existingDef.getSource())) || // scanned same file twice
newDef.equals(existingDef)); // scanned equivalent class twice
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ public void resetFilters(boolean useDefaultFilters) {
*/
@SuppressWarnings("unchecked")
protected void registerDefaultFilters() {
// 这里把Component放入到includeFilters里面了
this.includeFilters.add(new AnnotationTypeFilter(Component.class));
ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
try {
Expand Down Expand Up @@ -311,9 +312,13 @@ public final MetadataReaderFactory getMetadataReaderFactory() {
* @return a corresponding Set of autodetected bean definitions
*/
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
// 这个componentsIndex是当我们在META-INF下如果使用了一个spring.components文件,那么就会根据这个文件的配置和basePackage来过滤beanDefinition
// 需要注意的是,当使用这种方式去定义bean的时候,也要在对应的文件上加上@Component注解,如果不加注解在文件中配置了也不会被当作是一个bean
// 所以当我们在这个配置文件中配置了bean之后,需要在配置文件中定义+在类上注解两者一起才能生效
if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
}
// 正常情况下使用这个流程来加在beanDefinition
else {
return scanCandidateComponents(basePackage);
}
Expand Down Expand Up @@ -418,6 +423,7 @@ private Set<BeanDefinition> addCandidateComponentsFromIndex(CandidateComponentsI
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
Set<BeanDefinition> candidates = new LinkedHashSet<>();
try {
// 获取package下的所有文件
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + '/' + this.resourcePattern;
Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
Expand All @@ -428,10 +434,14 @@ private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
logger.trace("Scanning " + resource);
}
try {
// 获取资源的元数据
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
// 判断是否是component(就是excludeFilter和includeFilter的判断,includeFilter默认就会读取component注解)
if (isCandidateComponent(metadataReader)) {
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setSource(resource);
// 判断你这个类是否是独立的(静态内部类或者正常类而不是普通内部类),或者是否是接口或者抽象类
// 如果是抽象类实现了@Lookup方法页可以
if (isCandidateComponent(sbd)) {
if (debugEnabled) {
logger.debug("Identified candidate component class: " + resource);
Expand Down Expand Up @@ -491,6 +501,8 @@ protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOE
return false;
}
}
// 符合includeFilters的才会当作是bean,默认里面会有一个component注解,在构造方法里面指定的
// 如果符合了再判断是否有Conditional注解,如果有则判断是否符合条件
for (TypeFilter tf : this.includeFilters) {
if (tf.match(metadataReader, getMetadataReaderFactory())) {
return isConditionMatch(metadataReader);
Expand Down

0 comments on commit 550059c

Please sign in to comment.