likes
comments
collection
share

Spring源码(十六)-ConfigurationClassPostProcessor

作者站长头像
站长
· 阅读数 20

日积月累,水滴石穿 😄

前言

上篇讲到 refresh()invokeBeanFactoryPostProcessors方法,该方法会执行所有

BeanDefinitionRegistryPostProcessorpostProcessBeanDefinitionRegistry()方法以及BeanFactoryPostProcessorpostProcessBeanFactory()方法。其重中之中就是 postProcessBeanDefinitionRegistry方法。

在无自定义的情况下,Spring容器中就一个实现了 BeanDefinitionRegistryPostProcessorBeanDefinition,它的名字是 ConfigurationClassPostProcessor

作用

各位可能还不了解 ConfigurationClassPostProcessor这个类的作用,小杰就先说说。

SpringBean 的都是基于 BeanDefinition 去创建的,所以需要先有 BeanDefinition,才会有 Bean

一个 BeanDefinition就代表着一个类,那一个类是怎么被解析为BeanDefinition呢?这个就是由 ConfigurationClassPostProcessor来完成的。

ConfigurationClassPostProcessor是一个BeanFactory后置处理器,会对写有 @Configuration@ComponentScan@ComponentScans@ImportResource@Import@Component@Bean注解的类解析为 BeanDefinition,并添加到容器。再由后续的流程将之注册为 Bean

ConfigurationClassPostProcessor

public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {
    
}

可以看到实现了BeanDefinitionRegistryPostProcessor ,而 BeanDefinitionRegistryPostProcessor 接口继承了 BeanFactoryPostProcessor 接口,那就会重写其postProcessBeanDefinitionRegistry方法和postProcessBeanFactory方法。

一、postProcessBeanDefinitionRegistry

我们先来看 postProcessBeanDefinitionRegistry方法。看看是如何进行扫描的!

@Override
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);
    }
    // registriesPostProcessed在本类的 postProcessBeanFactory 方法中会用到
    // 记录 registryId
    this.registriesPostProcessed.add(registryId);

    // 寻找配置类对应的BeanDefinition然后进行处理
    // 比如开始扫描
    processConfigBeanDefinitions(registry);
}

processConfigBeanDefinitions

核心逻辑在processConfigBeanDefinition()方法中。

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
    List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
    String[] candidateNames = registry.getBeanDefinitionNames();

    // 遍历BeanDefinitionRegistry中当前存在的beanDefinition,从中找出那些 beanDefinition 是配置 bean
    for (String beanName : candidateNames) {
        BeanDefinition beanDef = registry.getBeanDefinition(beanName);
        if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
            if (logger.isDebugEnabled()) {
                logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
            }
        }
        // 检查BeanDefinition是不是配置类候选者,那什么样的BeanDefinition符合呢?
        // 1. 存在@Configuration的就是配置类
        // 2. 存在@Component,@ComponentScan,@Import,@ImportResource
        // 3. 存在@Bean标注的方法
        else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
            //构建一个 BeanDefinitionHolder,添加到 configCandidates 集合中
            configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
        }
    }

    // Return immediately if no @Configuration classes were found
    // 没有找到配置类
    if (configCandidates.isEmpty()) {
        return;
    }

    // Sort by previously determined @Order value, if applicable
    // 将配置类进行排序,根据 @Order 注解进行排序,数字越低优先级越高
    configCandidates.sort((bd1, bd2) -> {
        int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
        int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
        return Integer.compare(i1, i2);
    });

    // Detect any custom bean name generation strategy supplied through the enclosing application context
    SingletonBeanRegistry sbr = null;
    // 当前 BeanFactory 是不是支持单例bean的注册,如果支持则设置一个 BeanNameGenerator
    // 用来在扫描 @Component 和 @Import 某个Bean时取名字
    if (registry instanceof SingletonBeanRegistry) {
        sbr = (SingletonBeanRegistry) registry;
        // localBeanNameGeneratorSet 默认为 false
        if (!this.localBeanNameGeneratorSet) {
            // 程序员可以指定一个beanName生成器 applicationContext.setBeanNameGenerator()
            // 不指定则使用默认的 ConfigurationBeanNameGenerator
            BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
                AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
            if (generator != null) {
                this.componentScanBeanNameGenerator = generator;
                this.importBeanNameGenerator = generator;
            }
        }
    }

    if (this.environment == null) {
        this.environment = new StandardEnvironment();
    }

    // Parse each @Configuration class
    // 配置 bean 解析器,解析器里存在 registry,所以在解析的过程中可以往 registry 中添加 BeanDefinition
    ConfigurationClassParser parser = new ConfigurationClassParser(
        this.metadataReaderFactory, this.problemReporter, this.environment,
        this.resourceLoader, this.componentScanBeanNameGenerator, registry);

    Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
    Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
    do {
        // 对配置BeanDefinition进行解析,解析完后会生成ConfigurationClass
        parser.parse(candidates);
        //验证
        parser.validate();

        Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
        configClasses.removeAll(alreadyParsed);

        // Read the model and create bean definitions based on its content
        if (this.reader == null) {
            this.reader = new ConfigurationClassBeanDefinitionReader(
                registry, this.sourceExtractor, this.resourceLoader, this.environment,
                this.importBeanNameGenerator, parser.getImportRegistry());
        }

        // 利用 reader 解析 ConfigurationClass,同时注册 BeanDefinition
        this.reader.loadBeanDefinitions(configClasses);
        // 省略部分代码 ... 
    }
    while (!candidates.isEmpty());

