Back to Javatutorial

Spring启动流程(三):包的扫描流程

docs/Spring全家桶/Spring源码分析/Spring启动流程/Spring启动流程(三):包的扫描流程.md

1.0.025.5 KB
Original Source

applicationContext ĴУǷ applicationContext Ĵ̣ڱУǽ spring νаɨġ

AnnotationConfigApplicationContext Ĺ췽

public AnnotationConfigApplicationContext(String... basePackages) {
    this();
    //Դİɨ裬ɨɺ󣬻õһ BeanDefinition ļ
    scan(basePackages);
    refresh();
}

ǽĿ scan(basePackages); ϣ÷

AnnotationConfigApplicationContext#scan

public void scan(String... basePackages) {
     Assert.notEmpty(basePackages, "At least one base package must be specified");
     // scannerthis()д
     this.scanner.scan(basePackages);
}

ؼ this.scanner.scan(basePackages); scanner this() дĶ

public AnnotationConfigApplicationContext() {
    this.reader = new AnnotatedBeanDefinitionReader(this);
    // scanner ﴴ
    this.scanner = new ClassPathBeanDefinitionScanner(this);
}

׷٣ǶԲҪķصעɨḶ́

AnnotationConfigApplicationContext#AnnotationConfigApplicationContext(String...)
 |-AnnotationConfigApplicationContext#scan
  |-ClassPathBeanDefinitionScanner#scan
   |-ClassPathBeanDefinitionScanner#doScan

ClassPathBeanDefinitionScanner#doScan £

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) {
            //BeanDefinitionScope
            ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
            candidate.setScope(scopeMetadata.getScopeName());
            //鿴ǷǷָbeanƣûָʹĸСд
            String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
            //ifǴlazyAutowireDependencyOninitMethodenforceInitMethoddestroyMethod
            // enforceDestroyMethodPrimaryRoleDescriptionЩ߼
            if (candidate instanceof AbstractBeanDefinition) {
                postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
            }
            if (candidate instanceof AnnotatedBeanDefinition) {
                AnnotationConfigUtils.processCommonDefinitionAnnotations(
                        (AnnotatedBeanDefinition) candidate);
            }
            //beanǷ
            if (checkCandidate(beanName, candidate)) {
                //ְװһ
                BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
                //scopeǷ񴴽δд
                definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(
                        scopeMetadata, definitionHolder, this.registry);
                beanDefinitions.add(definitionHolder);
                //ע beanDefinition
                registerBeanDefinition(definitionHolder, this.registry);
            }
        }
    }
    return beanDefinitions;
}

δɵĹܺˣ¼£

  1. ݰ·õ BeanDefinition
  2. BeanDefinitionһḻ beanDefinition Ϣ
  3. BeanDefinition ӵ beanFactory

BeanDefinition Ҳ spring Ҫ֮һ BeanDefinition ķɲο spring ֮ BeanDefinition

ҪIJ

1. ݰ·õ BeanDefinition

һҪ Set<BeanDefinition> candidates = findCandidateComponents(basePackage);ǸȥִУɶԲҪ÷ĵ£

AnnotationConfigApplicationContext#AnnotationConfigApplicationContext(String...)
 |-AnnotationConfigApplicationContext#scan
  |-ClassPathBeanDefinitionScanner#scan
   |-ClassPathBeanDefinitionScanner#doScan
    |-ClassPathScanningCandidateComponentProvider#findCandidateComponents
     |-ClassPathScanningCandidateComponentProvider#scanCandidateComponents

յõ ClassPathScanningCandidateComponentProvider#scanCandidateComponents (ɾ)

private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
    Set<BeanDefinition> candidates = new LinkedHashSet<>();
    //װɨ·װɺָʽclasspath*:org/springframework/learn/demo01/**/*.class
    String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
            resolveBasePackage(basePackage) + '/' + this.resourcePattern;
    //·ȡԴ󣬼ɨ·µĵclassļõ Resource
    Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
    for (Resource resource : resources) {
        if (resource.isReadable()) {
            //ԴȡԴMetadataReader
            MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
            // £
            // 1\. ǷҪʼΪspring beanǷ @Component@Serviceע
            // 2\. 鿴Ƿ@Conditionalһϵеע⣬ȻǷעBean
            if (isCandidateComponent(metadataReader)) {
                ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
                sbd.setResource(resource);
                sbd.setSource(resource);
                if (isCandidateComponent(sbd)) {
                    candidates.add(sbd);
                }
            }
        }
    }
    return candidates;
}

