Spring組件掃描--源碼跟蹤

看這篇文章以前能夠先了解以前的跟蹤流程,https://www.jianshu.com/p/4934233f0eadjava

代碼過寬,能夠shift + 鼠標滾輪 左右滑動查看node

這篇文章主要跟蹤spring配置文件中component-scan標籤,查看它是怎樣被解析掃描生成對應的beanDefinition。web

在applicationContext.xml中作如下配置:spring

<!-- 啓動組件掃描,排除@Controller組件,該組件由SpringMVC配置文件掃描 -->
<context:component-scan base-package="cn.mrdear">
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
    <context:exclude-filter type="annotation" expression="org.springframework.web.bind.annotation.RestController" />
</context:component-scan>

以DefaultBeanDefinitionDocumentReader類中的parseBeanDefinitions方法做爲開始,向下跟蹤。express

/**
* Parse the elements at the root level in the document:
* "import", "alias", "bean".
*
* 解析在文檔中根層級的元素:"import", "alias", "bean".
*/
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
    //默認名稱空間是"http://www.springframework.org/schema/beans"
    //進入條件
    if (delegate.isDefaultNamespace(root)) {
        
        //獲取根元素下的子Node,注意,Node不必定是子標籤,多是回車,多是註釋
        NodeList nl = root.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (node instanceof Element) {
                
                //拿到了<beans>下的子標籤
                Element ele = (Element) node;
                if (delegate.isDefaultNamespace(ele)) {
                    
                    //若是該標籤屬於beans的名稱空間,則進入這個方法
                    //xmlns="http://www.springframework.org/schema/beans"
                    parseDefaultElement(ele, delegate);
                }
                else {
                    
                    //若是該標籤屬於其餘的名稱空間好比:context,aop等
                    //xmlns:aop="http://www.springframework.org/schema/aop"
                    //xmlns:context="http://www.springframework.org/schema/context"
                    delegate.parseCustomElement(ele);
                }
            }
        }
    }
    else {
        delegate.parseCustomElement(root);
    }
}

對以上方法不太瞭解的能夠先看下這篇文章:api

https://www.jianshu.com/p/a0cfaedf3fc5數組

由於component-scan標籤屬於context名稱空間,因此走這個方法。app

delegate.parseCustomElement(ele);

這個方法的實如今BeanDefinitionParserDelegate類中ide

public BeanDefinition parseCustomElement(Element ele) {
    return parseCustomElement(ele, null);
}

//containingBd入參傳遞爲null
public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
    
    //獲取標籤所屬的名稱空間
    //http://www.springframework.org/schema/context
    String namespaceUri = getNamespaceURI(ele);
    
    //每一個名稱空間對應一個處理器,拿到對應context的處理器
    NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
    if (handler == null) {
        error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
        return null;
    }
    //進入這個方法
    return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}

雖然context對應的處理器是ContextNamespaceHandler,但其實是調用其父類NamespaceHandlerSupport類中的parse方法。post

/**
* Parses the supplied {@link Element} by delegating to the {@link BeanDefinitionParser} that is
* registered for that {@link Element}.
*
* 經過委派給BeanDefinitionParser來解析元素,併爲該元素註冊
*/
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
    return findParserForElement(element, parserContext).parse(element, parserContext);
}

先查看findParserForElement方法,此方法仍是在NamespaceHandlerSupport類中。

/**
* Locates the {@link BeanDefinitionParser} from the register implementations using
* the local name of the supplied {@link Element}.
*
* 經過元素的部分名稱,去從註冊器實現中定位BeanDefinitionParser
*/
private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
    //拿到標籤的名稱(不包含名稱空間)
    //component-scan
    String localName = parserContext.getDelegate().getLocalName(element);
    
    //parsers是一個HashMap,
    //在生成處理器的時候,會初始化一系列解析器,每個解析器對應着一個標籤名稱
    //以名稱作key,解析器做爲value,放入到parsers屬性中
    //這裏能夠經過標籤名稱拿到對應的解析器
    BeanDefinitionParser parser = this.parsers.get(localName);
    
    if (parser == null) {
        parserContext.getReaderContext().fatal(
            "Cannot locate BeanDefinitionParser for element [" + localName + "]", element);
    }
    return parser;
}

找到解析器後,調用解析器的parse方法。

parse(零)

這裏的解析器是ComponentScanBeanDefinitionParser類,進入parse方法查看

/**
* 解析指定的Element,而後註冊結果BeanDefinition到內嵌在ParserContext裏的bean factory中。
*/
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
    //獲取component-scan標籤的base-package屬性值
    //cn.mrdear
    String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE);
    
    //若是有佔位符,則解析全部的佔位符
    basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);
    
    //字符串中有" ,;\n\t"等符號就看作分隔符,分割成數組
    String[] basePackages = StringUtils.tokenizeToStringArray(basePackage,
                                                              ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);

    // Actually scan for bean definitions and register them.
    // 掃描bean definition 並註冊它們
    // 1.配置掃描器
    ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
    
    // 2.利用掃描器掃描包,並註冊bean definition
    Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
    
    // 3. 註冊組件
    registerComponents(parserContext.getReaderContext(), beanDefinitions, element);

    return null;
}

1.configureScanner

跟蹤標記1的方法

此方法在ComponentScanBeanDefinitionParser類中實現

// 1.配置掃描器
ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);

//進入方法
protected ClassPathBeanDefinitionScanner configureScanner(ParserContext parserContext, Element element) {
    boolean useDefaultFilters = true;
    
    //拿到component-scan標籤的use-default-filters屬性,沒有配置則爲true
    if (element.hasAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)) {
        useDefaultFilters = Boolean.valueOf(element.getAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE));
    }

    // Delegate bean definition registration to scanner class.
    // 1.1將bean definition的工廠委派給scanner類
    ClassPathBeanDefinitionScanner scanner = createScanner(parserContext.getReaderContext(), useDefaultFilters);
    
    //這裏將閱讀器上下文中拿到的根web應用上下文做爲scanner的ResourceLoader,
    //根web應用上下文默認實現爲XmlWebApplicationContext,實現了ResourceLoader接口,
    //因此能夠做爲ResourceLoader
    scanner.setResourceLoader(parserContext.getReaderContext().getResourceLoader());
    
    //初始化scanner時使用默認的StandardEnvironment做爲environment,
    //這裏拿到了閱讀器上下文中的environment,StandardServletEnvironment
    //其實閱讀器中的environment拿的是XmlWebApplicationContext的environment
    scanner.setEnvironment(parserContext.getReaderContext().getEnvironment());
    
    //獲取代理類的defaults屬性中,對標籤屬性的一些默認設置
    scanner.setBeanDefinitionDefaults(parserContext.getDelegate().getBeanDefinitionDefaults());

    //這裏爲null  
    scanner.setAutowireCandidatePatterns(parserContext.getDelegate().getAutowireCandidatePatterns());
    
    //拿到component-scan標籤的resource-pattern屬性,這裏沒有設置
    if (element.hasAttribute(RESOURCE_PATTERN_ATTRIBUTE)) {
        scanner.setResourcePattern(element.getAttribute(RESOURCE_PATTERN_ATTRIBUTE));
    }

    try {
        //1.2解析name-generator屬性
        parseBeanNameGenerator(element, scanner);
    }
    catch (Exception ex) {
        parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause());
    }

    try {
        //1.3解析Scope
        parseScope(element, scanner);
    }
    catch (Exception ex) {
        parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause());
    }
    
    //1.4解析類過濾器
    parseTypeFilters(element, scanner, parserContext);

    return scanner;
}

