Spring源码解析之@Configuration注解解析

阅读须知

  • Spring源码版本:4.3.8
  • 文章中使用/* */注释的方法会做深入分析

正文

我们首先来看一个示例,用注解不用xml配置文件如何配置 Spring:

@Configuration
@ComponentScan(basePackages = {"com.test"})
@ImportResource("classpath:application-context.xml")
@Import(OtherConfiguration.class)
public class SpringConfiguration {

    @Bean
    @Scope("prototype")
    public TestBean testBean() {
        return new TestBean();
    }

}

这样就完成了一个简单的 Spring 配置,我们来分别简单介绍一下示例中出现的各个注解的作用:

  • @Configuration:我们可以把它理解为 Spring 的 xml 配置文件中的<beans/>标签,也就是 Spring 容器的上下文
  • @Bean:我们可以把它理解为 Spring 的 xml 配置文件中的<bean/>标签,也就是用来注册一个 bean 的,我们可以配置 initMethod、destroyMethod 等注解属性来完成和<bean/>标签中对应属性配置一样的功能
  • @Scope:用来配置bean的作用域,默认是 singleton,也就是单例
  • @ComponentScan:我们可以把它理解为 Spring 的 xml 配置文件中的<context:component-scan/>标签,也就是用来扫描 @Component 注解注册 bean 的,如果未指定包,则将从声明此注解的类的包进行扫描
  • @ImportResource:我们可以使用它来引入另一个 Spring 配置文件的配置
  • @Import:我们可以使用它来引入另一个注解配置

启动时我们可以使用 AnnotationConfigApplicationContext 替换 ClassPathXmlApplicationContext 来启动Spring容器,eg:ApplicationContext context = new AnnotationConfigApplicationContext(TestConfiguration.class);

在 web 应用中,我们需要修改 web.xml 中的配置:

<context-param>
    <param-name>contextClass</param-name>
    <param-value>
        org.springframework.web.context.
        support.AnnotationConfigWebApplicationContext
    </param-value>
</context-param>
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        com.test.SpringConfiguration
    </param-value>
</context-param>

这里的contextClass参数在默认不指定的情况下为XmlWebApplicationContext,所以我们在使用 xml 配置 Spring 的时候是不需要指定这个参数的。

Spring源码解析之@Component注解的扫描文章结尾,我们看到 Spring 注册了 ConfigurationClassPostProcessor,它实现了 BeanFactoryPostProcessor,我们已经很多次的提及了这个接口的作用,这里就不再重复了,它会在 bean 创建之前调用,示例中出现的这些注解就是由 ConfigurationClassPostProcessor 来完成解析,我们来看实现:
ConfigurationClassPostProcessor:

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
    int registryId = System.identityHashCode(registry);
    if (this.registriesPostProcessed.contains(registryId)) {
        throw new IllegalStateException(
                "postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
    }
    if (this.factoriesPostProcessed.contains(registryId)) {
        throw new IllegalStateException(
                "postProcessBeanFactory already called on this post-processor against " + registry);
    }
    this.registriesPostProcessed.add(registryId);
    /* 解析 @Configuration 注解,注册 BeanDefinition */
    processConfigBeanDefinitions(registry);
}