Կϴ£

  1. ݴ basePackage õɨ·
  2. ɨ·õ·µ class ļӦ Resource
  3. Resource תΪ beanDefinition

Ǿϴз

1.1 basePackage õɨ·

һûɶ÷һַƴ滻 org.springframework.learn.demo01 תΪ classpath*:org/springframework/learn/demo01/**/*.classشһУ

String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
        resolveBasePackage(basePackage) + '/' + this.resourcePattern;

1.2 ɨ·

õɨ·󣬽ǽɨˡspring ɨʱɨ·µ class ļɨȻװ Resource

Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);

룬ͬأǶԲҪķֻã

AnnotationConfigApplicationContext#AnnotationConfigApplicationContext(String...)
 |-AnnotationConfigApplicationContext#scan
  |-ClassPathBeanDefinitionScanner#scan
   |-ClassPathBeanDefinitionScanner#doScan
    |-ClassPathScanningCandidateComponentProvider#findCandidateComponents
     |-ClassPathScanningCandidateComponentProvider#scanCandidateComponents
      |- GenericApplicationContext#getResources
       |-AbstractApplicationContext#getResources
        |-PathMatchingResourcePatternResolver#getResources
         |-PathMatchingResourcePatternResolver#findPathMatchingResources

ǽۼ PathMatchingResourcePatternResolver#findPathMatchingResources:

protected Resource[] findPathMatchingResources(String locationPattern) throws IOException {
    //  locationPattern  classpath*:org/springframework/learn/demo01/**/*.class
    // rootDirPath  classpath*:org/springframework/learn/demo01/
    String rootDirPath = determineRootDir(locationPattern);

    // subPattern  **/*.class
    String subPattern = locationPattern.substring(rootDirPath.length());

    // ﷵص Resource  rootDirPath ľ·(urlʾ)
    // URL [file:/xxx/spring-learn/build/classes/java/main/org/springframework/learn/demo01/]
    Resource[] rootDirResources = getResources(rootDirPath);

    Set<Resource> result = new LinkedHashSet<>(16);
    for (Resource rootDirResource : rootDirResources) {
        rootDirResource = resolveRootDirResource(rootDirResource);
        URL rootDirUrl = rootDirResource.getURL();
        if (equinoxResolveMethod != null && rootDirUrl.getProtocol().startsWith("bundle")) {
            URL resolvedUrl = (URL) ReflectionUtils.invokeMethod(equinoxResolveMethod, null, rootDirUrl);
            if (resolvedUrl != null) {
                rootDirUrl = resolvedUrl;
            }
            rootDirResource = new UrlResource(rootDirUrl);
        }
        //  vfs Դ
        if (rootDirUrl.getProtocol().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) {
            result.addAll(VfsResourceMatchingDelegate
                    .findMatchingResources(rootDirUrl, subPattern, getPathMatcher()));
        }
        // jarļ
        else if (ResourceUtils.isJarURL(rootDirUrl) || isJarResource(rootDirResource)) {
            result.addAll(doFindPathMatchingJarResources(rootDirResource, rootDirUrl, subPattern));
        }
        // ļ·µļ
        else {
            result.addAll(doFindPathMatchingFileResources(rootDirResource, subPattern));
        }
    }
    return result.toArray(new Resource[0]);
}

ָͨĴ£

  1. ͨ locationPattern õ pattern µ url ·װΪ Resource
  2. ص· class ļװΪ Resource

spring ν pattrn תΪ url ·ģǸ룺

|-PathMatchingResourcePatternResolver#getResources
 |-PathMatchingResourcePatternResolver#findAllClassPathResources
  |-PathMatchingResourcePatternResolver#doFindAllClassPathResources

մ뵽 PathMatchingResourcePatternResolver#doFindAllClassPathResources:

protected Set<Resource> doFindAllClassPathResources(String path) throws IOException {
    Set<Resource> result = new LinkedHashSet<>(16);
    ClassLoader cl = getClassLoader();
    // pathӦurl
    Enumeration<URL> resourceUrls = (cl != null ? cl.getResources(path) : 
            ClassLoader.getSystemResources(path));
    while (resourceUrls.hasMoreElements()) {
        URL url = resourceUrls.nextElement();
        // urlתΪResourceӵ
        result.add(convertClassLoaderURL(url));
    }
    if ("".equals(path)) {
        addAllClassLoaderJarRoots(cl, result);
    }
    return result;
}