1.1 createScanner

跟蹤標記1.1的方法

此方法在ComponentScanBeanDefinitionParser類中實現

// 1.1將bean definition的註冊委派給scanner類
ClassPathBeanDefinitionScanner scanner = createScanner(parserContext.getReaderContext(), useDefaultFilters);

//入參傳遞了bean工廠,useDefaultFilters爲true
protected ClassPathBeanDefinitionScanner createScanner(XmlReaderContext readerContext, boolean useDefaultFilters) {
    return new ClassPathBeanDefinitionScanner(readerContext.getRegistry(), useDefaultFilters);
}

看下ClassPathBeanDefinitionScanner類的構造實現

//由於默認的工廠DefaultListableBeanFactory沒有實現EnvironmentCapable接口
//因此從新建立了一個environment,與上下文的StandardServletEnvironment不一樣,
//這個environment是StandardEnvironment類型,在environment初始化的同時,會將
//systemProperties和systemEnvironment讀取到environment內部
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
    this(registry, useDefaultFilters, getOrCreateEnvironment(registry));
}


public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters, Environment environment) {
    
    //調用了父類的構造
    super(useDefaultFilters, environment);

    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    
    //拿到bean工廠的引用
    this.registry = registry;

    // Determine ResourceLoader to use.
    // 默認bean工廠沒有實現ResourceLoader接口,這裏默認使用PathMatchingResourcePatternResolver
    // 做爲ResourceLoader
    if (this.registry instanceof ResourceLoader) {
        setResourceLoader((ResourceLoader) this.registry);
    }
}

再進入父類構造中查看初始化了哪些屬性

進入ClassPathScanningCandidateComponentProvider類中,查看對應的構造方法

public ClassPathScanningCandidateComponentProvider(boolean useDefaultFilters, Environment environment) {
    
    //由於useDefaultFilters設置爲了true,因此下面的方法會被調用
    if (useDefaultFilters) {
        registerDefaultFilters();
    }
    
    Assert.notNull(environment, "Environment must not be null");
    
    //拿到先前新建的StandardEnvironment引用
    this.environment = environment;
}