ConfigurationClassPostProcessor:

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
    List<BeanDefinitionHolder> configCandidates = new ArrayList<BeanDefinitionHolder>();
    // 读取 BeanDefinition 注册中心中已经存在的 BeanDefinition 的 beanName
    String[] candidateNames = registry.getBeanDefinitionNames();
    for (String beanName : candidateNames) {
        BeanDefinition beanDef = registry.getBeanDefinition(beanName);
        // 判断如果已经处理过,无需再次处理
        if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
                ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
            if (logger.isDebugEnabled()) {
                logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
            }
        }
        /* 判断是否含有相关的几个注解 */
        else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
            configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
        }
    }
    // 没有@Configuration直接返回
    if (configCandidates.isEmpty()) {
        return;
    }
    // 按照注解的@Order进行排序
    Collections.sort(configCandidates, new Comparator<BeanDefinitionHolder>() {
        @Override
        public int compare(BeanDefinitionHolder bd1, BeanDefinitionHolder bd2) {
            int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
            int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
            return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;
        }
    });
    SingletonBeanRegistry sbr = null;
    // 如果有自定义的beanName生成器,则应用
    if (registry instanceof SingletonBeanRegistry) {
        sbr = (SingletonBeanRegistry) registry;
        if (!this.localBeanNameGeneratorSet && sbr.containsSingleton(CONFIGURATION_BEAN_NAME_GENERATOR)) {
            BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
            this.componentScanBeanNameGenerator = generator;
            this.importBeanNameGenerator = generator;
        }
    }
    // @Configuration注解的解析器
    ConfigurationClassParser parser = new ConfigurationClassParser(
            this.metadataReaderFactory, this.problemReporter, this.environment,
            this.resourceLoader, this.componentScanBeanNameGenerator, registry);
    Set<BeanDefinitionHolder> candidates = new LinkedHashSet<BeanDefinitionHolder>(configCandidates);
    Set<ConfigurationClass> alreadyParsed = new HashSet<ConfigurationClass>(configCandidates.size());
    do {
        /* 解析 */
        parser.parse(candidates);
        // 因为CGLIB代理的关系,这里需要校验@Configuration注解的类和@Bean注解的方法都是可以被覆盖的,也就是类不能被final修饰,方法可以重写
        parser.validate();
        Set<ConfigurationClass> configClasses = new LinkedHashSet<ConfigurationClass>(parser.getConfigurationClasses());
        // 移除已经解析过的
        configClasses.removeAll(alreadyParsed);
        if (this.reader == null) {
            // 创建BeanDefinitionReader
            this.reader = new ConfigurationClassBeanDefinitionReader(
                    registry, this.sourceExtractor, this.resourceLoader, this.environment,
                    this.importBeanNameGenerator, parser.getImportRegistry());
        }
        /* 加载BeanDefinition */
        this.reader.loadBeanDefinitions(configClasses);
        alreadyParsed.addAll(configClasses);
        candidates.clear();
        // 个人理解这个判断的含义是在这期间可能有新的BeanDefinition被注册了,所以要判断新注册的BeanDefinition中是否有需要解析的
        if (registry.getBeanDefinitionCount() > candidateNames.length) {
            // 获取新的beanDefinitionNames
            String[] newCandidateNames = registry.getBeanDefinitionNames();
            // 旧的beanDefinitionNames
            Set<String> oldCandidateNames = new HashSet<String>(Arrays.asList(candidateNames));
            // 保存已经解析过的className
            Set<String> alreadyParsedClasses = new HashSet<String>();
            for (ConfigurationClass configurationClass : alreadyParsed) {
                alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
            }
            // 遍历新的beanDefinitionNames
            for (String candidateName : newCandidateNames) {
                if (!oldCandidateNames.contains(candidateName)) {
                    BeanDefinition bd = registry.getBeanDefinition(candidateName);
                    // 如果在旧的中不包含并且class没有被解析过,则判断是否需要解析
                    if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
                            !alreadyParsedClasses.contains(bd.getBeanClassName())) {
                        candidates.add(new BeanDefinitionHolder(bd, candidateName));
                    }
                }
            }
            candidateNames = newCandidateNames;
        }
    }
    while (!candidates.isEmpty());
    if (sbr != null) {
        // 对ImportAware的支持
        if (!sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
            sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
        }
    }
    // 清理元数据缓存
    if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
        ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
    }
}

ConfigurationClassUtils:

public static boolean checkConfigurationClassCandidate(BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
    String className = beanDef.getBeanClassName();
    if (className == null) {
        return false;
    }
    AnnotationMetadata metadata;
    // 根据不同类型的的BeanDefinition获取对应的metadata元数据
    if (beanDef instanceof AnnotatedBeanDefinition &&
            className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {
        metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata();
    }
    else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {
        Class<?> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass();
        metadata = new StandardAnnotationMetadata(beanClass, true);
    }
    else {
        try {
            MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className);
            metadata = metadataReader.getAnnotationMetadata();
        }
        catch (IOException ex) {
            if (logger.isDebugEnabled()) {
                logger.debug("Could not find class file for introspecting configuration annotations: " + className, ex);
            }
            return false;
        }
    }
    /* 判断是否有@Configuration注解 */
    if (isFullConfigurationCandidate(metadata)) {
        beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
    }
    /* 判断是否有另外相关的几个注解 */
    else if (isLiteConfigurationCandidate(metadata)) {
        beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
    }
    else {
        return false;
    }
    // 如果有@Order注解,设置order属性用于排序
    Map<String, Object> orderAttributes = metadata.getAnnotationAttributes(Order.class.getName());
    if (orderAttributes != null) {
        beanDef.setAttribute(ORDER_ATTRIBUTE, orderAttributes.get(AnnotationUtils.VALUE));
    }
    return true;
}

