• Spring组件扫描--源码跟踪


    看这篇文章之前可以先了解之前的跟踪流程,https://www.jianshu.com/p/4934233f0ead

    代码过宽,可以shift + 鼠标滚轮 左右滑动查看

    这篇文章主要跟踪spring配置文件中component-scan标签,查看它是怎样被解析扫描生成对应的beanDefinition。

    在applicationContext.xml中做以下配置:

    <!-- 启动组件扫描,排除@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方法作为开始,向下跟踪。

    /**
    * 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);
        }
    }
    

    对以上方法不太了解的可以先看下这篇文章:

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

    因为component-scan标签属于context名称空间,所以走这个方法。

    delegate.parseCustomElement(ele);
    

    这个方法的实现在BeanDefinitionParserDelegate类中

    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方法。

    /**
    * 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);
        
        //字符串中有" ,;
    	"等符号就看做分隔符,分割成数组
        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 集合包装后一一放入到组件中
    • 如果有没被注册的后处理器,注册到工厂后再添加到扫描组件中
  • 相关阅读:
    [转]c#的DateTime.Now函数详解
    PHP学习笔记
    【错误】MsDepSvc.exe 站用了80端口/IIS的0×8ffe2740错误解决方
    IIS连接数
    Mybatis3.2.1整合Spring3.1
    linux常用命令大全
    Spring3.2新注解@ControllerAdvice
    SpringMVC强大的数据绑定(2)——第六章 注解式控制器详解
    Console命令详解,让调试js代码变得更简单
    String.format
  • 原文地址:https://www.cnblogs.com/feng-jq/p/10282248.html
Copyright © 2020-2023  润新知