/**
* Register the default filter for {@link Component @Component}.
* <p>This will implicitly register all annotations that have the
* {@link Component @Component} meta-annotation including the
* {@link Repository @Repository}, {@link Service @Service}, and
* {@link Controller @Controller} stereotype annotations.
* <p>Also supports Java EE 6's {@link javax.annotation.ManagedBean} and
* JSR-330's {@link javax.inject.Named} annotations, if available.
* 
* 爲@Component註解註冊默認的過濾器。
* 隱式的註冊全部包含@Component元註解的註解,包括@Repository、@Service、@Controller
* 等老舊的註解。
* 也支持Java EE 6的javax.annotation.ManagedBean和JSR-330的javax.inject.Named註解
*/
@SuppressWarnings("unchecked")
protected void registerDefaultFilters() {
    
    //includeFilters是一個LinkedList,存放註解類型過濾器,
    //只有符合過濾器的註解類型才能生成bean definition
    //1.1.1瞭解下AnnotationTypeFilter的構造實現,註解類型爲Component
    this.includeFilters.add(new AnnotationTypeFilter(Component.class));
    
    //拿到該類的類加載器
    ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
    
    try {
        
        //1.1.2查看註解類型爲ManagedBean的AnnotationTypeFilter構造實現
        this.includeFilters.add(new AnnotationTypeFilter(
            ((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
        logger.debug("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
    }
    catch (ClassNotFoundException ex) {
        // JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
    }
    try {
        
        //Named註解同1.1.2,
        //可是這裏沒有相關jar包,因此沒有javax.inject.Named這個類,拋出異常,空捕獲跳出
        this.includeFilters.add(new AnnotationTypeFilter(
            ((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
        logger.debug("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
    }
    catch (ClassNotFoundException ex) {
        // JSR-330 API not available - simply skip.
    }
}

1.1.1 AnnotationTypeFilter

跟蹤標記1.1.1的方法

//1.1.1瞭解下AnnotationTypeFilter的構造實現
new AnnotationTypeFilter(Component.class)
    
    
/**
* Create a new AnnotationTypeFilter for the given annotation type.
* This filter will also match meta-annotations. To disable the
* meta-annotation matching, use the constructor that accepts a
* '{@code considerMetaAnnotations}' argument. The filter will
* not match interfaces.
* 
* 經過給定的註解類型建立一個新的註解類型過濾器
* 這個過濾器還會匹配元註解
* 若是要禁用元註解匹配,可使用接受considerMetaAnnotations參數的構造方法。
* 這個過濾器不會匹配接口
*/
public AnnotationTypeFilter(Class<? extends Annotation> annotationType) {
    this(annotationType, true, false);
}


/**
* 注意上一層調用構造時的入參,默認considerMetaAnnotations爲true,considerInterfaces爲false
* 這說明註解中若是它的元註解匹配過濾器,那麼也算是匹配。
* 過濾的時候不考慮是接口的狀況
*/
public AnnotationTypeFilter(Class<? extends Annotation> annotationType, boolean considerMetaAnnotations, boolean considerInterfaces) {
    
    //isAnnotationPresent方法是用來查看annotationType上是否有Inherited註解
    //其boolean值賦值給父類AbstractTypeHierarchyTraversingFilter的屬性considerInherited中
    super(annotationType.isAnnotationPresent(Inherited.class), considerInterfaces);
    
    this.annotationType = annotationType;
    this.considerMetaAnnotations = considerMetaAnnotations;
}

1.1.2 AnnotationTypeFilter

跟蹤標記1.1.2的方法

//1.1.2查看註解類型爲ManagedBean的AnnotationTypeFilter構造實現
new AnnotationTypeFilter(
    ((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false);

首先經過forName方法,拿到字符串javax.annotation.ManagedBean對應的Class,而後調用AnnotationTypeFilter的構造。

/**
* 上一層傳參時considerMetaAnnotations爲false,說明不用考慮註解上的元註解,這個註解不匹配過濾器就過濾掉
*/
public AnnotationTypeFilter(Class<? extends Annotation> annotationType, boolean considerMetaAnnotations) {
    this(annotationType, considerMetaAnnotations, false);
}

//considerInterfaces依然爲false
public AnnotationTypeFilter(Class<? extends Annotation> annotationType, boolean considerMetaAnnotations, boolean considerInterfaces) {
    
    //ManagedBean的元註解上依然沒有Inherited,因此considerInherited爲false
    super(annotationType.isAnnotationPresent(Inherited.class), considerInterfaces);
    
    this.annotationType = annotationType;
    this.considerMetaAnnotations = considerMetaAnnotations;
}

1.2 parseBeanNameGenerator

跟蹤標記1.2的方法

在ComponentScanBeanDefinitionParser類中實現

//1.2解析name-generator屬性
parseBeanNameGenerator(element, scanner);

protected void parseBeanNameGenerator(Element element, ClassPathBeanDefinitionScanner scanner) {
    
    //component-scan標籤的name-generator屬性,這裏沒有設置,跳過
    if (element.hasAttribute(NAME_GENERATOR_ATTRIBUTE)) {
        BeanNameGenerator beanNameGenerator = (BeanNameGenerator) instantiateUserDefinedStrategy(
            element.getAttribute(NAME_GENERATOR_ATTRIBUTE), BeanNameGenerator.class,
            scanner.getResourceLoader().getClassLoader());
        scanner.setBeanNameGenerator(beanNameGenerator);
    }
}

1.3 parseScope

跟蹤標記1.3的方法

在ComponentScanBeanDefinitionParser類中實現

//1.3 解析Scope
parseScope(element, scanner);

protected void parseScope(Element element, ClassPathBeanDefinitionScanner scanner) {
    // Register ScopeMetadataResolver if class name provided.
    // 若是類名被提供,則註冊ScopeMetadataResolver
    
    // 標籤上有無scope-resolver屬性
    if (element.hasAttribute(SCOPE_RESOLVER_ATTRIBUTE)) {
        
        // 若是還同時添加了scoped-proxy屬性則報錯
        if (element.hasAttribute(SCOPED_PROXY_ATTRIBUTE)) {
            throw new IllegalArgumentException(
                "Cannot define both 'scope-resolver' and 'scoped-proxy' on <component-scan> tag");
        }
        ScopeMetadataResolver scopeMetadataResolver = (ScopeMetadataResolver) instantiateUserDefinedStrategy(
            element.getAttribute(SCOPE_RESOLVER_ATTRIBUTE), ScopeMetadataResolver.class,
            scanner.getResourceLoader().getClassLoader());
        scanner.setScopeMetadataResolver(scopeMetadataResolver);
    }
    
    // 標籤上有無scoped-proxy屬性
    if (element.hasAttribute(SCOPED_PROXY_ATTRIBUTE)) {
        String mode = element.getAttribute(SCOPED_PROXY_ATTRIBUTE);
        if ("targetClass".equals(mode)) {
            scanner.setScopedProxyMode(ScopedProxyMode.TARGET_CLASS);
        }
        else if ("interfaces".equals(mode)) {
            scanner.setScopedProxyMode(ScopedProxyMode.INTERFACES);
        }
        else if ("no".equals(mode)) {
            scanner.setScopedProxyMode(ScopedProxyMode.NO);
        }
        else {
            throw new IllegalArgumentException("scoped-proxy only supports 'no', 'interfaces' and 'targetClass'");
        }
    }
}

1.4 parseTypeFilters

跟蹤標記1.4的方法

在ComponentScanBeanDefinitionParser類中實現

//1.4解析類過濾器
parseTypeFilters(element, scanner, parserContext);

protected void parseTypeFilters(Element element, ClassPathBeanDefinitionScanner scanner, ParserContext parserContext) {
    
    // Parse exclude and include filter elements.
    // 解析包含和不包含過濾器元素
    
    //拿到根應用上下文的類加載器
    ClassLoader classLoader = scanner.getResourceLoader().getClassLoader();
    
    //拿到全部的子節點
    NodeList nodeList = element.getChildNodes();
    for (int i = 0; i < nodeList.getLength(); i++) {
        
        Node node = nodeList.item(i);
        
        //拿到的子節點是否是子標籤
        if (node.getNodeType() == Node.ELEMENT_NODE) {
            
            //獲取子標籤的部分名稱(不包含名稱空間)
            String localName = parserContext.getDelegate().getLocalName(node);
           
            try {
                
                //是include-filter標籤的狀況,上下兩個調用的同一個方法,跟蹤其中一個
                if (INCLUDE_FILTER_ELEMENT.equals(localName)) {
                    TypeFilter typeFilter = createTypeFilter((Element) node, classLoader, parserContext);
                    scanner.addIncludeFilter(typeFilter);
                }
                
                //是exclude-filter標籤的狀況
                else if (EXCLUDE_FILTER_ELEMENT.equals(localName)) {
                    TypeFilter typeFilter = createTypeFilter((Element) node, classLoader, parserContext);
                    scanner.addExcludeFilter(typeFilter);
                }
            }
            catch (Exception ex) {
                parserContext.getReaderContext().error(
                    ex.getMessage(), parserContext.extractSource(element), ex.getCause());
            }
        }
    }
}

跟蹤createTypeFilter方法

protected TypeFilter createTypeFilter(Element element, ClassLoader classLoader, ParserContext parserContext) {
    
    //獲取標籤上的type屬性和expression屬性對應的值
    String filterType = element.getAttribute(FILTER_TYPE_ATTRIBUTE);
    String expression = element.getAttribute(FILTER_EXPRESSION_ATTRIBUTE);
    
    //expression可能帶有佔位符,若是有則解析佔位符
    expression = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(expression);
    try {
        
        //xml文件中type填寫的是annotation,因此走這個方法
        if ("annotation".equals(filterType)) {
            
            //將xml中的"org.springframework.stereotype.Controller"字符串解析爲Class
            //構造已經看過,默認considerMetaAnnotations爲true,considerInterfaces爲false
            return new AnnotationTypeFilter((Class<Annotation>) classLoader.loadClass(expression));
        }
        else if ("assignable".equals(filterType)) {
            return new AssignableTypeFilter(classLoader.loadClass(expression));
        }
        else if ("aspectj".equals(filterType)) {
            return new AspectJTypeFilter(expression, classLoader);
        }
        else if ("regex".equals(filterType)) {
            return new RegexPatternTypeFilter(Pattern.compile(expression));
        }
        else if ("custom".equals(filterType)) {
            Class<?> filterClass = classLoader.loadClass(expression);
            if (!TypeFilter.class.isAssignableFrom(filterClass)) {
                throw new IllegalArgumentException(
                    "Class is not assignable to [" + TypeFilter.class.getName() + "]: " + expression);
            }
            return (TypeFilter) BeanUtils.instantiateClass(filterClass);
        }
        else {
            throw new IllegalArgumentException("Unsupported filter type: " + filterType);
        }
    }
    catch (ClassNotFoundException ex) {
        throw new FatalBeanException("Type filter class not found: " + expression, ex);
    }
}

最後scanner的includeFilters屬性中,默認添加了org.springframework.stereotype.Component的註解過濾器和javax.annotation.ManagedBean的註解過濾器。

scanner的excludeFilters屬性中,自定義添加了xml配置文件中的org.springframework.stereotype.Controller註解過濾器和org.springframework.web.bind.annotation.RestController註解過濾器。

2.doScan

跟蹤標記2的方法

此方法在ClassPathBeanDefinitionScanner類中實現

// 2.利用掃描器掃描包,並註冊bean definition
Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);

/**
* Perform a scan within the specified base packages,
* returning the registered bean definitions.
* <p>This method does <i>not</i> register an annotation config processor
* but rather leaves this up to the caller.
* 
* 掃描指定包,返回被註冊的bean definitions
* 這個方法不會註冊annotation config processor,交由調用者處理
*/
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
    Assert.notEmpty(basePackages, "At least one base package must be specified");
    Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();
    
    //根據配置,這裏就只有一個"cn.mrdear"
    for (String basePackage : basePackages) {
        
        //2.1掃描候選者的class path
        Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
        for (BeanDefinition candidate : candidates) {
            
            //2.2解析@scope註解
            ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
            candidate.setScope(scopeMetadata.getScopeName());
            
            //2.3AnnotatedBeanDefinition的默認名稱生成規則
            String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
            if (candidate instanceof AbstractBeanDefinition) {
                
                //2.4給beanDefinition設置默認值、自動注入的候選者
                postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
            }
            if (candidate instanceof AnnotatedBeanDefinition) {
                
                //2.5拿到類上其餘的context名稱空間的註解,若是有的話,獲取其value屬性
                AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
            }
            
            //2.6檢查beanName是否正確匹配對應的bean Definition,該名稱是否已經被註冊
            if (checkCandidate(beanName, candidate)) {
                BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
                
                //應用Scope代理模式
                definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
                beanDefinitions.add(definitionHolder);
                
                //註冊bean definition
                registerBeanDefinition(definitionHolder, this.registry);
            }
        }
    }
    return beanDefinitions;
}

2.1 findCandidateComponents

跟蹤標記2.1的方法

在ClassPathScanningCandidateComponentProvider類中實現

ClassPathScanningCandidateComponentProvider是ClassPathBeanDefinitionScanner的父類

//2.1掃描候選者的class path
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);


public Set<BeanDefinition> findCandidateComponents(String basePackage) {
    Set<BeanDefinition> candidates = new LinkedHashSet<BeanDefinition>();
    try {
        
        //給包名添加上"classpath*:"的前綴和"**/*.class"的後綴
        //最後結果:classpath*:cn/mrdear/**/*.class
        String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
            resolveBasePackage(basePackage) + "/" + this.resourcePattern;
        
        //將包下的全部class文件用Resource的方式描述
        //Resource--資源描述符
        //裏面的實現很是大,有興趣能夠本身看看。
        //主要是將packageSearchPath分紅classpath,包名,後綴名三部分進行處理,又根據有無*或者?
        //等表達式,處理方式有所不一樣
        Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath);
        boolean traceEnabled = logger.isTraceEnabled();
        boolean debugEnabled = logger.isDebugEnabled();
        
        //對每一個class進行處理
        for (Resource resource : resources) {
            if (traceEnabled) {
                logger.trace("Scanning " + resource);
            }
            
            //是否非目錄,可讀
            if (resource.isReadable()) {
                try {
                    
                    //這個metadataReader包含class文件中,類上的註解
                    //方法的註解,所使用註解的元註解等描述 
                    //在獲取metadataReader的同時,在CachingMetadataReaderFactory類的
                    //metadataReaderCache屬性中存放了一份。此屬性是LinkedHashMap
                    MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);
                    
                    //2.1.1判斷metadataReader可否經過註解類型過濾器過濾
                    if (isCandidateComponent(metadataReader)) {
                        
                        //建立bean definition,拿到metadataReader的beanClass
                        //保存metadataReader的annotationMetadata的引用
                        ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
                        
                        //取得資源描述符的引用
                        sbd.setResource(resource);
                        sbd.setSource(resource);
                        
                        //2.1.2查看類是否具體且獨立
                        if (isCandidateComponent(sbd)) {
                            if (debugEnabled) {
                                
                                //肯定候選組件class
                                logger.debug("Identified candidate component class: " + resource);
                            }
                            candidates.add(sbd);
                        }
                        else {
                            if (debugEnabled) {
                                
                                //被忽略,不是一個具體的頂層class
                                logger.debug("Ignored because not a concrete top-level class: " + resource);
                            }
                        }
                    }
                    else {
                        if (traceEnabled) {
                            
                            //被忽略,不匹配任何過濾器
                            logger.trace("Ignored because not matching any filter: " + resource);
                        }
                    }
                }
                catch (Throwable ex) {
                    throw new BeanDefinitionStoreException(
                        
                        //失敗讀取候選組件
                        "Failed to read candidate component class: " + resource, ex);
                }
            }
            else {
                if (traceEnabled) {
                    
                    //不可讀,忽略
                    logger.trace("Ignored because not readable: " + resource);
                }
            }
        }
    }
    catch (IOException ex) {
        
        //掃描類路徑時IO異常
        throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
    }
    
    //最後返回候選的bean definition
    return candidates;
}

我這裏返回的就只有兩個類,加了@ControllerAdvice的GlobalException、加了@Service的BookServiceImpl。

其他的要麼是接口,要麼沒被掃描,要麼被過濾器過濾了,如下是我項目中全部class:

項目層級結構.png

2.1.1 isCandidateComponent

跟蹤標記2.1.1的方法

在ClassPathScanningCandidateComponentProvider類中實現

//2.1.1判斷metadataReader可否經過註解類型過濾器過濾
isCandidateComponent(metadataReader)

/**
* Determine whether the given class does not match any exclude filter
* and does match at least one include filter.
*
* 不匹配任何exclude filter,至少匹配一個include filter.
* 才能肯定其爲候選人
*/
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
    for (TypeFilter tf : this.excludeFilters) {
        
        //2.1.1.1跟蹤match方法
        //若是metadataReader中有註解匹配exclude過濾器的註解,則返回false
        if (tf.match(metadataReader, this.metadataReaderFactory)) {
            return false;
        }
    }
    for (TypeFilter tf : this.includeFilters) {
        
        //若是metadataReader中有註解匹配include過濾器的註解,則進入條件
        if (tf.match(metadataReader, this.metadataReaderFactory)) {
            
            //2.1.1.2是否有@Conditional註解,進行相關處理
            return isConditionMatch(metadataReader);
        }
    }
    return false;
}

過濾器中存放的都是AnnotationTypeFilter類型

TypeFilter是其頂層接口

match方法主要是在AbstractTypeHierarchyTraversingFilter抽象類中實現

AnnotationTypeFilter繼承圖.png

2.1.1.1 match

跟蹤標記2.1.1.1的方法

在AbstractTypeHierarchyTraversingFilter類中實現

//2.1.1.1跟蹤match方法
tf.match(metadataReader, this.metadataReaderFactory)


@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
    throws IOException {

    // This method optimizes avoiding unnecessary creation of ClassReaders
    // as well as visiting over those readers.
    // 此方法作了優化,避免沒必要要的ClassReaders建立以及對它們的訪問
    
    // matchSelf方法判斷metadataReader中相關class的註解有沒有包含這個過濾器的註解
    // 若是沒有,可是過濾器的considerMetaAnnotations屬性設置爲true,
    // 那麼再判斷class全部註解的元註解中,有沒有包含這個過濾器的註解
    // 有就返回true,進入條件
    if (matchSelf(metadataReader)) {
        return true;
    }
    ClassMetadata metadata = metadataReader.getClassMetadata();
    
    // 默認返回false,不進入條件
    if (matchClassName(metadata.getClassName())) {
        return true;
    }
    
    //considerInherited這個屬性前面跟蹤的過濾器中都爲false
    //和過濾器的註解有關,其元註解包含Inherited,
    //那麼considerInherited屬性就爲true
    if (this.considerInherited) {
        if (metadata.hasSuperClass()) {
            
            // Optimization to avoid creating ClassReader for super class.
            Boolean superClassMatch = matchSuperClass(metadata.getSuperClassName());
            if (superClassMatch != null) {
                if (superClassMatch.booleanValue()) {
                    return true;
                }
            }
            else {
                
                // Need to read super class to determine a match...
                try {
                    if (match(metadata.getSuperClassName(), metadataReaderFactory)) {
                        return true;
                    }
                }
                catch (IOException ex) {
                    logger.debug("Could not read super class [" + metadata.getSuperClassName() +
                                 "] of type-filtered class [" + metadata.getClassName() + "]");
                }
            }
        }
    }
    
    //considerInterfaces屬性在AnnotationTypeFilter構造器中都默認被設置爲false
    if (this.considerInterfaces) {
        for (String ifc : metadata.getInterfaceNames()) {
            
            // Optimization to avoid creating ClassReader for super class
            Boolean interfaceMatch = matchInterface(ifc);
            if (interfaceMatch != null) {
                if (interfaceMatch.booleanValue()) {
                    return true;
                }
            }
            else {
                
                // Need to read interface to determine a match...
                try {
                    if (match(ifc, metadataReaderFactory)) {
                        return true;
                    }
                }
                catch (IOException ex) {
                    logger.debug("Could not read interface [" + ifc + "] for type-filtered class [" +
                                 metadata.getClassName() + "]");
                }
            }
        }
    }

    return false;
}
2.1.1.2 isConditionMatch

跟蹤標記2.1.1.2的方法

在ClassPathScanningCandidateComponentProvider類中實現

//2.1.1.2是否有@Conditional註解,進行相關處理
isConditionMatch(metadataReader);

/**
* Determine whether the given class is a candidate component based on any
* {@code @Conditional} annotations.
* 
* 肯定指定類是不是基於任何@Conditional註解的候選組件
*/
private boolean isConditionMatch(MetadataReader metadataReader) {
    if (this.conditionEvaluator == null) {
        this.conditionEvaluator = new ConditionEvaluator(getRegistry(), getEnvironment(), getResourceLoader());
    }
    
    //跟蹤這個方法
    return !this.conditionEvaluator.shouldSkip(metadataReader.getAnnotationMetadata());
}

因而進入ConditionEvaluator的shouldSkip方法

/**
* Determine if an item should be skipped based on {@code @Conditional} annotations.
* The {@link ConfigurationPhase} will be deduced from the type of item (i.e. a
* {@code @Configuration} class will be {@link ConfigurationPhase#PARSE_CONFIGURATION})
* 
* 根據@Conditional註解肯定一個子項是否應該被跳過
* 從子項的類型能夠推導ConfigurationPhase,好比@Configuration class就是
* ConfigurationPhase#PARSE_CONFIGURATION--解析配置
*/
public boolean shouldSkip(AnnotatedTypeMetadata metadata) {
    return shouldSkip(metadata, null);
}



//這個方法就不跟了,若是要了解condition註解的用法,能夠詳細瞭解該方法
public boolean shouldSkip(AnnotatedTypeMetadata metadata, ConfigurationPhase phase) {
    
    //類上註解或者註解上的元註解不包含Conditional註解就返回false
    if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) {
        return false;
    }

    if (phase == null) {
        if (metadata instanceof AnnotationMetadata &&
            ConfigurationClassUtils.isConfigurationCandidate((AnnotationMetadata) metadata)) {
            return shouldSkip(metadata, ConfigurationPhase.PARSE_CONFIGURATION);
        }
        return shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN);
    }

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

    AnnotationAwareOrderComparator.sort(conditions);

    for (Condition condition : conditions) {
        ConfigurationPhase requiredPhase = null;
        if (condition instanceof ConfigurationCondition) {
            requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
        }
        if (requiredPhase == null || requiredPhase == phase) {
            if (!condition.matches(this.context, metadata)) {
                return true;
            }
        }
    }

    return false;
}

2.1.2 isCandidateComponent

跟蹤標記2.1.2的方法

在ClassPathScanningCandidateComponentProvider類中實現

//2.1.2查看類是否具體且獨立
isCandidateComponent(sbd)


/**
* Determine whether the given bean definition qualifies as candidate.
* <p>The default implementation checks whether the class is concrete
* (i.e. not abstract and not an interface). Can be overridden in subclasses.
* 
* 肯定bean definition qualifies可否做爲候選
* 默認實現會檢查class是否具體(不是抽象、不是接口)。能夠被子類覆蓋
*/
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
    
    //看下這兩個判斷的含義
    return (beanDefinition.getMetadata().isConcrete() && beanDefinition.getMetadata().isIndependent());
}


//不能是接口和抽象類
public boolean isConcrete() {
    return !(this.isInterface || this.isAbstract);
}


//要麼是頂層class,要麼是被嵌套的class(靜態內部類),可是被嵌套的class必須可以從
//封閉的class中獨立構造,才能說明此class是獨立的。
public boolean isIndependent() {
    
    //沒有封閉的class或者是獨立的內部類
    return (this.enclosingClassName == null || this.independentInnerClass);
}

2.2 resolveScopeMetadata

跟蹤標記2.2的方法

在AnnotationScopeMetadataResolver類中實現

//2.2解析@scope註解
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);


/**
* Resolve the {@link ScopeMetadata} appropriate to the supplied
* bean {@code definition}.
* <p>Implementations can of course use any strategy they like to
* determine the scope metadata, but some implementations that spring
* immediately to mind might be to use source level annotations
* present on {@link BeanDefinition#getBeanClassName() the class} of the
* supplied {@code definition}, or to use metadata present in the
* {@link BeanDefinition#attributeNames()} of the supplied {@code definition}.
* 
* 解析適用於BeanDefinition的ScopeMetadata
* 實現固然可使用任何喜歡的策略去肯定scope metadata,可是spring的實現立馬
* 想到的是使用source level註解在BeanDefinition對應的class上
* 或者將metadata存放於BeanDefinition的屬性中
*/
public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
    
    //默認單例,無代理
    ScopeMetadata metadata = new ScopeMetadata();
    if (definition instanceof AnnotatedBeanDefinition) {
        AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
        
        //拿到指定類上的@scope註解的全部屬性
        AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(
            annDef.getMetadata(), this.scopeAnnotationType);
        if (attributes != null) {
            metadata.setScopeName(attributes.getString("value"));
            ScopedProxyMode proxyMode = attributes.getEnum("proxyMode");
            if (proxyMode == null || proxyMode == ScopedProxyMode.DEFAULT) {
                proxyMode = this.defaultProxyMode;
            }
            metadata.setScopedProxyMode(proxyMode);
        }
    }
    return metadata;
}

2.3 generateBeanName

跟蹤標記2.3的方法

在AnnotationBeanNameGenerator類中實現

//2.3AnnotatedBeanDefinition的默認名稱生成規則
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);