ConfigurationClassUtils:

public static boolean isFullConfigurationCandidate(AnnotationMetadata metadata) {
    // 是否有@Configuration类注解
    return metadata.isAnnotated(Configuration.class.getName());
}

ConfigurationClassUtils:

public static boolean isLiteConfigurationCandidate(AnnotationMetadata metadata) {
    // 接口不通过
    if (metadata.isInterface()) {
        return false;
    }
    /* 是否有candidateIndicators中包含的类注解 */
    for (String indicator : candidateIndicators) {
        if (metadata.isAnnotated(indicator)) {
            return true;
        }
    }
    try {
        // 是否有@Bean方法注解
        return metadata.hasAnnotatedMethods(Bean.class.getName());
    }
    catch (Throwable ex) {
        if (logger.isDebugEnabled()) {
            logger.debug("Failed to introspect @Bean methods on class [" + metadata.getClassName() + "]: " + ex);
        }
        return false;
    }
}

ConfigurationClassUtils:

static {
    candidateIndicators.add(Component.class.getName());
    candidateIndicators.add(ComponentScan.class.getName());
    candidateIndicators.add(Import.class.getName());
    candidateIndicators.add(ImportResource.class.getName());
}

下面就是配置解析的流程:
ConfigurationClassParser:

public void parse(Set<BeanDefinitionHolder> configCandidates) {
    this.deferredImportSelectors = new LinkedList<DeferredImportSelectorHolder>();
    for (BeanDefinitionHolder holder : configCandidates) {
        BeanDefinition bd = holder.getBeanDefinition();
        try {
            if (bd instanceof AnnotatedBeanDefinition) {
                /* 解析配置 */
                parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
            }
            else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
                /* 解析配置 */
                parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
            }
            else {
                /* 解析配置 */
                parse(bd.getBeanClassName(), holder.getBeanName());
            }
        }
        catch (BeanDefinitionStoreException ex) {
            throw ex;
        }
        catch (Throwable ex) {
            throw new BeanDefinitionStoreException(
                    "Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
        }
    }
    /* 处理延迟导入 */
    processDeferredImportSelectors();
}

ConfigurationClassParser:

protected final void parse(String className, String beanName) throws IOException {
    MetadataReader reader = this.metadataReaderFactory.getMetadataReader(className);
    /* 解析配置 */
    processConfigurationClass(new ConfigurationClass(reader, beanName));
}

protected final void parse(Class<?> clazz, String beanName) throws IOException {
    /* 解析配置 */
    processConfigurationClass(new ConfigurationClass(clazz, beanName));
}

protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
    /* 解析配置 */
    processConfigurationClass(new ConfigurationClass(metadata, beanName));
}

三个重载的parse方法最终都会被包装成ConfigurationClass调用processConfigurationClass方法:
ConfigurationClassParser:

protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
    /* 判断是否需要跳过 */
    if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
        return;
    }
    ConfigurationClass existingClass = this.configurationClasses.get(configClass);
    // 是否已经配置过
    if (existingClass != null) {
        // 是否已经注册
        if (configClass.isImported()) {
            if (existingClass.isImported()) {
                // 已经存在的ConfigurationClass合并新ConfigurationClass的导入者
                existingClass.mergeImportedBy(configClass);
            }
            // 注册过无需再次注册
            return;
        }
        else {
            // 这里代表有重复的BeanDefinition,将已经存在的去掉重新注册
            this.configurationClasses.remove(configClass);
            for (Iterator<ConfigurationClass> it = this.knownSuperclasses.values().iterator(); it.hasNext();) {
                if (configClass.equals(it.next())) {
                    it.remove();
                }
            }
        }
    }
    // 递归处理当前ConfigurationClass和它的父类
    SourceClass sourceClass = asSourceClass(configClass);
    do {
        /* 处理ConfigurationClass */
        sourceClass = doProcessConfigurationClass(configClass, sourceClass);
    }
    while (sourceClass != null);
    // 保存已经处理过的ConfigurationClass
    this.configurationClasses.put(configClass, configClass);
}