// urlתΪResource
protected Resource convertClassLoaderURL(URL url) {
    return new UrlResource(url);
}

ʱ path Ϊ org/springframework/learn/demo01/Ӵ֪յ java ClassLoader ȡ path Ӧ urlȻ url תΪ Resource ӵвء

õľ·֮󣬽¾Ƕ·бõ class ļˡٻص PathMatchingResourcePatternResolver#findPathMatchingResourcesspring ɨʱݴ url ͣɨ 3 ط

  1. vfs
  2. jar
  3. ļ·

vfs ע˵ "URL protocol for a general JBoss VFS resource"ͨ JBoss VFS Դ URL Э飬ﲻĿ jar Ҫɨ jar е·ͻʹ jar ɨ跽ʽ class ļңڵʱdemo01 ʹļʽɨģصļɨ跽ʽ jar ɨģȤСо¡

Ǹ findPathMatchingResources

|-PathMatchingResourcePatternResolver#findPathMatchingResources
 |-PathMatchingResourcePatternResolver#doFindPathMatchingFileResources
  |-PathMatchingResourcePatternResolver#doFindMatchingFileSystemResources

protected Set<Resource> doFindMatchingFileSystemResources(File rootDir, 
            String subPattern) throws IOException {
    // ļ
    Set<File> matchingFiles = retrieveMatchingFiles(rootDir, subPattern);
    Set<Resource> result = new LinkedHashSet<>(matchingFiles.size());
    for (File file : matchingFiles) {
        result.add(new FileSystemResource(file));
    }
    return result;
}

PathMatchingResourcePatternResolver#doFindMatchingFileSystemResources Уspring ɨ赽 File תΪ FileSystemResource 棬ĵڶ Resource (ǰΪ UrlResourceΪ FileSystemResource).

صע Set<File> matchingFiles = retrieveMatchingFiles(rootDir, subPattern); spring ļҵģ

|-PathMatchingResourcePatternResolver#findPathMatchingResources
 |-PathMatchingResourcePatternResolver#doFindPathMatchingFileResources
  |-PathMatchingResourcePatternResolver#doFindMatchingFileSystemResources
   |-PathMatchingResourcePatternResolver#retrieveMatchingFiles
    |-PathMatchingResourcePatternResolver#doRetrieveMatchingFiles

protected void doRetrieveMatchingFiles(String fullPattern, File dir, Set<File> result) 
        throws IOException {
    for (File content : listDirectory(dir)) {
        String currPath = StringUtils.replace(content.getAbsolutePath(), File.separator, "/");
        if (content.isDirectory() && getPathMatcher().matchStart(fullPattern, currPath + "/")) {
            if (!content.canRead()) {
            }
            else {
                // ļУݹ
                doRetrieveMatchingFiles(fullPattern, content, result);
            }
        }
        // ļļ·
        if (getPathMatcher().match(fullPattern, currPath)) {
            result.add(content);
        }
    }
}

ϴȽϼ򵥣ƽļķʽһġ

ֵһǣgetPathMatcher().match(fullPattern, currPath) յõ AntPathMatcher#doMatchһ ant ·ƥ֤·д *紫 pattern /xxx/spring-framework/spring-learn/build/classes/java/main/org/springframework/learn/demo01/**/*.classʾƥ /xxx/spring-framework/spring-learn/build/classes/java/main/org/springframework/learn/demo01/ ļ.class ļβļǰ path /xxx/spring-framework/spring-learn/build/classes/java/main/org/springframework/learn/demo01/BeanObj2.classȻƥ䡣 AntPathMatcher#doMatch νƥģͲչˡ

ϲ裬ڵõ class ļӦ Resource .

1.3 Resource תΪ BeanDefinition

Resource תΪ BeanDefinition

ClassPathScanningCandidateComponentProvider#scanCandidateComponents

//  resource õ MetadataReader
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);