public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
    if (definition instanceof AnnotatedBeanDefinition) {
        
        //先進入這個方法查看
        String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition);
        if (StringUtils.hasText(beanName)) {
            
            // Explicit bean name found.
            // 發現明確bean Name
            return beanName;
        }
    }
    
    // Fallback: generate a unique default bean name.
    // 回退:生成一個惟一的默認beanName
    return buildDefaultBeanName(definition, registry);
}


/**
* Derive a bean name from one of the annotations on the class.
*
* 從類上的一個註解中,派生出bean name
*/
protected String determineBeanNameFromAnnotation(AnnotatedBeanDefinition annotatedDef) {
    AnnotationMetadata amd = annotatedDef.getMetadata();
    
    //嘉定拿的是org.springframework.web.bind.annotation.ControllerAdvice
    Set<String> types = amd.getAnnotationTypes();
    String beanName = null;
    for (String type : types) {
        
        //拿到@ControllerAdvice上的全部的屬性
        AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(amd, type);
        
        //將@ControllerAdvice註解名,@ControllerAdvice的元註解,@ControllerAdvice上的屬性
        //當作參數傳遞
        //進入這個方法
        if (isStereotypeWithNameValue(type, amd.getMetaAnnotationTypes(type), attributes)) {
            
            //獲取註解上的value屬性對應的值
            Object value = attributes.get("value");
            if (value instanceof String) {
                String strVal = (String) value;
                if (StringUtils.hasLength(strVal)) {
                    if (beanName != null && !strVal.equals(beanName)) {
                        throw new IllegalStateException("Stereotype annotations suggest inconsistent " +
                                                        "component names: '" + beanName + "' versus '" + strVal + "'");
                    }
                    
                    //用value屬性對應的值做爲beanName
                    beanName = strVal;
                }
            }
        }
    }
    return beanName;
}