ConditionEvaluator:

public boolean shouldSkip(AnnotatedTypeMetadata metadata, ConfigurationPhase phase) {
    // 是否有@Conditional注解,没有则不用判断其中配置的条件,无需跳过
    if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) {
        return false;
    }
    // 如果处理阶段(包括解析配置阶段和注册bean阶段)等于null,递归判断是否需要跳过
    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>();
    // 遍历@Conditional的value属性值
    for (String[] conditionClasses : getConditionClasses(metadata)) {
        for (String conditionClass : conditionClasses) {
            // 转换成Condition对象
            Condition condition = getCondition(conditionClass, this.context.getClassLoader());
            conditions.add(condition);
        }
    }
    // 按照order排序
    AnnotationAwareOrderComparator.sort(conditions);
    for (Condition condition : conditions) {
        ConfigurationPhase requiredPhase = null;
        if (condition instanceof ConfigurationCondition) {
            requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
        }
        if (requiredPhase == null || requiredPhase == phase) {
            // 如果Condition条件不匹配,则需要跳过
            if (!condition.matches(this.context, metadata)) {
                return true;
            }
        }
    }
    return false;
}

这里简单介绍一下@Conditional注解,注意不是上文的@Configuration注解,我们可以实现Condition接口来定义个性化的匹配条件,并在@Conditional注解中声明这些Condition,Spring会按照我们定义的条件来确定是否创建注解范围内的bean。
ConfigurationClassParser:

protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
        throws IOException {
    // 递归处理成员内部类
    processMemberClasses(configClass, sourceClass);
    // 提取@PropertySource注解的属性遍历进行处理
    for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
            sourceClass.getMetadata(), PropertySources.class,
            org.springframework.context.annotation.PropertySource.class)) {
        if (this.environment instanceof ConfigurableEnvironment) {
            /* 处理属性 */
            processPropertySource(propertySource);
        }
        else {
            logger.warn("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
                    "]. Reason: Environment must implement ConfigurableEnvironment");
        }
    }
    // 提取@ComponentScan注解的属性遍历进行处理
    Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
            sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
    // 同样的@Conditional注解条件判断
    if (!componentScans.isEmpty() &&
            !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
        for (AnnotationAttributes componentScan : componentScans) {
            /* 解析 */
            Set<BeanDefinitionHolder> scannedBeanDefinitions =
                    this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
            // 如果扫描生成的BeanDefinition有需要进一步处理的,递归再次进行同样的解析处理
            for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
                if (ConfigurationClassUtils.checkConfigurationClassCandidate(
                        holder.getBeanDefinition(), this.metadataReaderFactory)) {
                    parse(holder.getBeanDefinition().getBeanClassName(), holder.getBeanName());
                }
            }
        }
    }
    /* 提取@Import注解的属性遍历进行处理 */
    processImports(configClass, sourceClass, getImports(sourceClass), true);
    // 提取@ImportResource注解的属性遍历进行处理
    if (sourceClass.getMetadata().isAnnotated(ImportResource.class.getName())) {
        AnnotationAttributes importResource =
                AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
        // locations属性
        String[] resources = importResource.getStringArray("locations");
        // reader属性
        Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader"); 
        for (String resource : resources) {
            // 处理路径中的特殊符号
            String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
            configClass.addImportedResource(resolvedResource, readerClass);
        }
    }
    /* 提取@Bean注解的方法的元数据 */
    Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
    for (MethodMetadata methodMetadata : beanMethods) {
        configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
    }
    // 处理实现的所有接口中@Bean注解的方法,去上面的处理方法一样,但不是抽象方法,因为java8中接口有默认方法和其他具体方法,这里只会处理这些方法的@Bean注解
    processInterfaces(configClass, sourceClass);
    // 处理父类
    if (sourceClass.getMetadata().hasSuperClass()) {
        String superclass = sourceClass.getMetadata().getSuperClassName();
        // java包的父类和已经处理过的父类不处理
        if (!superclass.startsWith("java") && !this.knownSuperclasses.containsKey(superclass)) {
            // 标记父类已经处理过
            this.knownSuperclasses.put(superclass, configClass);
            // 返回父类的SourceClass再次进行递归处理
            return sourceClass.getSuperClass();
        }
    }
    return null;
}