// £
// 1\. ǷҪʼΪspring beanǷ @Component@Serviceע
// 2\. 鿴Ƿ@Conditionalһϵеע⣬ȻǷעBean
if (isCandidateComponent(metadataReader)) {
    //  metadataReader תΪ ScannedGenericBeanDefinitionҲBeanDefinitionеһԱ
    ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
    ...
}

1. Resource õ MetadataReader

׷ MetadataReader Ļȡ

|-ClassPathScanningCandidateComponentProvider#scanCandidateComponents
 |-CachingMetadataReaderFactory#getMetadataReader
  |-SimpleMetadataReaderFactory#getMetadataReader(Resource)
   |-SimpleMetadataReader#SimpleMetadataReader

е SimpleMetadataReader Ĺ췽:

SimpleMetadataReader(Resource resource, @Nullable ClassLoader classLoader) throws IOException {
    SimpleAnnotationMetadataReadingVisitor visitor 
        = new SimpleAnnotationMetadataReadingVisitor(classLoader);
    // ﷢classļĶȡ
    getClassReader(resource).accept(visitor, PARSING_OPTIONS);
    this.resource = resource;
    this.annotationMetadata = visitor.getMetadata();
}

ٽһ׷٣ class ļĶȡ ClassReader

ʹ asm ȡ class ļȽϸӣͲˡ

һֱҶΪ spring ͨȡϢģ֪ԭ spring ͨ asm ֱӶȡ class ļȡϢ

µõ MetadataReader Ľ

صע annotations ԣһ annotations mappings``annotations Ϊ @Service``mappings һ飬Ϊ

0-@Service
1-@Component
2-@Index

annotations ˲² BeanObj1 ϵע⣺

mappings ɶҲò²⣬ҲԴעзһЩߣ

@Service @Component ע⣬@Component @Indexed߶ mappings У⿴רע֮ϵעģˣҾ͵⹦ܰɣע⣺mappings ݺҪ

2. isCandidateComponent(MetadataReader)жǷҪʵΪ spring bean

һУǵõ basePackage **** MetadataReader ļע****ЩDzǶҪת spring beanйܵ spring أ isCandidateComponent(MetadataReader) Ĺˡϻ˵ϴ룺

protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
    // ʡԲִ
    for (TypeFilter tf : this.includeFilters) {
        // жǷҪйܵspring
        if (tf.match(metadataReader, getMetadataReaderFactory())) {
            // жǷ@Conditionalһϵеע
            return isConditionMatch(metadataReader);
        }
    }
    return false;
}

Ҫжϣ

  • ǷҪΪ spring bean
  • Ƿ @Conditional һϵеע

һжϡ

spring У spring bean עкܶ࣬ @Component``@Repository``@Service``@Controller``@ConfigurationԼдעֻ࣬ҪЩע⣬

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
//  @Component  @Service  @Repository ֮һ
@Component
public @interface MySpringBean {
    ...
}

ܱ spring ʶ spring ṩע⣨@Component``@Repository ȣжDz spring bean ʱֻҪ

if(annotation == Component.class || annotation == Repository.class) {
    ...
}

жϾˡԶע @MySpringBeanspring ô֪ spring bean أǶ @MySpringBean ʱһҪ @Component @Service @Repository ֮һܱ spring ʶʲôأǸ AbstractTypeHierarchyTraversingFilter#match(MetadataReader, MetadataReaderFactory)ǶԲҪĴֻ

|-ClassPathScanningCandidateComponentProvider#isCandidateComponent(MetadataReader)
 |-AbstractTypeHierarchyTraversingFilter#match(MetadataReader, MetadataReaderFactory)
  |-AnnotationTypeFilter#matchSelf

յ AnnotationTypeFilter#matchSelf:

@Override
protected boolean matchSelf(MetadataReader metadataReader) {
    AnnotationMetadata metadata = metadataReader.getAnnotationMetadata();
    // annotationType @Component
    return metadata.hasAnnotation(this.annotationType.getName()) ||
        (this.considerMetaAnnotations && metadata.hasMetaAnnotation(this.annotationType.getName()));
}

ؼˣ

metadata.hasAnnotation(this.annotationType.getName())

this.considerMetaAnnotations && metadata.hasMetaAnnotation(this.annotationType.getName())

ȿ metadata.hasAnnotation(this.annotationType.getName()) ıȽϣ