/**
* Check whether the given annotation is a stereotype that is allowed
* to suggest a component name through its annotation {@code value()}.
*
* 檢查註解是否是stereotype類型,若是是的話,能夠用註解的value()屬性,做爲組件名稱
*/
protected boolean isStereotypeWithNameValue(String annotationType,
                                            Set<String> metaAnnotationTypes, Map<String, Object> attributes) {
    
    //註解是否是stereotype類型,主要看他是否是component註解、ManagedBean註解或者Named註解
    //或者註解的元註解包含component註解
    boolean isStereotype = annotationType.equals(COMPONENT_ANNOTATION_CLASSNAME) ||
        (metaAnnotationTypes != null && metaAnnotationTypes.contains(COMPONENT_ANNOTATION_CLASSNAME)) ||
        annotationType.equals("javax.annotation.ManagedBean") ||
        annotationType.equals("javax.inject.Named");
    
    //是stereotype類型,且有value屬性的註解,返回true
    return (isStereotype && attributes != null && attributes.containsKey("value"));
}

上面看了beanDefinition是AnnotatedBeanDefinition類型狀況下,beanName怎樣生成。可是若是class上的stereotype註解,沒有給value屬性賦值,那麼又是怎樣生成beanName的?

查看其默認的beanName生成方式:

buildDefaultBeanName(definition, registry);

此方法的實現仍是在AnnotationBeanNameGenerator類中:

/**
* Derive a default bean name from the given bean definition.
* <p>The default implementation delegates to {@link #buildDefaultBeanName(BeanDefinition)}.
*
* 從給定的bean definition派生一個默認bean Name
*/
protected String buildDefaultBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
    return buildDefaultBeanName(definition);
}


/**
* Derive a default bean name from the given bean definition.
* <p>The default implementation simply builds a decapitalized version
* of the short class name: e.g. "mypackage.MyJdbcDao" -> "myJdbcDao".
* <p>Note that inner classes will thus have names of the form
* "outerClassName.InnerClassName", which because of the period in the
* name may be an issue if you are autowiring by name.
*
* 默認的實現是構建一個首字母小寫(像變量同樣的命名方式)的簡短類名。
* 注意內部類所以會是這樣的格式"outerClassName.InnerClassName"
* 若是經過名稱自動注入,中間的點就可能引起問題
*/
protected String buildDefaultBeanName(BeanDefinition definition) {
    
    //cn.mrdear.exception.GlobalException => GlobalException
    String shortClassName = ClassUtils.getShortName(definition.getBeanClassName());
    
    //此方法將字符串首字符大寫轉小寫,可是若是第二個字符也是大寫就不進行轉換,由於他多是
    //這樣的格式--> "URL"
    return Introspector.decapitalize(shortClassName);
}