ConfigurationClassParser:

private void processPropertySource(AnnotationAttributes propertySource) throws IOException {
    // name属性
    String name = propertySource.getString("name");
    if (!StringUtils.hasLength(name)) {
        name = null;
    }
    // encoding属性
    String encoding = propertySource.getString("encoding");
    if (!StringUtils.hasLength(encoding)) {
        encoding = null;
    }
    // value属性
    String[] locations = propertySource.getStringArray("value");
    Assert.isTrue(locations.length > 0, "At least one @PropertySource(value) location is required");
    // ignoreResourceNotFound属性
    boolean ignoreResourceNotFound = propertySource.getBoolean("ignoreResourceNotFound");
    // factory属性
    Class<? extends PropertySourceFactory> factoryClass = propertySource.getClass("factory");
    PropertySourceFactory factory = (factoryClass == PropertySourceFactory.class ?
            DEFAULT_PROPERTY_SOURCE_FACTORY : BeanUtils.instantiateClass(factoryClass));
    for (String location : locations) {
        try {
            // 处理路径中的特殊字符
            String resolvedLocation = this.environment.resolveRequiredPlaceholders(location);
            // 根据路径获取资源
            Resource resource = this.resourceLoader.getResource(resolvedLocation);
            // 添加属性到Environment环境对象中的propertySources中,
            addPropertySource(factory.createPropertySource(name, new EncodedResource(resource, encoding)));
        }
        catch (IllegalArgumentException ex) {
            if (ignoreResourceNotFound) {
                if (logger.isInfoEnabled()) {
                    logger.info("Properties location [" + location + "] not resolvable: " + ex.getMessage());
                }
            }
            else {
                throw ex;
            }
        }
        catch (IOException ex) {
            if (ignoreResourceNotFound &&
                    (ex instanceof FileNotFoundException || ex instanceof UnknownHostException)) {
                if (logger.isInfoEnabled()) {
                    logger.info("Properties location [" + location + "] not resolvable: " + ex.getMessage());
                }
            }
            else {
                throw ex;
            }
        }
    }
}

ComponentScanAnnotationParser:

public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
    Assert.state(this.environment != null, "Environment must not be null");
    Assert.state(this.resourceLoader != null, "ResourceLoader must not be null");
    // 创建Scanner
    ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
            componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
    // nameGenerator属性
    Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
    boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);
    scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator :
            BeanUtils.instantiateClass(generatorClass));
    // scopedProxy属性
    ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy");
    if (scopedProxyMode != ScopedProxyMode.DEFAULT) {
        scanner.setScopedProxyMode(scopedProxyMode);
    }
    else {
        // scopeResolver属性
        Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");
        scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));
    }
    // resourcePattern属性
    scanner.setResourcePattern(componentScan.getString("resourcePattern"));
    // includeFilters属性
    for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {
        for (TypeFilter typeFilter : typeFiltersFor(filter)) {
            scanner.addIncludeFilter(typeFilter);
        }
    }
    // excludeFilters属性
    for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) {
        for (TypeFilter typeFilter : typeFiltersFor(filter)) {
            scanner.addExcludeFilter(typeFilter);
        }
    }
    // lazyInit属性
    boolean lazyInit = componentScan.getBoolean("lazyInit");
    if (lazyInit) {
        scanner.getBeanDefinitionDefaults().setLazyInit(true);
    }
    Set<String> basePackages = new LinkedHashSet<String>();
    // basePackages属性
    String[] basePackagesArray = componentScan.getStringArray("basePackages");
    for (String pkg : basePackagesArray) {
        String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),
                ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
        basePackages.addAll(Arrays.asList(tokenized));
    }
    for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) {
        basePackages.add(ClassUtils.getPackageName(clazz));
    }
    if (basePackages.isEmpty()) {
        basePackages.add(ClassUtils.getPackageName(declaringClass));
    }
    scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
        @Override
        protected boolean matchClassName(String className) {
            return declaringClass.equals(className);
        }
    });
    // 扫描
    return scanner.doScan(StringUtils.toStringArray(basePackages));
}