// 省略部分代码 ... 
}

方法一:checkConfigurationClassCandidate

检查BeanDefinition是不是配置类。配置类分两种 full、lite,如果加了@Configuration,那么配置类类型为full,如果加了@Bean@Component@ComponentScan@Import@ImportResource这些注解,配置类类型为lite

public static boolean checkConfigurationClassCandidate(
    BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {

    // 省略部分不重要的代码
    
    // 获取 Configuration 注解的属性信息,配置类分两种
    // 1、被 @Configuration 标记的配置类为 full,full 的配置类会生成代理对象
    // 2、其他的配置类为 lite
    Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
    // proxyBeanMethods 默认值为 true
    if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
        // CONFIGURATION_CLASS_FULL = full
        beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
    }
    // 注意,并不是说没有 @Configuration 注解,当前 BeanDefinition 就不是一个配置类
    // 还要注意 isConfigurationCandidate 方法,会检查是否存在
    // @Component, @ComponentScan,@Import,@ImportResource,@Bean注解
    // 只是配置类类型为 lite
    else if (config != null || isConfigurationCandidate(metadata)) {
        // CONFIGURATION_CLASS_LITE = lite
        beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
    }
    else {
        // 返回false,表示不是一个配置类
        return false;
    }

    // It's a full or lite configuration candidate... Let's determine the order value, if any.
    Integer order = getOrder(metadata);
    if (order != null) {
        beanDef.setAttribute(ORDER_ATTRIBUTE, order);
    }

    return true;
}
isConfigurationCandidate

检查是否存在@Component@ComponentScan@Import@ImportResource@Bean注解,如果有,当前BeanDefinition是一个配置类,类型为 lite

public static boolean isConfigurationCandidate(AnnotationMetadata metadata) {
    // Do not consider an interface or an annotation...
    // 不考虑接口上的注解
    if (metadata.isInterface()) {
        return false;
    }

    // Any of the typical annotations found?
    // candidateIndicators 是一个静态的 Set 集合
    // 集合中有四个值,分别为@Component,@ComponentScan,@Import,@ImportResource这四个注解
    for (String indicator : candidateIndicators) {
        if (metadata.isAnnotated(indicator)) {
            return true;
        }
    }

    // Finally, let's look for @Bean methods...
    // 查找有没有加了@Bean注解的方法
    try {
        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;
    }
}

private static final Set<String> candidateIndicators = new HashSet<>(8);

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

方法二:parse

该方法会对上面找到的配置类进行解析,也就是解析类上的注解。会将@ComponentScan扫描到的类,@Import导入的类,@Bean方法所在的类解析成ConfigurationClass类。

@Component@ComponentScan@Import@ImportResource@Bean

public void parse(Set<BeanDefinitionHolder> configCandidates) {
    // 遍历多个配置类的 BeanDefinition
    for (BeanDefinitionHolder holder : configCandidates) {
        BeanDefinition bd = holder.getBeanDefinition();
        try {
            // 根据BeanDefinition类型的不同,调用parse()不同的重载方法
            // 但是内部都是调用 processConfigurationClass 方法
            // 小杰这就分析 AnnotatedBeanDefinition 入口
            // 处理有注解的 BeanDefinition
            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);
        }
    }
	
    // 如果@Import 导入的类的类型为 DeferredImportSelector
    // 这句话才会生效,内部其实也是调用 processImports 方法。
    this.deferredImportSelectorHandler.process();
}

// 处理注解的信息
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
    // 构建一个 ConfigurationClass 对象,表示配置类信息,包括注解信息
    // 和 beanName,以及resource属性,表示配置类的类路径地址
    processConfigurationClass(new ConfigurationClass(metadata, beanName));
}

processConfigurationClass

processConfigurationClass 方法中调用 doProcessConfigurationClass方法,这才是核心处理逻辑方法。

protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {

    // 省略部分代码
    // sourceClass 将类简单的包装了一下,可以忽略
    SourceClass sourceClass = asSourceClass(configClass);
    do {
        //循环解析,核心逻辑
        sourceClass = doProcessConfigurationClass(configClass, sourceClass);
    }
    // 配置类可能存在父类,所以需要递归处理
    while (sourceClass != null);

    // 把当前配置类存在configurationClasses Map里面
    this.configurationClasses.put(configClass, configClass);
}

doProcessConfigurationClass