2.4 postProcessBeanDefinition

跟蹤標記2.4的方法

在ClassPathBeanDefinitionScanner類中實現

//2.4給beanDefinition設置默認值,自動注入的候選者
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);

/**
* Apply further settings to the given bean definition,
* beyond the contents retrieved from scanning the component class.
*
* 除從組件class掃描檢索的內容外,應用更多的設置到bean definition
*/
protected void postProcessBeanDefinition(AbstractBeanDefinition beanDefinition, String beanName) {
    //掃描器中的Defaults應用到beanDefinition中
    beanDefinition.applyDefaults(this.beanDefinitionDefaults);
    if (this.autowireCandidatePatterns != null) {
        
        //設置自動注入候選者
        beanDefinition.setAutowireCandidate(PatternMatchUtils.simpleMatch(this.autowireCandidatePatterns, beanName));
    }
}

2.5 processCommonDefinitionAnnotations

跟蹤標記2.5的方法

在AnnotationConfigUtils類中實現

//2.5拿到類上其餘的context名稱空間的註解,若是有的話,獲取其value屬性
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);


public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) {
    processCommonDefinitionAnnotations(abd, abd.getMetadata());
}


static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
    
    //類上是否有Lazy註解,或者註解的元註解上有Lazy註解
    if (metadata.isAnnotated(Lazy.class.getName())) {
        
        //拿到@Lazy註解上的全部屬性,獲取其value屬性的值
        abd.setLazyInit(attributesFor(metadata, Lazy.class).getBoolean("value"));
    }
    
    //metadata不屬於abd的狀況
    else if (abd.getMetadata() != metadata && abd.getMetadata().isAnnotated(Lazy.class.getName())) {
        abd.setLazyInit(attributesFor(abd.getMetadata(), Lazy.class).getBoolean("value"));
    }

    //類上是否有Primary註解,或者註解的元註解上有Primary註解
    if (metadata.isAnnotated(Primary.class.getName())) {
        abd.setPrimary(true);
    }
    
    //類上是否有DependsOn註解,或者註解的元註解上有DependsOn註解
    if (metadata.isAnnotated(DependsOn.class.getName())) {
        
        //拿到@DependsOn註解上的全部屬性,獲取其value屬性的值
        abd.setDependsOn(attributesFor(metadata, DependsOn.class).getStringArray("value"));
    }

    if (abd instanceof AbstractBeanDefinition) {
        AbstractBeanDefinition absBd = (AbstractBeanDefinition) abd;
        
        //類上是否有Role註解,或者註解的元註解上有Role註解
        if (metadata.isAnnotated(Role.class.getName())) {
            
            //拿到@Role註解上的全部屬性,獲取其value屬性的值
            absBd.setRole(attributesFor(metadata, Role.class).getNumber("value").intValue());
        }
        
        //類上是否有Description註解,或者註解的元註解上有Role註解
        if (metadata.isAnnotated(Description.class.getName())) {
            
            //拿到@Description註解上的全部屬性,獲取其value屬性的值
            absBd.setDescription(attributesFor(metadata, Description.class).getString("value"));
        }
    }
}

2.6 checkCandidate

跟蹤標記2.6的方法

在ClassPathBeanDefinitionScanner類中實現

//2.6檢查beanName是否正確匹配對應的bean Definition,該名稱是否已經被註冊
checkCandidate(beanName, candidate)

    
protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition) throws IllegalStateException {
    
    //工廠中沒有註冊這個beanName,返回true
    if (!this.registry.containsBeanDefinition(beanName)) {
        return true;
    }
    BeanDefinition existingDef = this.registry.getBeanDefinition(beanName);
    BeanDefinition originatingDef = existingDef.getOriginatingBeanDefinition();
    if (originatingDef != null) {
        existingDef = originatingDef;
    }
    
    //若是已存在的和入參的beanDefinition可以兼容,就返回false,不然拋出異常
    if (isCompatible(beanDefinition, existingDef)) {
        return false;
    }
    throw new ConflictingBeanDefinitionException("Annotation-specified bean name '" + beanName +
                                                 "' for bean class [" + beanDefinition.getBeanClassName() + "] conflicts with existing, " +
                                                 "non-compatible bean definition of same name and class [" + existingDef.getBeanClassName() + "]");
}

3.registerComponents

跟蹤標記3的方法

此方法在ComponentScanBeanDefinitionParser類中實現

// 3. 註冊組件
registerComponents(parserContext.getReaderContext(), beanDefinitions, element);

protected void registerComponents(
    XmlReaderContext readerContext, Set<BeanDefinitionHolder> beanDefinitions, Element element) {
    
    //這裏返回的是null
    Object source = readerContext.extractSource(element);
    
    //拿到組合組件定義對象,以完整標籤名作爲name
    CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), source);

    for (BeanDefinitionHolder beanDefHolder : beanDefinitions) {
        
        //分兩部分看
        //3.1bean組件定義的構造初始化
        //將建立好的BeanComponentDefinition放入到組合組件定義的nestedComponents中
        //nestedComponents是一個LinkedList
        compositeDef.addNestedComponent(new BeanComponentDefinition(beanDefHolder));
    }

    // Register annotation config processors, if necessary.
    // 若是必要的話,註冊註解配置處理器
    boolean annotationConfig = true;
    
    //拿到component-scan標籤的annotation-config屬性
    if (element.hasAttribute(ANNOTATION_CONFIG_ATTRIBUTE)) {
        
        //默認設置爲true
        annotationConfig = Boolean.valueOf(element.getAttribute(ANNOTATION_CONFIG_ATTRIBUTE));
    }
    if (annotationConfig) {
        
        //3.2查看怎麼註冊註解配置處理器
        Set<BeanDefinitionHolder> processorDefinitions =
            AnnotationConfigUtils.registerAnnotationConfigProcessors(readerContext.getRegistry(), source);
        for (BeanDefinitionHolder processorDefinition : processorDefinitions) {
            
            //若是有爲被註冊的處理器,註冊完成後再添加到組合組件定義中
            compositeDef.addNestedComponent(new BeanComponentDefinition(processorDefinition));
        }
    }
    
    //這裏空實現
    readerContext.fireComponentRegistered(compositeDef);
}