这里看起来是不是很熟悉,没错啦,我们在分析<context:component-scan/>标签的解析时也是同样的流程,只不过这里是解析注解方式的@ComponentScan。
ConfigurationClassParser:

private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
        Collection<SourceClass> importCandidates, boolean checkForCircularImports) throws IOException {
    if (importCandidates.isEmpty()) {
        return;
    }
    // 栈中链式导入的检查,检查正在导入的class是否有冲突
    if (checkForCircularImports && isChainedImportOnStack(configClass)) {
        this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
    }
    else {
        // 入栈标识正在解析中
        this.importStack.push(configClass);
        try {
            for (SourceClass candidate : importCandidates) {
                // 我们可以实现ImportSelector来决定导入哪些配置
                if (candidate.isAssignable(ImportSelector.class)) {
                    Class<?> candidateClass = candidate.loadClass();
                    ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
                    // 执行selector实现的Aware的相关set方法
                    ParserStrategyUtils.invokeAwareMethods(
                            selector, this.environment, this.resourceLoader, this.registry);
                    if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {
                        // 如果是延迟导入的selector添加到延迟导入的集合中稍后处理
                        this.deferredImportSelectors.add(
                                new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector));
                    }
                    else {
                        // 提取
                        String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
                        Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
                        // 递归解析
                        processImports(configClass, currentSourceClass, importSourceClasses, false);
                    }
                }
                // 我们可以实现ImportBeanDefinitionRegistrar来注册额外的BeanDefinition
                else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
                    Class<?> candidateClass = candidate.loadClass();
                    ImportBeanDefinitionRegistrar registrar =
                            BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
                    ParserStrategyUtils.invokeAwareMethods(
                            registrar, this.environment, this.resourceLoader, this.registry);
                    configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
                }
                else {
                    // 如果两者都不是就按照@Configuration注解类的解析方式再次解析一遍
                    this.importStack.registerImport(
                            currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
                    processConfigurationClass(candidate.asConfigClass(configClass));
                }
            }
        }
        catch (BeanDefinitionStoreException ex) {
            throw ex;
        }
        catch (Throwable ex) {
            throw new BeanDefinitionStoreException(
                    "Failed to process import candidates for configuration class [" +
                    configClass.getMetadata().getClassName() + "]", ex);
        }
        finally {
            // 出栈表示已经解析完
            this.importStack.pop();
        }
    }
}

这里我们看到了两个接口ImportSelector和ImportBeanDefinitionRegistrar,这两个接口在Spring boot中有非常重要的作用,详见笔者关于Spring boot源码分析的文章。
下面是延迟导入的处理:
ConfigurationClassParser:

private void processDeferredImportSelectors() {
    List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
    this.deferredImportSelectors = null;
    // 排序
    Collections.sort(deferredImports, DEFERRED_IMPORT_COMPARATOR);
    for (DeferredImportSelectorHolder deferredImport : deferredImports) {
        ConfigurationClass configClass = deferredImport.getConfigurationClass();
        try {
            // 同样的提取
            String[] imports = deferredImport.getImportSelector().selectImports(configClass.getMetadata());
            // 同样的处理
            processImports(configClass, asSourceClass(configClass), asSourceClasses(imports), false);
        }
        catch (BeanDefinitionStoreException ex) {
            throw ex;
        }
        catch (Throwable ex) {
            throw new BeanDefinitionStoreException(
                    "Failed to process import candidates for configuration class [" +
                    configClass.getMetadata().getClassName() + "]", ex);
        }
    }
}

最后就是注册BeanDefinition了:
ConfigurationClassBeanDefinitionReader:

public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
    TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
    for (ConfigurationClass configClass : configurationModel) {
        /* 加载BeanDefinition */
        loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
    }
}

ConfigurationClassBeanDefinitionReader:

private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass,
        TrackedConditionEvaluator trackedConditionEvaluator) {
    // 判断是否需要跳过,与之前解析@Configuration判断是否跳过的逻辑是相同的
    if (trackedConditionEvaluator.shouldSkip(configClass)) {
        // 如果需要跳过则将相关已经注册的资源移除掉
        String beanName = configClass.getBeanName();
        if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
            this.registry.removeBeanDefinition(beanName);
        }
        this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
        return;
    }
    if (configClass.isImported()) {
        /* 注册@Configuration注解的当前类为一个BeanDefinition */
        registerBeanDefinitionForImportedConfigurationClass(configClass);
    }
    for (BeanMethod beanMethod : configClass.getBeanMethods()) {
        /* 加载@Bean注解的方法需要生成的BeanDefinition */
        loadBeanDefinitionsForBeanMethod(beanMethod);
    }
    /* 加载@ImportResource注解配置的资源需要生成的BeanDefinition */
    loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
    // 调用自定义的ImportBeanDefinitionRegistrar的registerBeanDefinitions方法注册BeanDefinition
    loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}

ConfigurationClassBeanDefinitionReader:

private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) {
    AnnotationMetadata metadata = configClass.getMetadata();
    AnnotatedGenericBeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata);
    // scope属性解析
    ScopeMetadata scopeMetadata = scopeMetadataResolver.resolveScopeMetadata(configBeanDef);
    configBeanDef.setScope(scopeMetadata.getScopeName());
    // 生成beanName
    String configBeanName = this.importBeanNameGenerator.generateBeanName(configBeanDef, this.registry);
    /* 通用注解解析 */
    AnnotationConfigUtils.processCommonDefinitionAnnotations(configBeanDef, metadata);
    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(configBeanDef, configBeanName);
    // 应用代理模式
    definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
    // 注册BeanDefinition
    this.registry.registerBeanDefinition(definitionHolder.getBeanName(), definitionHolder.getBeanDefinition());
    configClass.setBeanName(configBeanName);
    if (logger.isDebugEnabled()) {
        logger.debug("Registered bean definition for imported class '" + configBeanName + "'");
    }
}

大部分过程我们之前都分析过。
AnnotationConfigUtils:

static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
    // @Lazy注解属性提取和设置
    if (metadata.isAnnotated(Lazy.class.getName())) {
        abd.setLazyInit(attributesFor(metadata, Lazy.class).getBoolean("value"));
    }
    else if (abd.getMetadata() != metadata && abd.getMetadata().isAnnotated(Lazy.class.getName())) {
        abd.setLazyInit(attributesFor(abd.getMetadata(), Lazy.class).getBoolean("value"));
    }
    // @Primary注解属性提取和设置
    if (metadata.isAnnotated(Primary.class.getName())) {
        abd.setPrimary(true);
    }
    // @DependsOn注解属性提取和设置
    if (metadata.isAnnotated(DependsOn.class.getName())) {
        abd.setDependsOn(attributesFor(metadata, DependsOn.class).getStringArray("value"));
    }
    if (abd instanceof AbstractBeanDefinition) {
        AbstractBeanDefinition absBd = (AbstractBeanDefinition) abd;
        // @Role注解属性提取和设置
        if (metadata.isAnnotated(Role.class.getName())) {
            absBd.setRole(attributesFor(metadata, Role.class).getNumber("value").intValue());
        }
        // @Description注解属性提取和设置
        if (metadata.isAnnotated(Description.class.getName())) {
            absBd.setDescription(attributesFor(metadata, Description.class).getString("value"));
        }
    }
}

ConfigurationClassBeanDefinitionReader:

private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
    ConfigurationClass configClass = beanMethod.getConfigurationClass();
    MethodMetadata metadata = beanMethod.getMetadata();
    String methodName = metadata.getMethodName();
    // 相同的是否需要跳过的判断
    if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) {
        configClass.skippedBeanMethods.add(methodName);
        return;
    }
    if (configClass.skippedBeanMethods.contains(methodName)) {
        return;
    }
    // @Bean注解属性的提取
    AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);
    // name属性
    List<String> names = new ArrayList<String>(Arrays.asList(bean.getStringArray("name")));
    String beanName = (!names.isEmpty() ? names.remove(0) : methodName);
    for (String alias : names) {
        // 注册别名
        this.registry.registerAlias(beanName, alias);
    }
    if (isOverriddenByExistingDefinition(beanMethod, beanName)) {
        return;
    }
    ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata);
    beanDef.setResource(configClass.getResource());
    beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));
    // 对@Bean注解的静态方法和普通方法的不同处理
    if (metadata.isStatic()) {
        beanDef.setBeanClassName(configClass.getMetadata().getClassName());
        beanDef.setFactoryMethodName(methodName);
    }
    else {
        beanDef.setFactoryBeanName(configClass.getBeanName());
        beanDef.setUniqueFactoryMethodName(methodName);
    }
    beanDef.setAutowireMode(RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
    beanDef.setAttribute(RequiredAnnotationBeanPostProcessor.SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);
    // 通用注解的解析和设置
    AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);
    // autowire属性
    Autowire autowire = bean.getEnum("autowire");
    if (autowire.isAutowire()) {
        beanDef.setAutowireMode(autowire.value());
    }
    // initMethod属性
    String initMethodName = bean.getString("initMethod");
    if (StringUtils.hasText(initMethodName)) {
        beanDef.setInitMethodName(initMethodName);
    }
    // destroyMethod属性
    String destroyMethodName = bean.getString("destroyMethod");
    if (destroyMethodName != null) {
        beanDef.setDestroyMethodName(destroyMethodName);
    }
    ScopedProxyMode proxyMode = ScopedProxyMode.NO;
    // @Scope注解属性提取
    AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(metadata, Scope.class);
    if (attributes != null) {
        // value属性
        beanDef.setScope(attributes.getString("value"));
        // proxyMode属性
        proxyMode = attributes.getEnum("proxyMode");
        if (proxyMode == ScopedProxyMode.DEFAULT) {
            proxyMode = ScopedProxyMode.NO;
        }
    }
    BeanDefinition beanDefToRegister = beanDef;
    if (proxyMode != ScopedProxyMode.NO) {
        // 代理模式的应用
        BeanDefinitionHolder proxyDef = ScopedProxyCreator.createScopedProxy(
                new BeanDefinitionHolder(beanDef, beanName), this.registry,
                proxyMode == ScopedProxyMode.TARGET_CLASS);
        beanDefToRegister = new ConfigurationClassBeanDefinition(
                (RootBeanDefinition) proxyDef.getBeanDefinition(), configClass, metadata);
    }
    if (logger.isDebugEnabled()) {
        logger.debug(String.format("Registering bean definition for @Bean method %s.%s()",
                configClass.getMetadata().getClassName(), beanName));
    }
    this.registry.registerBeanDefinition(beanName, beanDefToRegister); // 注册BeanDefinition
}

其中大部分过程我们在默认标签解析的文章中分析bean标签的解析时都阐述过,这里不再重复说明。
ConfigurationClassBeanDefinitionReader:

private void loadBeanDefinitionsFromImportedResources(
        Map<String, Class<? extends BeanDefinitionReader>> importedResources) {
    Map<Class<?>, BeanDefinitionReader> readerInstanceCache = new HashMap<Class<?>, BeanDefinitionReader>();
    for (Map.Entry<String, Class<? extends BeanDefinitionReader>> entry : importedResources.entrySet()) {
        String resource = entry.getKey();
        Class<? extends BeanDefinitionReader> readerClass = entry.getValue();
        if (BeanDefinitionReader.class == readerClass) {
            // 根据配置资源的后缀判断使用哪种BeanDefinitionReader
            if (StringUtils.endsWithIgnoreCase(resource, ".groovy")) {
                readerClass = GroovyBeanDefinitionReader.class;
            }
            else {
                readerClass = XmlBeanDefinitionReader.class;
            }
        }
        BeanDefinitionReader reader = readerInstanceCache.get(readerClass);
        if (reader == null) {
            try {
                // 缓存中没有则进行初始化
                reader = readerClass.getConstructor(BeanDefinitionRegistry.class).newInstance(this.registry);
                if (reader instanceof AbstractBeanDefinitionReader) {
                    AbstractBeanDefinitionReader abdr = ((AbstractBeanDefinitionReader) reader);
                    abdr.setResourceLoader(this.resourceLoader);
                    abdr.setEnvironment(this.environment);
                }
                readerInstanceCache.put(readerClass, reader);
            }
            catch (Throwable ex) {
                throw new IllegalStateException(
                        "Could not instantiate BeanDefinitionReader class [" + readerClass.getName() + "]");
            }
        }
        // 加载BeanDefinition
        reader.loadBeanDefinitions(resource);
    }
}

到这里,以注解方式配置Spring的源码分析就完成了。

  • 2
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值