@Nullable
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
    throws IOException {

    // 1. 如果配置类上有@Component注解,则要获得类中的内部类,判断内部类上是否有 @Component、@ComponentScan、@Import、@ImportResource注解
    // 如果有调用 processConfigurationClass
    if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
        // Recursively process any member (nested) classes first
        processMemberClasses(configClass, sourceClass);
    }

    // Process any @PropertySource annotations
    // 2. 解析@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.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
                        "]. Reason: Environment must implement ConfigurableEnvironment");
        }
    }

    // Process any @ComponentScan annotations
    // 3. 解析@ComponentScan、ComponentScans 注解,获得类上注解的信息,比如:basePackages 的值
    // 并进行扫描
    Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
        sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
    if (!componentScans.isEmpty() &&
        !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
        for (AnnotationAttributes componentScan : componentScans) {

            // The config class is annotated with @ComponentScan -> perform the scan immediately
            // 扫描指定包路径及子包下的类,得到 BeanDefinitionHolder,BeanDefinitionHolder 中包含 BeanDefinition
            Set<BeanDefinitionHolder> scannedBeanDefinitions =
                this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());

            // Check the set of scanned definitions for any further config classes and parse recursively if needed
            for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
                BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
                if (bdCand == null) {
                    bdCand = holder.getBeanDefinition();
                }

                // 检查扫描所得到 BeanDefinition 是不是配置 Bean
                // 基本上都有 @Component 注解,所以都是配置类,继续需要进行解析
                if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
                    parse(bdCand.getBeanClassName(), holder.getBeanName());
                }
            }
        }
    }

    // Process any @Import annotations
    // 4. 解析@Import。
    // getImports方法返回 sourceClass 上定义的 Import注解中所导入的类的信息的集合
    processImports(configClass, sourceClass, getImports(sourceClass), true);

    // Process any @ImportResource annotations
    // 5. 解析@ImportResource,得到导入进来的spring的xml配置文件,然后解析
    AnnotationAttributes importResource =
        AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
    if (importResource != null) {
        //xml文件地址
        String[] resources = importResource.getStringArray("locations");
        //得到解析xml文件的解析器
        Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
        for (String resource : resources) {
            String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
// 添加到ConfigurationClass 类 importedResources Map 属性中,后续进行解析
            configClass.addImportedResource(resolvedResource, readerClass);
        }
    }

    // Process individual @Bean methods
    // 6. 解析配置类中的加了@Bean注解的方法
    Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
    for (MethodMetadata methodMetadata : beanMethods) {
        // 将找到的方法添加到 ConfigurationClass 类 beanMethods Set 属性中,后续进行解析
        configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
    }

    // Process default methods on interfaces
    // 7. 如果配置类实现了某个接口,那么则解析该接口中的加了@Bean注解的默认方法
    // 添加到 ConfigurationClass 类 beanMethods Set 属性中,后续进行解析
    processInterfaces(configClass, sourceClass);

    // Process superclass, if any
    // 8. 如果有父类,则返回父类给上层遍历进行处理
    if (sourceClass.getMetadata().hasSuperClass()) {
        String superclass = sourceClass.getMetadata().getSuperClassName();
        if (superclass != null && !superclass.startsWith("java") &&
            !this.knownSuperclasses.containsKey(superclass)) {
            this.knownSuperclasses.put(superclass, configClass);
            // Superclass found, return its annotation metadata and recurse
            return sourceClass.getSuperClass();
        }
    }

    // No superclass -> processing is complete
    return null;
}

方法逻辑挺长的,大体流程如下:

  • 1、配置类上有@Component注解,则要获得配置类中的内部类,判断内部类上是否有 @Component、@ComponentScan、@Import、@ImportResource注解,如果有则代表内部类也是配置类,则需要调用 processConfigurationClass方法。相当于递归。
  • 2、处理解析@PropertySource注解。
  • 3、解析@ComponentScan、ComponentScans注解,扫描指定包路径及子包下的类。由于扫描所得到 BeanDefinition有可能也是配置类,所以也需要递归处理解析。
  • 4、处理@Import注解。
  • 5、处理@ImportResource注解,解析 xml 文件。
  • 6、处理@Bean注解的方法
  • 如果配置类实现了某个接口,那么则解析该接口中的加了@Bean注解的默认方法
  • 8、如果有父类,则返回父类给上层遍历进行处理

简单的流程步骤这里就不再分析了。

流程一

核心逻辑在 this.componentScanParser.parse方法中。

public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {

// useDefaultFilters 值默认为 true,所以 includeFilters 中默认就注册了一个 @Component 注解对应的 Filter
// ClassPathBeanDefinitionScanner 这个对象在讲 Spring 启动流程中已经分析了
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);

// 设置BeanName生成器
Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);
scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator :
BeanUtils.instantiateClass(generatorClass));

ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy");
if (scopedProxyMode != ScopedProxyMode.DEFAULT) {
	scanner.setScopedProxyMode(scopedProxyMode);
}
else {
	Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");
	scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));
}

scanner.setResourcePattern(componentScan.getString("resourcePattern"));

// 得到 @ComponentScan 中 includeFilters 的值 ,并设置 IncludeFilter,
for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {
for (TypeFilter typeFilter : typeFiltersFor(filter)) {
	scanner.addIncludeFilter(typeFilter);
}
}

// 得到 @ComponentScan 中 excludeFilters 的值 ,并设置 ExcludeFilter
for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) {
for (TypeFilter typeFilter : typeFiltersFor(filter)) {
	scanner.addExcludeFilter(typeFilter);
}
}

// 设置懒加载
boolean lazyInit = componentScan.getBoolean("lazyInit");
if (lazyInit) {
	scanner.getBeanDefinitionDefaults().setLazyInit(true);
}

Set<String> basePackages = new LinkedHashSet<>();
String[] basePackagesArray = componentScan.getStringArray("basePackages");
for (String pkg : basePackagesArray) {
String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
Collections.addAll(basePackages, tokenized);
}
for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) {
	basePackages.add(ClassUtils.getPackageName(clazz));
}
if (basePackages.isEmpty()) {
	basePackages.add(ClassUtils.getPackageName(declaringClass));
}
// declaringClass 为传入的配置类全路径,例如:com.cxyxj.xx.AppApplication
// 默认的排除过滤
scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
    @Override
    protected boolean matchClassName(String className) {
    	return declaringClass.equals(className);
    }
});

// 开始扫描包路径,得到 BeanDefinitionHolder
return scanner.doScan(StringUtils.toStringArray(basePackages));
}