3.1 BeanComponentDefinition

跟蹤標記3.1的方法

進入BeanComponentDefinition的構造方法

//3.1bean組件定義的構造初始化
new BeanComponentDefinition(beanDefHolder)


public BeanComponentDefinition(BeanDefinitionHolder holder) {
    
    //先看父類構造作了什麼操做
    super(holder);
    
    //找到這個class中,屬性爲註冊到工廠中的bean deifiniion或者BeanReference的集合
    findInnerBeanDefinitionsAndBeanReferences(holder.getBeanDefinition());
}

/**
* 其實BeanComponentDefinition就是BeanDefinitionHolder的子類
* 
* Copy constructor: Create a new BeanDefinitionHolder with the
* same contents as the given BeanDefinitionHolder instance.
* <p>Note: The wrapped BeanDefinition reference is taken as-is;
* it is {@code not} deeply copied.
*
* 複製構造:利用給定的beanDefinitionHolder實例,建立一個新的BeanDefinitionHolder
*/
public BeanDefinitionHolder(BeanDefinitionHolder beanDefinitionHolder) {
    Assert.notNull(beanDefinitionHolder, "BeanDefinitionHolder must not be null");
    this.beanDefinition = beanDefinitionHolder.getBeanDefinition();
    this.beanName = beanDefinitionHolder.getBeanName();
    this.aliases = beanDefinitionHolder.getAliases();
}

而後再瞭解下findInnerBeanDefinitionsAndBeanReferences方法作了什麼事情

private void findInnerBeanDefinitionsAndBeanReferences(BeanDefinition beanDefinition) {
    List<BeanDefinition> innerBeans = new ArrayList<BeanDefinition>();
    List<BeanReference> references = new ArrayList<BeanReference>();
    PropertyValues propertyValues = beanDefinition.getPropertyValues();
    
    //拿到類中全部的屬性值,若是屬性爲在bean工廠中註冊的bean definition、或者
    //有BeanReference--非實體bean只是邏輯上的引用,則放入集合
    for (int i = 0; i < propertyValues.getPropertyValues().length; i++) {
        PropertyValue propertyValue = propertyValues.getPropertyValues()[i];
        Object value = propertyValue.getValue();
        if (value instanceof BeanDefinitionHolder) {
            innerBeans.add(((BeanDefinitionHolder) value).getBeanDefinition());
        }
        else if (value instanceof BeanDefinition) {
            innerBeans.add((BeanDefinition) value);
        }
        else if (value instanceof BeanReference) {
            references.add((BeanReference) value);
        }
    }
    this.innerBeanDefinitions = innerBeans.toArray(new BeanDefinition[innerBeans.size()]);
    this.beanReferences = references.toArray(new BeanReference[references.size()]);
}

3.2 registerAnnotationConfigProcessors

跟蹤標記3.2的方法

進入AnnotationConfigUtils的構造方法

//3.2查看怎麼註冊註解配置處理器
Set<BeanDefinitionHolder> processorDefinitions =
    AnnotationConfigUtils.registerAnnotationConfigProcessors(readerContext.getRegistry(), source);


/**
* Register all relevant annotation post processors in the given registry.
*
* 註冊全部相關的註解後處理器到指定工廠中
*/
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
    BeanDefinitionRegistry registry, Object source) {
    
    DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
    if (beanFactory != null) {
        
        //bean工廠的依賴比較器不是AnnotationAwareOrderComparator的實例,
        //就換成AnnotationAwareOrderComparator
        if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
            beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
        }
        
        //bean工廠的自動注入候選解析器不是ContextAnnotationAutowireCandidateResolver的實例,
        //就換成ContextAnnotationAutowireCandidateResolver
        if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
            beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
        }
    }

    Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<BeanDefinitionHolder>(4);
    
    //工廠中沒有註冊internalConfigurationAnnotationProcessor,則註冊
    if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    //工廠中沒有註冊internalAutowiredAnnotationProcessor,則註冊
    if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    }
    
    //工廠中沒有註冊internalRequiredAnnotationProcessor,則註冊
    if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
    // 檢查是否支持JSR-250,若是有則添加CommonAnnotationBeanPostProcessor
    if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
    // 檢查JPA支持,若是有則添加PersistenceAnnotationBeanPostProcessor
    if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition();
        try {
            def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
                                                AnnotationConfigUtils.class.getClassLoader()));
        }
        catch (ClassNotFoundException ex) {
            throw new IllegalStateException(
                "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
        }
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    //工廠中沒有註冊internalEventListenerProcessor,則註冊
    if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
    }
    
    //工廠中沒有註冊internalEventListenerFactory,則註冊
    if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
    }

    return beanDefs;
}

到這裏也就跟蹤完了。

其實還有不少種狀況沒有分析,只能先把握總體的脈絡,遇到具體的狀況再作具體分析。

總結

  • 獲取標籤context:component-scan上的base-package屬性,有佔位符的進行解析,並切分爲數組形式
  • 1.配置掃描器
  • 2.利用掃描器掃描包,註冊 BeanDefinition
  • 3.註冊組件

——————————————————————————————————

  • 1
  • 建立一個掃描器,默認狀況下會註冊幾個過濾器,其實就是在掃描器的 includeFilters 屬性中保存幾個 AnnotationTypeFilter 類型的過濾器,其中包括註解Component
  • 解析子標籤context:exclude-filtercontext:exclude-filter,根據子標籤上的 type 屬性建立不一樣的類型過濾器。並添加到掃描器的 excludeFilters 屬性或 includeFilters 屬性中。
  • 添加其餘屬性等

——————————————————————————————————

  • 2
  • 遍歷全部的base-package,經過base-package獲取 Resource 對象數組,對符合條件的 Resource 組裝成 BeanDefinition ,並將 BeanDefinition 集合返回。條件:不匹配 excludeFilters 中的過濾器,匹配 includeFilters 的過濾器的同時,若是有@Conditional註解須要知足限制。
  • 解析@Scope等註解以及元註解,設置屬性
  • 包裝 BeanDefinition 生成 DefinitionHolder,註冊 BeanDefinition 和別名到工廠中,返回 DefinitionHolder 集合

——————————————————————————————————

  • 3
  • 新建一個掃描組件,添加標籤名,並把 DefinitionHolder 集合包裝後一一放入到組件中
  • 若是有沒被註冊的後處理器,註冊到工廠後再添加到掃描組件中
相關文章
相關標籤/搜索