// AnnotationMetadata#hasAnnotation
default boolean hasAnnotation(String annotationName) {
    return getAnnotations().isDirectlyPresent(annotationName);
}

getAnnotations() õĽ

mappings

0-@Service
1-@Component
2-@Index

ʵǰõ MetadataReader ݣ

׷ȥ isDirectlyPresent ж annotations mappings ûг @Component:

private boolean isPresent(Object requiredType, boolean directOnly) {
    // ж annotations ûг @Component
    for (MergedAnnotation<?> annotation : this.annotations) {
        Class<? extends Annotation> type = annotation.getType();
        if (type == requiredType || type.getName().equals(requiredType)) {
            return true;
        }
    }
    if (!directOnly) {
        // ж mappings ûг @Component
        for (AnnotationTypeMappings mappings : this.mappings) {
            for (int i = 1; i < mappings.size(); i++) {
                AnnotationTypeMapping mapping = mappings.get(i);
                if (isMappingForType(mapping, requiredType)) {
                    return true;
                }
            }
        }
    }
    return false;
}

this.considerMetaAnnotations && metadata.hasMetaAnnotation(this.annotationType.getName())鿴ã

|-AnnotationTypeFilter#matchSelf
 |-AnnotationMetadata#hasMetaAnnotation
  |-MergedAnnotationsCollection#get(String, Predicate)
   |-MergedAnnotationsCollection#get(String, Predicate, MergedAnnotationSelector)
    |-MergedAnnotationsCollection#find

յIJҷ MergedAnnotationsCollection#find:

private <A extends Annotation> MergedAnnotation<A> find(Object requiredType,
        @Nullable Predicate<? super MergedAnnotation<A>> predicate,
        @Nullable MergedAnnotationSelector<A> selector) {

    MergedAnnotation<A> result = null;
    for (int i = 0; i < this.annotations.length; i++) {
        MergedAnnotation<?> root = this.annotations[i];
        AnnotationTypeMappings mappings = this.mappings[i];
        // mappings  mappings
        for (int mappingIndex = 0; mappingIndex < mappings.size(); mappingIndex++) {
            AnnotationTypeMapping mapping = mappings.get(mappingIndex);
            if (!isMappingForType(mapping, requiredType)) {
                continue;
            }
            // ҵ @Component ע
            MergedAnnotation<A> candidate = (mappingIndex == 0
                ? (MergedAnnotation<A>) root
                : TypeMappedAnnotation.createIfPossible(mapping, root, IntrospectionFailureLogger.INFO));
            if (candidate != null && (predicate == null || predicate.test(candidate))) {
                if (selector.isBestCandidate(candidate)) {
                    return candidate;
                }
                result = (result != null ? selector.select(result, candidate) : candidate);
            }
        }
    }
    return result;
}

Կҷʽ metadata.hasAnnotation(this.annotationType.getName()) ߶ơ

Ͼ spring жǷ @Service``@Component ע߼ˡ

java УעDzܼ̳еģ

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Base {

}

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Child extends  Base {

}

﷨ java вģspring Dzעעķʽʵڼ̳еĹܡ

ClassPathScanningCandidateComponentProvider#isConditionMatch ʵϣжǷ @Conditional עģʶΪ spring beanյõ ConditionEvaluator#shouldSkip(AnnotatedTypeMetadata, ConfigurationCondition.ConfigurationPhase):

public boolean shouldSkip(@Nullable AnnotatedTypeMetadata metadata, @Nullable ConfigurationPhase phase) {
    // ʡһЩ

    // õ condition 
    List<Condition> conditions = new ArrayList<>();
        for (String[] conditionClasses : getConditionClasses(metadata)) {
            for (String conditionClass : conditionClasses) {
                Condition condition = getCondition(conditionClass, this.context.getClassLoader());
                conditions.add(condition);
            }
        }
    }

    AnnotationAwareOrderComparator.sort(conditions);
    // ж condition Ƿ
    for (Condition condition : conditions) {
        ConfigurationPhase requiredPhase = null;
        if (condition instanceof ConfigurationCondition) {
            requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
        }
        if ((requiredPhase == null || requiredPhase == phase) 
                // ж condition Ƿһͷtrue
                && !condition.matches(this.context, metadata)) {
            return true;
        }
    }

    return false;
}