不出意外,还是包含一个 doScan方法。

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
    Assert.notEmpty(basePackages, "At least one base package must be specified");
    Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
    for (String basePackage : basePackages) {
        // 扫描包路径得到BeanDefinition,得到的BeanDefinition是空的,还没有解析类上所定义的注解信息
        Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
        for (BeanDefinition candidate : candidates) {
            // 得到Scope的信息,并设置
            ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
            candidate.setScope(scopeMetadata.getScopeName());
            // 得到beanName
            String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);

            if (candidate instanceof AbstractBeanDefinition) {
                postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
            }
            if (candidate instanceof AnnotatedBeanDefinition) {
                AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
            }
            if (checkCandidate(beanName, candidate)) {
                // 生成BeanDefinitionHolder并注册到registry中
                BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
				// 根据 @@Scope 属性 proxyMode 的值,确定是否需要产生代理对象
                definitionHolder =
                    AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
                beanDefinitions.add(definitionHolder);
                registerBeanDefinition(definitionHolder, this.registry);
            }
        }
    }
    return beanDefinitions;
}

// Scope注解中的ProxyMode属性有四个取值
// 1.DEFAULT:默认值,默认情况下取no
// 2.NO:不开启代理
// 3.INTERFACES:使用jdk动态代理
// 4.TARGET_CLASS:使用cglib代理
// 假如有一个单例beanA,其中有一个属性B,B的Scope是session,此时,容器在启动时创建A的过程中需要注入B属性,
// 但是B的scope是session,这种情况下是注入不了的,是会报错的
// 但是如果将B的Scope的ProxyMode属性配置为INTERFACES/TARGET_CLASS时,那么B就会生成一个ScopedProxyFactoryBean类型的BeanDefinitionHolder
// 在A注入B时,就会注入一个ScopedProxyFactoryBean类型的Bean
static BeanDefinitionHolder applyScopedProxyMode(
    ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {

    ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
    if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
        return definition;
    }

    // 是否使用cglib
    boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
    // 创建ScopedProxyFactoryBean类型的BeanDefinitionHolder
    return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
}
findCandidateComponents

findCandidateComponents的方法值为 Set<BeanDefinition>,可以得知,扫描就是在这个方法干的。

public Set<BeanDefinition> findCandidateComponents(String basePackage) {

    // Spring提供了一种支持更快速扫描的机制,就是编译时直接创建一个静态的,ASM技术
    if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
        return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
    }
    else {
        // 扫描@Component,扫描 basePackage 下的所有类,看是否有@Component注解
        return scanCandidateComponents(basePackage);
    }
}

对于 ASM 技术,有兴趣的伙伴可以去网上了解下。小杰不会。我们来看最笨的方法 scanCandidateComponents

private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
    // 扫描类,得到BeanDefinition
    Set<BeanDefinition> candidates = new LinkedHashSet<>();
    try {
        String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
            resolveBasePackage(basePackage) + '/' + this.resourcePattern;
        //路径下所有的类
        Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
        boolean traceEnabled = logger.isTraceEnabled();
        boolean debugEnabled = logger.isDebugEnabled();
        for (Resource resource : resources) {
            if (traceEnabled) {
                logger.trace("Scanning " + resource);
            }
            if (resource.isReadable()) {
                try {
                    // MetadataReader 包含了对应 class 的元信息以及注解元信息。
                    MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
                    // 判断一个类是不是Component
                    if (isCandidateComponent(metadataReader)) {
                        // 通过扫描@Component得到的BeanDefinition类型为ScannedGenericBeanDefinition
                        ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
                        sbd.setResource(resource);
                        sbd.setSource(resource);
                        // 再进一步验证
                        if (isCandidateComponent(sbd)) {
                            if (debugEnabled) {
                                logger.debug("Identified candidate component class: " + resource);
                            }
                            //将 sbd 添加到 Set 集合中
                            candidates.add(sbd);
                        }
       // 省略诸多 catch、else
    return candidates;
}
                    

protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
	//如果读取的类的注解在排除注解过滤规则中,返回false
	for (TypeFilter tf : this.excludeFilters) {
		if (tf.match(metadataReader, getMetadataReaderFactory())) {
			return false;
		}
	}
	//如果读取的类的注解在包含的注解的过滤规则中,则返回ture
	for (TypeFilter tf : this.includeFilters) {
		if (tf.match(metadataReader, getMetadataReaderFactory())) {
			return isConditionMatch(metadataReader);
		}
	}
	//如果读取的类的注解既不在排除规则,也不在包含规则中,则返回false
	return false;
}

 // 判断一个类是不是Component
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
		// 不匹配,扫描到的类在 excludeFilters 中,返回false,代表不是一个备选的Component
		for (TypeFilter tf : this.excludeFilters) {
			if (tf.match(metadataReader, getMetadataReaderFactory())) {
				return false;
			}
		}

		// 匹配,只有通过了 includeFilters 的验证才算是一个备选的Component
		for (TypeFilter tf : this.includeFilters) {
			if (tf.match(metadataReader, getMetadataReaderFactory())) {
				return isConditionMatch(metadataReader);
			}
		}
		return false;
	}       

excludeFiltersincludeFilters都是 @ComponentScan注解的属性,如果不熟悉,可以前往:@ComponentScan 注解详解

流程四

private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
			Collection<SourceClass> importCandidates, boolean checkForCircularImports) {

		if (importCandidates.isEmpty()) {
			return;
		}

		if (checkForCircularImports && isChainedImportOnStack(configClass)) {
			this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
		}
		else {
			this.importStack.push(configClass);
			try {
				// 以下会判断 @Import(UserService.class) 导入的类型
				for (SourceClass candidate : importCandidates) {
					// 如果导入的类实现了 ImportSelector 接口
					if (candidate.isAssignable(ImportSelector.class)) {
						// Candidate class is an ImportSelector -> delegate to it to determine imports
						Class<?> candidateClass = candidate.loadClass();
						// 得到 ImportSelector 对象
						ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
								this.environment, this.resourceLoader, this.registry);
						// DeferredImportSelector 是 ImportSelector 的子接口
						if (selector instanceof DeferredImportSelector) {
							this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
						}
						else {
							// 执行 selectImports 方法,得到 selectImports 方法的返回值(需要导入的类名)。
							String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
							//包装为 SourceClass
							Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
							// 将导入的类作为配置类,进行递归解析。可能可能还带有 @Import 或者其他注解,
							processImports(configClass, currentSourceClass, importSourceClasses, false);
						}
					}
					// 实现了 ImportBeanDefinitionRegistrar 接口
					else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
						// Candidate class is an ImportBeanDefinitionRegistrar ->
						// delegate to it to register additional bean definitions
						// 如果@Import注解中的类实现了ImportBeanDefinitionRegistrar接口
						// 就把该类的实例放入 ConfigurationClass类中属性 importBeanDefinitionRegistrars Map中,
						// 后面再执行该实例的 registerBeanDefinitions 方法
						Class<?> candidateClass = candidate.loadClass();
						ImportBeanDefinitionRegistrar registrar =
								ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
										this.environment, this.resourceLoader, this.registry);
						configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
					}
					else {
						// 如果导入的类就是一个普通的类,将其作为配置类进行解析
						// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
						// process it as an @Configuration class
						this.importStack.registerImport(
								currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
						// 调用 processConfigurationClass 方法
						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();
			}
		}
	}

如果配置类上存在@Import注解,那么需要判断导入类的类型:

  • 如果是 ImportSelector,那么调用执行 selectImports方法得到类名,然后在把这个类当做配置类进行解析**(递归)**
  • 如果是ImportBeanDefinitionRegistrar,那么则生成一个ImportBeanDefinitionRegistrar 实例对象,并添加到配置类对象中(ConfigurationClass)的 importBeanDefinitionRegistrars属性中。
  • 如果是普通类,做作为配置类进行处理。

流程 4(ImportBeanDefinitionRegistrar类型)、流程 5、流程6都没有真正的将之解析为 BeanDefinition,都是先存到 ConfigurationClass类的属性中。

流程七

流程 7,只是Spring 多了一种注册 Bean 的写法。写法如下:

public interface UService {

	@Bean
	default UserService u(){
		return new UserService();
	}

}

@Service
public class UServiceImpl implements UService{
}

UServiceImpl是一个配置类,且实现了 UService接口,接口中有一个默认的实现方法 u,该方法上添加了@Bean注解。经过第(7)步的解析,会添加到 ConfigurationClassbeanMethods 属性中,后续进行解析。

会向Spring容器中注册一个UserService类型的 Bean。

经过 processConfigurationClass方法的解析后,我们会得到许多个配置类,这些配置类存放在 ConfigurationClassParser类的configurationClasses属性中。存储结构如下:

Spring源码(十六)-ConfigurationClassPostProcessor

接下来就利用reader来进一步解析ConfigurationClass,因为还有一部分没有被生成 BeanDefinition

我们回到 processConfigBeanDefinitions方法中,找到 this.reader.loadBeanDefinitions(configClasses);代码。

方法三 loadBeanDefinitions

该方法就是将另外一部分生成BeanDefinition,被@Import@Bean@ImportedResource注解方式注册的类解析成BeanDefinition,然后注册到BeanDefinitionMap中。

public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
    TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
    for (ConfigurationClass configClass : configurationModel) {
        //循环调用
        loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
    }
}