// ͨȡ Condition 
private Condition getCondition(String conditionClassName, @Nullable ClassLoader classloader) {
    Class<?> conditionClass = ClassUtils.resolveClassName(conditionClassName, classloader);
    return (Condition) BeanUtils.instantiateClass(conditionClass);
}

£

  1. ȡ condition
  2. condition 󣬵 condition.matches() жǷ
3. MetadataReader õ ScannedGenericBeanDefinition

һ򵥵ĸֵ ScannedGenericBeanDefinition Ĺ췽ˣ

ScannedGenericBeanDefinition#ScannedGenericBeanDefinition

public ScannedGenericBeanDefinition(MetadataReader metadataReader) {
    Assert.notNull(metadataReader, "MetadataReader must not be null");
    this.metadata = metadataReader.getAnnotationMetadata();
    setBeanClassName(this.metadata.getClassName());
}

Ƚϼ򵥣Ͳˡ

2. ḻ beanDefinition Ϣ

ǧգڵõ beanDefinitionʱ beanDefinition ḻǽһչ beanDefinition ϢˡЩϢ bean``bean``@Lazy ע⡢@Primary ע⡢@DependsOn עȣ£

public abstract class AnnotationConfigUtils {

    ...

    /**
     * һḻ BeanDefinition
     */
    static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, 
            AnnotatedTypeMetadata metadata) {
        //  @Lazy
        AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);
        if (lazy != null) {
            abd.setLazyInit(lazy.getBoolean("value"));
        }
        else if (abd.getMetadata() != metadata) {
            lazy = attributesFor(abd.getMetadata(), Lazy.class);
            if (lazy != null) {
                abd.setLazyInit(lazy.getBoolean("value"));
            }
        }
        //  @Primary
        if (metadata.isAnnotated(Primary.class.getName())) {
            abd.setPrimary(true);
        }
        //  @DependsOn
        AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);
        if (dependsOn != null) {
            abd.setDependsOn(dependsOn.getStringArray("value"));
        }
        //  @Role
        AnnotationAttributes role = attributesFor(metadata, Role.class);
        if (role != null) {
            abd.setRole(role.getNumber("value").intValue());
        }
        //  @Description
        AnnotationAttributes description = attributesFor(metadata, Description.class);
        if (description != null) {
            abd.setDescription(description.getString("value"));
        }
    }
}

3. registerBeanDefinition(definitionHolder, this.registry): BeanDefinition beanFactory

BeanDefinition beanFactory IJȽϼ򵥣ؼĴ£

|-ClassPathBeanDefinitionScanner#registerBeanDefinition
 |-BeanDefinitionReaderUtils#registerBeanDefinition
  |-GenericApplicationContext#registerBeanDefinition
   |-DefaultListableBeanFactory#registerBeanDefinition

DefaultListableBeanFactory#registerBeanDefinition

this.beanDefinitionMap.put(beanName, beanDefinition);

ClassPathBeanDefinitionScanner#registerBeanDefinition DefaultListableBeanFactory#registerBeanDefinitionȻһЩƣɲҵؼĴ롣

ˣϵ class ļ spring ɨ裬ڱ BeanDefinition BeanFactory ˡ

4. ܽ

ıȽϳҪ spring ɨ·õ beanDefinition Ḷ́Ҫ£

  1. ݰõ· Resource
  2. · Resouce õ· class ļ Resouce
  3. class ļ Resouce ͨ asm õ MetadataReaderע⣺ MetadataReader class ļ MetadataReader
  4. MetadataReader ҵҪ spring йܵ MetadataReaderתΪ ScannedGenericBeanDefinition``ScannedGenericBeanDefinition Ϊ BeanDefinition
  5. һḻ ScannedGenericBeanDefinition Ϣ
  6. õ BeanDefinition ӵ BeanFactory

ˣתΪ BeanDefinition ɡ

Ļֵעĵط

  1. spring ڻȡϵעʱͨ䣬ʹ asm ֱӽ class ļȻٻȡϵע
  2. ڴעʱspring ͨ עע⡱ ʵһע̳еķʽҲ spring ʶ @Component``@Service ǿԶעԭ

õ BeanDefinition 󣬽ž spring ijʼˣƪټ


ԭӣhttps://my.oschina.net/funcy/blog/4614071 ߸ˮƽд֮ӭָԭףҵתϵ߻Ȩҵתע