private void loadBeanDefinitionsForConfigurationClass(
    ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {

  // 省略....

    // 当前配置类是不是通过 @Import 注解导入进来的,如果是则解析该类上面的注解
    // 比如 @Scope,@Lazy 这些注解信息,然后构建成 BeanDefinition
    // 并注册到 BeanDefinitionMap 中
    if (configClass.isImported()) {
        registerBeanDefinitionForImportedConfigurationClass(configClass);
    }
    //getBeanMethods:@Bean注解标注的方法,解析并注册到 BeanDefinitionMap 中
    for (BeanMethod beanMethod : configClass.getBeanMethods()) {
        loadBeanDefinitionsForBeanMethod(beanMethod);
    }

    // 从 @ImportedResource 导入进来的资源文件中加载BeanDefinition,并注册到 BeanDefinitionMap 中
    loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
    // 如果@Import注解中的类实现了ImportBeanDefinitionRegistrar接口
    // 调用 ImportBeanDefinitionRegistrar 对象的 registerBeanDefinitions 方法加载 BeanDefinition
    loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}

除了loadBeanDefinitionsForBeanMethod之外,其余方法就不再分析了,整体逻辑一目了然的。

@SuppressWarnings("deprecation")  // for RequiredAnnotationBeanPostProcessor.SKIP_REQUIRED_CHECK_ATTRIBUTE
	private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
		// @Bean标注方法的来源
		ConfigurationClass configClass = beanMethod.getConfigurationClass();
		MethodMetadata metadata = beanMethod.getMetadata();
		// 方法名称
		String methodName = metadata.getMethodName();

		// Do we need to mark the bean as skipped by its condition?
		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);
		Assert.state(bean != null, "No @Bean annotation attributes");

		// Consider name and any aliases
		//获得所有别名
		List<String> names = new ArrayList<>(Arrays.asList(bean.getStringArray("name")));
		//如果指定了别名,则第一个别名作为 beanName,负责使用 方法名称作为 beanName
		String beanName = (!names.isEmpty() ? names.remove(0) : methodName);

		// Register aliases even when overridden
		for (String alias : names) {
			// 注册别名
			this.registry.registerAlias(beanName, alias);
		}

		// Has this effectively been overridden before (e.g. via XML)?
		// 判断 beanName 是否已经被加载过了
		if (isOverriddenByExistingDefinition(beanMethod, beanName)) {
			if (beanName.equals(beanMethod.getConfigurationClass().getBeanName())) {
				throw new BeanDefinitionStoreException(beanMethod.getConfigurationClass().getResource().getDescription(),
						beanName, "Bean name derived from @Bean method '" + beanMethod.getMetadata().getMethodName() +
						"' clashes with bean name for containing configuration class; please make those names unique!");
			}
			return;
		}
		// 构建 BeanDefinition
		ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata);
		beanDef.setResource(configClass.getResource());
		beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));
		// 被@Bean标注的方法是静态,则使用静态工厂注入
		if (metadata.isStatic()) {
			// static @Bean method
			if (configClass.getMetadata() instanceof StandardAnnotationMetadata) {
				beanDef.setBeanClass(((StandardAnnotationMetadata) configClass.getMetadata()).getIntrospectedClass());
			}
			else {
				// 指定工厂类路径
				beanDef.setBeanClassName(configClass.getMetadata().getClassName());
			}
			// 指定工厂方法
			beanDef.setUniqueFactoryMethodName(methodName);
		}
		else {
			// 实例工厂注入
			// instance @Bean method
			// factory-bean 配置实例化工厂类的名称
			beanDef.setFactoryBeanName(configClass.getBeanName());
			// 指定工厂方法
			beanDef.setUniqueFactoryMethodName(methodName);
		}

		if (metadata instanceof StandardMethodMetadata) {
			beanDef.setResolvedFactoryMethod(((StandardMethodMetadata) metadata).getIntrospectedMethod());
		}

		beanDef.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
		beanDef.setAttribute(org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor.
				SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);

		AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);

		Autowire autowire = bean.getEnum("autowire");
		if (autowire.isAutowire()) {
			beanDef.setAutowireMode(autowire.value());
		}

		boolean autowireCandidate = bean.getBoolean("autowireCandidate");
		if (!autowireCandidate) {
			beanDef.setAutowireCandidate(false);
		}

		String initMethodName = bean.getString("initMethod");
		if (StringUtils.hasText(initMethodName)) {
			beanDef.setInitMethodName(initMethodName);
		}

		String destroyMethodName = bean.getString("destroyMethod");
		beanDef.setDestroyMethodName(destroyMethodName);

		// Consider scoping
		ScopedProxyMode proxyMode = ScopedProxyMode.NO;
		AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(metadata, Scope.class);
		if (attributes != null) {
			beanDef.setScope(attributes.getString("value"));
			proxyMode = attributes.getEnum("proxyMode");
			if (proxyMode == ScopedProxyMode.DEFAULT) {
				proxyMode = ScopedProxyMode.NO;
			}
		}

		// Replace the original bean definition with the target one, if necessary
		// 使用需要创建代理对象
		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.isTraceEnabled()) {
			logger.trace(String.format("Registering bean definition for @Bean method %s.%s()",
					configClass.getMetadata().getClassName(), beanName));
		}
		// 注册BeanDefinition
		this.registry.registerBeanDefinition(beanName, beanDefToRegister);
	}

看完上述逻辑,你会得到以下知识:

  • @Bean可以指定别名,第一个别名会作为beanName,如果没指定别名,会将方法名称作为别名。
  • @Bean 是通过factory-method实例化对象的。

具体使用请移步前往:XML文件的读取-factory-method的使用

上面几千字将 postProcessBeanDefinitionRegistry方法分析完啦!接下来看 postProcessBeanFactory

方法。

二、postProcessBeanFactory

通过前面的学习我们应该知道 postProcessBeanFactory是对BeanFactory进行处理的。那这个方法是怎么处理的呢,方法干了两件事:

  • 对被 @Configuration 标注的类,使用CGLIB代理生成代理对象。
  • beanPostProcessors 集合中添加一个 ImportAwareBeanPostProcessorBean的后置处理器。
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    int factoryId = System.identityHashCode(beanFactory);
    if (this.factoriesPostProcessed.contains(factoryId)) {
        throw new IllegalStateException(
            "postProcessBeanFactory already called on this post-processor against " + beanFactory);
    }
    this.factoriesPostProcessed.add(factoryId);
    // 是否需要进行解析
    // factoryId 在执行 postProcessBeanDefinitionRegistry 方法时,已经添加到了 registriesPostProcessed 集合中
    // 所以该判断永远不会成立
    if (!this.registriesPostProcessed.contains(factoryId)) {
        // BeanDefinitionRegistryPostProcessor hook apparently not supported...
        // Simply call processConfigurationClasses lazily at this point then.
        processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
    }

    // 对被 @Configuration 标注的类,使用CGLIB代理生成代理对象
    enhanceConfigurationClasses(beanFactory);
    // 向 beanPostProcessors 中添加一个 Bean的后置处理器
    beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}

enhanceConfigurationClasses

public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
    
    Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
    for (String beanName : beanFactory.getBeanDefinitionNames()) {
        BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
        // configClassAttr 的值有两种:full、lite
        Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE);
        // 省略代码 。。。

        // 被@Configuration标注的配置类就是 full
        if (ConfigurationClassUtils.CONFIGURATION_CLASS_FULL.equals(configClassAttr)) {
           // 省略代码 。。。
            configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
        }
    }

    // 加了@Configuration注解的配置类的BeanDefinition
    if (configBeanDefs.isEmpty()) {
        // nothing to enhance -> return immediately
        // 没有什么可增强的 -> 立即返回
        return;
    }

    // 生成被 @Configuration 标注类的代理对象
    ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
    for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
        AbstractBeanDefinition beanDef = entry.getValue();
        // If a @Configuration class gets proxied, always proxy the target class
        beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
        // Set enhanced subclass of the user-specified bean class
        Class<?> configClass = beanDef.getBeanClass();
        // 创建增强类
        Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
        if (configClass != enhancedClass) {
            if (logger.isTraceEnabled()) {
                logger.trace(String.format("Replacing bean definition '%s' existing class '%s' with " +
                                           "enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName()));
            }
            // 将增强类设置给 beanDefinition,后续基于 BeanDefinition 产生的bean就是增强类的对象了
            beanDef.setBeanClass(enhancedClass);
        }
    }
}
  • enhancer.enhance
public Class<?> enhance(Class<?> configClass, @Nullable ClassLoader classLoader) {
     // 省略一大串日志 。。。
    Class<?> enhancedClass = createClass(newEnhancer(configClass, classLoader));
    
    return enhancedClass;
}

上面的核心方法为newEnhancer,我们来看 newEnhancer方法。

  • newEnhancer
private Enhancer newEnhancer(Class<?> configSuperClass, @Nullable ClassLoader classLoader) {
    Enhancer enhancer = new Enhancer();
    // 对代理对象设置父类
    enhancer.setSuperclass(configSuperClass);
    // 对代理对象设置父接口
    // EnhancedConfiguration 继承了 BeanFactoryAware
    enhancer.setInterfaces(new Class<?>[] {EnhancedConfiguration.class});
    enhancer.setUseFactory(false);
    enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
    enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));
    // 添加了两个 MethodInterceptor ,BeanMethodInterceptor和BeanFactoryAwareMethodInterceptor
    // CGLIB 的增强就是执行 MethodInterceptor类 的 intercept 方法
    // BeanMethodInterceptor :对加了@Bean注解的方法进行增强
    // BeanFactoryAwareMethodInterceptor:对实现了 BeanFactoryAware 接口,调用 setBeanFactory() 方法
    enhancer.setCallbackFilter(CALLBACK_FILTER);
    enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
    return enhancer;
}

这方法创建了一个 Enhancer 实例。并设置了代理对象的父类、代理对象的父接口 EnhancedConfiguration,代理对象的增强逻辑 BeanMethodInterceptor和BeanFactoryAwareMethodInterceptor

addBeanPostProcessor

beanPostProcessors 中添加一个 Bean的后置处理器,类型为 ImportAwareBeanPostProcessor,在后续 Bean 的生命周期中会触发。我们一起看看 ImportAwareBeanPostProcessor的代码逻辑。

private static class ImportAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {

    private final BeanFactory beanFactory;

    public ImportAwareBeanPostProcessor(BeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }

    @Override
    public PropertyValues postProcessProperties(@Nullable PropertyValues pvs, Object bean, String beanName) {
        // Inject the BeanFactory before AutowiredAnnotationBeanPostProcessor's
        // postProcessProperties method attempts to autowire other configuration beans.
        if (bean instanceof EnhancedConfiguration) {
            ((EnhancedConfiguration) bean).setBeanFactory(this.beanFactory);
        }
        return pvs;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        if (bean instanceof ImportAware) {
            ImportRegistry ir = this.beanFactory.getBean(IMPORT_REGISTRY_BEAN_NAME, ImportRegistry.class);
            AnnotationMetadata importingClass = ir.getImportingClassFor(ClassUtils.getUserClass(bean).getName());
            if (importingClass != null) {
                ((ImportAware) bean).setImportMetadata(importingClass);
            }
        }
        return bean;
    }
}

ImportAwareBeanPostProcessor中就重写了两个方法,postProcessProperties方法与 postProcessBeforeInitialization方法。

  • postProcessProperties:如果当前 bean 实现了EnhanceConfiguration类,则为它设置 beanFactory属性赋值。如果忘记了 EnhanceConfiguration,看看 enhanceConfigurationClasses方法。

  • postProcessBeforeInitialization:处理 ImportAware回调。

为什么加了 @Configuration注解的类需要被代理呢?

不加 @Configuration注解

我们来看一个现象,准备如下代码,两个@Bean标注的方法 u()u2,在 u2中调用 u。会打印几次====== u?1次还是2次呢?

@ComponentScan(basePackages = {"com.cxyxj.conf"})
public class AppApplication {

   	@Bean
	UserService u(){

		UserService userService = new UserService();
		System.out.println("====== u == " + userService);
		return userService;
	}

    @Bean
    BeanTest u2(){
        u();
        System.out.println("====== u2");
        return new BeanTest();
}

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context =
            new AnnotationConfigApplicationContext(AppApplication.class);
        UserService bean = context.getBean(UserService.class);
		System.out.println("bean = " + bean);
    }
}

启动结果如下:

Spring源码(十六)-ConfigurationClassPostProcessor

结果是打印了两次。返回的对象并不一致,这个两个对象的作用域都是singleton, 这不就违背了Spring的单例原则吗?即一个bean在一个IoC容器中只有一个实例。

各位是否还记得 @Bean是如何创建 Bean 实例的吗?采用的是 factory-method方式进行实例化,而这种方式底层是通过反射

Spring源码(十六)-ConfigurationClassPostProcessor

源码位于 SimpleInstantiationStrategyinstantiate方法。

前往博文:Supplier、工厂方法实例化Bean

  • 通过反射执行 u()方法,将返回的的对象放入单例池中。
  • 通过反射执行 u2()方法,再调用 u(),这没办法从单例池获得UserService对象,只能重新创建UserService对象,并且这次创建的对象没办法放入单例池中。调用完 u(),将创建的 BeanTest对象放入单例池。

加 @Configuration注解

在类上加上 @Configuration注解,进行启动。结果如下:

Spring源码(十六)-ConfigurationClassPostProcessor

可以看出加上@Configuration注解之后,u()只被调用了一次。Spring 是怎么保证的呢?

各位还记得小杰在enhanceConfigurationClasses方法中提到,在由 CGLIB 产生代理对象的过程中,会构建一个 Enhancer实例,会给Enhancer实例的 filter属性添加了两个 MethodInterceptor ,分别是 BeanMethodInterceptor和BeanFactoryAwareMethodInterceptor。其中 BeanMethodInterceptor就是处理被 @Bean 注解的方法。

BeanMethodInterceptor实现了MethodInterceptor接口,会重写其 intercept,这也是 CGLIB 代理的核心方法,代码如下:

  • enhancedConfigInstance:CGLIB 创建的代理对象
  • beanMethod:代理类执行的方法,本例中的 u()u2()
  • beanMethodArgs:需要传给方法的参数
  • cglibMethodProxy:方法代理,不需要过于关心
@Override
@Nullable
public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
                        MethodProxy cglibMethodProxy) throws Throwable {

    // 得到bean工厂
    ConfigurableBeanFactory beanFactory = getBeanFactory(enhancedConfigInstance);
    // beanMethod对应的beanName
    String beanName = BeanAnnotationHelper.determineBeanNameFor(beanMethod);

    // Determine whether this bean is a scoped-proxy
    // 确定此 bean 是否是作用域代理
    if (BeanAnnotationHelper.isScopedProxy(beanMethod)) {
        String scopedBeanName = ScopedProxyCreator.getTargetBeanName(beanName);
        if (beanFactory.isCurrentlyInCreation(scopedBeanName)) {
            beanName = scopedBeanName;
        }
    }

    // To handle the case of an inter-bean method reference, we must explicitly check the
    // container for already cached instances.

    // First, check to see if the requested bean is a FactoryBean. If so, create a subclass
    // proxy that intercepts calls to getObject() and returns any cached bean instance.
    // This ensures that the semantics of calling a FactoryBean from within @Bean methods
    // is the same as that of referring to a FactoryBean within XML. See SPR-6602.
    // 如果beanFactory中存在beanName并且也存在&+beanName所对应的bean,那么这个bean是一个FactoryBean
    if (factoryContainsBean(beanFactory, BeanFactory.FACTORY_BEAN_PREFIX + beanName) &&
        factoryContainsBean(beanFactory, beanName)) {
        // FactoryBean对象
        Object factoryBean = beanFactory.getBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName);
        if (factoryBean instanceof ScopedProxyFactoryBean) {
            // Scoped proxy factory beans are a special case and should not be further proxied
        }
        else {
            // It is a candidate FactoryBean - go ahead with enhancement
            // 对FactoryBean对象进行增强,当userService()中调用userFactoryBean()时,返回的是UserFactoryBean的代理对象
            // 因为不能返回getObject方法的bean,也不能直接方法上面的factoryBean对象,因为如果返回的是factoryBean对象
            // 如果后面调用getObject方法就会产生问题,而产生一个代理对象就可以对getObject方法进行代理,保证getObject方法返回的是同一个bean
            return enhanceFactoryBean(factoryBean, beanMethod.getReturnType(), beanFactory, beanName);
        }
    }

    // 比如当前正在进行实例化的是u2()方法所对应的bean,而在u2()方法中会调用u()方法
   // 这个时候下面这个判断等于false,而等于false,就不会真正去执行u()方法了,就会直接去beanFactory中去获取bean
    if (isCurrentlyInvokedFactoryMethod(beanMethod)) {
        // The factory is calling the bean method in order to instantiate and register the bean
        // (i.e. via a getBean() call) -> invoke the super implementation of the method to actually
        // create the bean instance.
        if (logger.isInfoEnabled() &&
            BeanFactoryPostProcessor.class.isAssignableFrom(beanMethod.getReturnType())) {
            logger.info(String.format("@Bean method %s.%s is non-static and returns an object " +
                                      "assignable to Spring's BeanFactoryPostProcessor interface. This will " +
                                      "result in a failure to process annotations such as @Autowired, " +
                                      "@Resource and @PostConstruct within the method's declaring " +
                                      "@Configuration class. Add the 'static' modifier to this method to avoid " +
                                      "these container lifecycle issues; see @Bean javadoc for complete details.",
                                      beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName()));
        }
        // 真正执行 @Bean 注解标注的方法
        return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
    }
    // 直接去beanFactory中去获取bean
    return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
}

在执行 factoryMethod.invoke(factoryBean, args)时,就会进入到上述逻辑中。 好了,这就是本文的全部内容。


  • 如你对本文有疑问或本文有错误之处,欢迎评论留言指出。如觉得本文对你有所帮助,欢迎点赞和关注。