Spring源码解析-ConfigurationClassPostProcessor

591 阅读8分钟

前言

@Configuration @Component @Bean @Import等注解,相信大家在使用spring的时候会经常使用到,这些注解在spring中是如何处理的,不知道大家会不会很好奇,今天我们来探索spring注解的秘密 --- ConfigurationClassPostProcessor

类图

image.png

查看ConfigurationClassPostProcessor的类图,可以清楚地看到它分别实现了 BeanDefinitionRegistryPostProcessor PriorityOrdered,如果有看过本人的上一篇文章,就可以知道这个类的执行时机,下面是这个类执行的代码,委托给 PostProcessorRegistrationDelegate执行,

String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
  // 如果该类既实现了PriorityOrdered,又实现了BeanDefinitionRegistryPostProcessor,放到暂存list中
  if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
    processedBeans.add(ppName);
  }
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// 在这里执行
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// 执行代码也非常简单,就是一个for循环
private static void invokeBeanDefinitionRegistryPostProcessors(
			Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {

    for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
            postProcessor.postProcessBeanDefinitionRegistry(registry);
    }
}

注册时机

那么问题来了, ConfigurationClassPostProcessor是在什么时候注册到IOC容器中的?

// AnnotationConfigApplicationContext构造器中会初始化AnnotatedBeanDefinitionReader
public AnnotationConfigApplicationContext(DefaultListableBeanFactory beanFactory) {
   super(beanFactory);
   this.reader = new AnnotatedBeanDefinitionReader(this);
   this.scanner = new ClassPathBeanDefinitionScanner(this);
}
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    Assert.notNull(environment, "Environment must not be null");
    this.registry = registry;
    this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
    // AnnotatedBeanDefinitionReader中会提前注册支持注解的组件
    AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
			BeanDefinitionRegistry registry, @Nullable Object source) {
        // 获取DefaultListableBeanFactory,这个方法只是一个类型转换
        DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
        if (beanFactory != null) {
                if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
                        beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
                }
                if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
                        beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
                }
        }

        Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
        // 在这里注册ConfigurationClassPostProcessor
        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));
        }
        // 注册AutowiredAnnotationBeanPostProcessor,处理@Autowired,bean的属性注入的时候会用到
        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));
        }

        // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
        // 注册CommonAnnotationBeanPostProcessor,处理一些公共注解,比如@Resource、@PostConstruct、@PreDestroy
        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的处理,首先会判断有没有引入jpa相关的jar包,再注册这个类
        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));
        }
        // 注册EventListenerMethodProcessor,处理@EventListener
        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));
        }

        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;
}

源码解析

postProcessBeanDefinitionRegistry

ConfigurationClassPostProcessor实现了 BeanDefinitionRegistryPostProcessor接口,那么我们可以很简单地找到执行的入口:

postProcessBeanDefinitionRegistry

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);
        // 上面都是一些校验,直接看核心代码
        processConfigBeanDefinitions(registry);
}

看下面的源码之前,我们先了解一下配置类 full模式 lite模式的区别:full模式配置类会被cglib代理,lite模式配置类不会被cglib代理,所以full模式下@Bean方法不能被声明为private和final(cglib是通过生成子类来实现代理的)

我们通过一个测试看一下两者的差别

@Configuration // 通过@Configuration来区别是full配置类 or lite配置类
public class FullConfig {

    @Bean
    public String test() {
        System.out.println(user().hashCode());
        System.out.println(user().hashCode());
        return "test";
    }

    @Bean
    public User user() {
        return new User();
    }
}
@Component
public class LiteConfig {
    @Bean
    public String test() {
        System.out.println(user().hashCode());
        System.out.println(user().hashCode());
        return "test";
    }

    @Bean
    public User user() {
        return new User();
    }
}
public class Test {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(LiteConfig.class);
        context.getBean(User.class);
        context.close();
    }
}

lite模式下的打印信息

image.png

full模式下的打印信息

image.png

总结:lite模式下,多次调用user()会生成多个对象,full模式不会

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
    // 用来保存full配置类
    List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
    // 拿到当前registry中所有已经注册到beanDefinition的名称
    String[] candidateNames = registry.getBeanDefinitionNames();

    
    for (String beanName : candidateNames) {
                BeanDefinition beanDef = registry.getBeanDefinition(beanName);
                // org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass
                // BeanDefinition中这个值不为空,说明之前已经设置过了
                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设置属性为lite或者full
                // 在这为BeanDefinition设置lite和full属性值是为了后面再使用
                // 这个方法的详细解释见下文
                else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
                        configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
                }
        }

        // 没有发现待处理的配置类(@Configuration),直接返回
        if (configCandidates.isEmpty()) {
                return;
        }

        // 按照@Order值进行排序
        configCandidates.sort((bd1, bd2) -> {
                int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
                int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
                return Integer.compare(i1, i2);
        });


        SingletonBeanRegistry sbr = null;
        if (registry instanceof SingletonBeanRegistry) {
                sbr = (SingletonBeanRegistry) registry;
                // 判断是否有设置命名策略
                if (!this.localBeanNameGeneratorSet) {
                        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
        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...while循环,所有配置类解析完毕后会退出循环
        do {
        // 委托给ConfigurationClassParser来解析这些配置类
                parser.parse(candidates);
                // 校验扫描出来的beanDefinition是否合法,这里主要是校验
                // 1.proxyBeanMethods = true的情况下配置类是否可以重写(非final,需要生成cglib代理类)
                // 2.@Bean修饰的方法是否可以重写(非final,需要生成cglib代理类)
                parser.validate();

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

                // 初始化一个ConfigurationClassBeanDefinitionReader
                if (this.reader == null) {
                        this.reader = new ConfigurationClassBeanDefinitionReader(
                                        registry, this.sourceExtractor, this.resourceLoader, this.environment,
                                        this.importBeanNameGenerator, parser.getImportRegistry());
                }
                // 把封装好的ConfigurationClass对象委托给BeanDefinitionReader处理
                // 将ConfigurationClass解析为BeanDefinition
                this.reader.loadBeanDefinitions(configClasses);
                alreadyParsed.addAll(configClasses);

                candidates.clear();
                if (registry.getBeanDefinitionCount() > candidateNames.length) {
                        String[] newCandidateNames = registry.getBeanDefinitionNames();
                        Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
                        Set<String> alreadyParsedClasses = new HashSet<>();
                        for (ConfigurationClass configurationClass : alreadyParsed) {
                                alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
                        }
                        for (String candidateName : newCandidateNames) {
                                if (!oldCandidateNames.contains(candidateName)) {
                                        BeanDefinition bd = registry.getBeanDefinition(candidateName);
                                        // 这里会对解析好的BeanDefinition再次校验是full配置类还是lite配置类
                                        // 比如某个类Import了一个配置类
                                        if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
                                                        !alreadyParsedClasses.contains(bd.getBeanClassName())) {
                                                candidates.add(new BeanDefinitionHolder(bd, candidateName));
                                        }
                                }
                        }
                        candidateNames = newCandidateNames;
                }
        }
        while (!candidates.isEmpty());

        // Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
        if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
                sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
        }

        if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
                // Clear cache in externally provided MetadataReaderFactory; this is a no-op
                // for a shared cache since it'll be cleared by the ApplicationContext.
                ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
        }
}
判断全配置类or半配置类
public static boolean checkConfigurationClassCandidate(
			BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {

  	String className = beanDef.getBeanClassName();
        if (className == null || beanDef.getFactoryMethodName() != null) {
                return false;
        }

        AnnotationMetadata metadata;
        // 不是spring预先注册的类,会走这个if
        if (beanDef instanceof AnnotatedBeanDefinition &&
                        className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {
                // Can reuse the pre-parsed metadata from the given BeanDefinition...
                metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata();
        }
        // 此处return false,过滤了spring预先注册的几个类
        else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {
                Class<?> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass();
                if (BeanFactoryPostProcessor.class.isAssignableFrom(beanClass) ||
                                BeanPostProcessor.class.isAssignableFrom(beanClass) ||
                                AopInfrastructureBean.class.isAssignableFrom(beanClass) ||
                                EventListenerFactory.class.isAssignableFrom(beanClass)) {
                        return false;
                }
                metadata = AnnotationMetadata.introspect(beanClass);
        }
        else {
                try {
                        // asm技术获取该类的信息
                        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;
                }
        }

        Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
        // 这里有两个判断
        // 1.当前类中含有@Configuration注解
        // 2.注解中proxyBeanMethods属性为true
        // 则将其设置为full配置类
        if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
                beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
        }
        // 因为含有@Configuration注解并且proxyBeanMethods属性为true的类走上面的判断
        // 走这个逻辑的有两种类
        // 1.含有@Configuration注解并且proxyBeanMethods属性为false
        // 2.含有@Bean,@Component,@ComponentScan,@Import,@ImportResource注解
        // 以上两种类设置为lite配置类
        else if (config != null || isConfigurationCandidate(metadata)) {
                beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
        }
        else {
                return false;
        }

        // lite或者full配置类设置order优先级
        Integer order = getOrder(metadata);
        if (order != null) {
                beanDef.setAttribute(ORDER_ATTRIBUTE, order);
        }

        return true;
}
// candidateIndicators静态常量初始化时包含了四个元素
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());
	}



public static boolean isConfigurationCandidate(AnnotationMetadata metadata) {
        // 该类是接口直接返回false
        if (metadata.isInterface()) {
                return false;
        }

        // candidateIndicators是一个静态常量,在初始化时,包含了四个元素
        // 分别是@Bean,@Component,@ComponentScan,@Import,@ImportResource
        // 只要这个类上添加了这四种注解中的一个,这个类便是一个配置类
        // 这个类对应的BeanDefinition中的configurationClass属性值是lite
        for (String indicator : candidateIndicators) {
                if (metadata.isAnnotated(indicator)) {
                        return true;
                }
        }

        // 查找有没有加了@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;
        }
}
ConfigurationClass

一个配置类中有什么注解,如何进行描述呢?Spring使用了ConfigurationClass用来抽象一个配置类

final class ConfigurationClass {
	// 配置类的注解信息
	private final AnnotationMetadata metadata;

	private final Resource resource;

	@Nullable
	private String beanName;
	// 当前类是由哪个配置类导入的
	private final Set<ConfigurationClass> importedBy = new LinkedHashSet<>(1);
	// 当前配置类所有的含@Bean注解的方法
	private final Set<BeanMethod> beanMethods = new LinkedHashSet<>();
	// @ImportResource相关的信息,这个不理会
	private final Map<String, Class<? extends BeanDefinitionReader>> importedResources =
			new LinkedHashMap<>();
	// 配置类上的@Import注解导入的类,如果是实现了@ImportBeanDefinitionRegister接口,将会封装到这里
	private final Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> importBeanDefinitionRegistrars =
			new LinkedHashMap<>();

	final Set<String> skippedBeanMethods = new HashSet<>();
}
protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
        if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
                return;
        }
        // 该配置类是否以及解析过,比如当前类以及被别的类import过
        ConfigurationClass existingClass = this.configurationClasses.get(configClass);
        if (existingClass != null) {
                if (configClass.isImported()) {
                        if (existingClass.isImported()) {
                              // 某个配置类被多个类import
                                existingClass.mergeImportedBy(configClass);
                        }
                        // Otherwise ignore new imported config class; existing non-imported class overrides it.
                        return;
                }
                else {
                        // Explicit bean definition found, probably replacing an import.
                        // Let's remove the old one and go with the new one.
                        this.configurationClasses.remove(configClass);
                        this.knownSuperclasses.values().removeIf(configClass::equals);
                }
        }

        // sourceClass:对配置类的元数据的封装,比如这个配置类有什么注解,有什么方法
        // 此处的configClass只是一个实例化好的对象,只是一个空壳,doProcessConfigurationClass对配置类进行解析,并且填充 
        // configClass
        SourceClass sourceClass = asSourceClass(configClass, filter);
        // 这里的do...while循环是为了处理某个类有父类的情况,有父类的情况下会继续解析父类
        do {
                sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
        }
        while (sourceClass != null);

        // 将处理好的类放进 configurationClasses 中
        this.configurationClasses.put(configClass, configClass);
}
@Nullable
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
			throws IOException {

            if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
                    // 如果配置类被@Component修饰,先处理内部类
                    processMemberClasses(configClass, sourceClass);
            }

            // 处理@PropertySource和@PropertySources注解
            // 会将文件转换成一个PropertySource对象,然后存到environment对象当中
            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");
                    }
            }

            // 处理@ComponentScan和@ComponentScans注解
            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) {
                            // 处理扫描,对于类的配置暂时不进行处理
                            Set<BeanDefinitionHolder> scannedBeanDefinitions =
                                            this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
                            // 
                            for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
                                    BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
                                    if (bdCand == null) {
                                            bdCand = holder.getBeanDefinition();
                                    }
                                    if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
                                            // 遍历所有扫描出来的类
                                            parse(bdCand.getBeanClassName(), holder.getBeanName());
                                    }
                            }
                    }
            }

            // 处理@Import注解
            processImports(configClass, sourceClass, getImports(sourceClass), true);

            // 处理@ImportResource注解
            AnnotationAttributes importResource =
                            AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
            if (importResource != null) {
                    String[] resources = importResource.getStringArray("locations");
                    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));
            }

            // 因为java8支持接口中定义默认方法,此处处理接口的默认方法
            processInterfaces(configClass, sourceClass);

            // 如果该类有父类,返回父类,外层是一个do...while循环,会再跑一遍这个方法
            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();
                    }
            }

            // 如果没有父类,返回空,此类处理完毕
            return null;
 }

以上是ConfigurationClassPostProcessor大致执行流程,但是每个注解处理的细节,各位看官应该还是半知半解,下面接着说

@Component

先看一段代码来感受一下这个注解的使用场景

@Component
public class ComponentConfig {
    // 一个内部类
    class InnerClass {
        @Bean
        public User user() {
            System.out.println("component test");
            return new User();
        }
    }
}
private void processMemberClasses(ConfigurationClass configClass, SourceClass sourceClass,
			Predicate<String> filter) throws IOException {
        // 获取所有的内部类
        Collection<SourceClass> memberClasses = sourceClass.getMemberClasses();
        // 如果含内部类
        if (!memberClasses.isEmpty()) {
                List<SourceClass> candidates = new ArrayList<>(memberClasses.size());
                // 循环解析内部类
                for (SourceClass memberClass : memberClasses) {
                        // 这里有两个判断
                        // 1.内部类是否是一个配置类
                        // 2.内部类的名字与当前类不一致(这个判断有点诡异)
                        // 则加入待处理的配置类列表中
                        if (ConfigurationClassUtils.isConfigurationCandidate(memberClass.getMetadata()) &&
                                        !memberClass.getMetadata().getClassName().equals(configClass.getMetadata().getClassName())) {
                                candidates.add(memberClass);
                        }
                }
                // 待配置类进行排序
                OrderComparator.sort(candidates);
                for (SourceClass candidate : candidates) {
                        // 判断是否有出现循环import的情况
                        if (this.importStack.contains(configClass)) {
                                this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
                        }
                        else {
                                this.importStack.push(configClass);
                                try {
                                        // 处理内部类,这里是一个递归,再次走一遍解析的流程(详细可见上文)
                                        processConfigurationClass(candidate.asConfigClass(configClass), filter);
                                }
                                finally {
                                        this.importStack.pop();
                                }
                        }
                }
        }
}
@ComponentScan

先看一段代码来感受一下这个注解的使用场景

@ComponentScan(value = "com.example")
public class ComponentScanConfig {
}
public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
        // 创建一个扫描器
        ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
                                componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);

                Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
        // @ComponentScan注解可以配置命名策略(nameGenerator)
        // 默认情况下为true,如果为false,命名策略用的是你在配置类上配置的
        // BeanUtils.instantiateClass 此处会对命令策略的类进行初始化
        boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);
                scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator :
                                BeanUtils.instantiateClass(generatorClass));

        ····

        ····  
        return scanner.doScan(StringUtils.toStringArray(basePackages));
}
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) {
                // 进行扫描,找出想要加载的类
                Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
                for (BeanDefinition candidate : candidates) {
                        ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
                        candidate.setScope(scopeMetadata.getScopeName());
                        String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
                        if (candidate instanceof AbstractBeanDefinition) {
                                postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
                        }
                        // 使用了注解的类会走这个if
                        if (candidate instanceof AnnotatedBeanDefinition) {
                                // 处理一些常用的注解,比如@Lazy、@Primary,代码比较简单,一看便知
                                AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
                        }
                        // 判断该beanDefinition是否已注册,如果已注册,就不再重复注册
                        if (checkCandidate(beanName, candidate)) {
                                BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
                                definitionHolder =
                                                AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
                                beanDefinitions.add(definitionHolder);
                                // 注册beanDefinition
                                registerBeanDefinition(definitionHolder, this.registry);
                        }
                }
        }
        return beanDefinitions;
}
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
		Set<BeanDefinition> candidates = new LinkedHashSet<>();
        try {
              // 将包名转换为一个路径
              // 这里的路径是指编译为字节码之后的路径
              // 举个例子:com.example --> classpath*:com/example/**/*.class
                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 {
                                        // 使用asm技术解析类,MetadataReader描述了类的信息
                                        // 为什么这里要使用asm技术来解析类,不用Class.forName反射的方式?
                                        // 因为使用asm是一种无侵入式的方式,如果使用反射技术,需要先将class文件加载进JVM中,这样子的话,
                                        // class的某些初始化代码(static)就会被执行,这不是一个框架应该做的事情
                                        MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
                                        // 剔除某些不需要加载的类,比如excludeFilters,@condition注解
                                        if (isCandidateComponent(metadataReader)) {
                                                ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
                                                sbd.setSource(resource);
                                                if (isCandidateComponent(sbd)) {
                                                        if (debugEnabled) {
                                                                logger.debug("Identified candidate component class: " + resource);
                                                        }
                                                        candidates.add(sbd);
                                                }
                                                else {
                                                        if (debugEnabled) {
                                                                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) {
                throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
        }
        return candidates;
}
@Import

先看一段代码来感受一下这个注解的使用场景

public class ImportSelectorConfig implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        String[] str = {"com.example.springdemo.bean.User"};
        System.out.println("ImportSelectorConfig");
        return str;
    }
}
public class ImportBeanDefinitionRegistrarConfig implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        System.out.println("ImportBeanDefinitionRegistrarConfig");
        ImportBeanDefinitionRegistrar.super.registerBeanDefinitions(importingClassMetadata, registry);
    }
}
@Data
@Builder
public class Staff {

    public Staff() {
        System.out.println("staff");
    }
}
@Configuration
@Import({Staff.class, ImportSelectorConfig.class, ImportBeanDefinitionRegistrarConfig.class})
public class Config {

}

image.png

总结:import注解可以import三种类型的类

  • ImportSelector类型
  • ImportBeanDefinitionRegistrar类型
  • 普通类
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
			Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
			boolean checkForCircularImports) {
		// import注解没有import任何类
		if (importCandidates.isEmpty()) {
			return;
		}
		// 检查是否有循环import的情况
		if (checkForCircularImports && isChainedImportOnStack(configClass)) {
			this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
		}
		else {
			this.importStack.push(configClass);
			try {
                        // 这里会对import类做处理,import类有三种类型
                        // 1.ImportSelector类型
                        // 2.ImportBeanDefinitionRegistrar类型
                        // 3.普通类
                        for (SourceClass candidate : importCandidates) {
                                if (candidate.isAssignable(ImportSelector.class)) {
                                        // Candidate class is an ImportSelector -> delegate to it to determine imports
                                        Class<?> candidateClass = candidate.loadClass();
                                        ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
                                                        this.environment, this.resourceLoader, this.registry);
                                        Predicate<String> selectorFilter = selector.getExclusionFilter();
                                        if (selectorFilter != null) {
                                                exclusionFilter = exclusionFilter.or(selectorFilter);
                                        }
                                        if (selector instanceof DeferredImportSelector) {
                                                this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
                                        }
                                        else {
                                                String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
                                                Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
                                               // 这里会做一个processImports的递归,为什么只有当import的类是ImportSelector才会做这个递归,
                                               // ImportBeanDefinitionRegistrar和普通类都不会?
                                               // 因为ImportSelector可能会导入多个类,这些类中可能有ImportSelector、ImportBeanDefinitionRegistrar
                                               // 或者普通类,需要再次做处理
                                               // ImportSelector这个类本身对于spring是没有意义的,它的作用在于导入类
                                              processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
                                        }
                                }
                                else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
                                        // import的类是ImportBeanDefinitionRegistrar类型
                                        // 会暂存在ConfigurationClass中,后面做处理
                                        Class<?> candidateClass = candidate.loadClass();
                                        ImportBeanDefinitionRegistrar registrar =
                                                        ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
                                                                        this.environment, this.resourceLoader, this.registry);
                                        configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
                                }
                                else {
                                        // import导入的类既不是ImportBeanDefinitionRegistrar、也不是ImportSelector
                                        // 当成一个配置类来处理,再走一个配置类的处理流程
                                        this.importStack.registerImport(
                                                        currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
                                        processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
                                }
                        }
                }
                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();
                }
        }
}
loadBeanDefinitions
private void loadBeanDefinitionsForConfigurationClass(
			ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {

		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;
		}
		// 如果该类是通过@Import或者ImportSelector的方式添加到容器中的,会走这个if
		if (configClass.isImported()) {
			registerBeanDefinitionForImportedConfigurationClass(configClass);
		}
                // 如果该类中含有@Bean方法,走这个if
		for (BeanMethod beanMethod : configClass.getBeanMethods()) {
			loadBeanDefinitionsForBeanMethod(beanMethod);
		}
		// 处理@ImportResource注解,这部分代码不看了
		loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
                // 如果该类中存在@Import注解,且Import的类实现了ImportBeanDefinitionRegistrar
		loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
@Bean

先看一段代码来感受一下这个注解的使用场景

@Configuration
public class BeanConfig {
    @Bean
    public User user() {
        System.out.println("user");
        return new User();
    }

    @Bean
    public static Staff staff() {
        System.out.println("staff");
        return new Staff();
    }
}

这两个@bean,一个加了static,一个没有加,主要的差别要在初始化的时候才能够体现,后面会写bean的生命周期相关的文章

private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
		·····

    ·····  
                // 如果是静态的@Bean方法,设置beanClass,bean的初始化时会调用到
		if (metadata.isStatic()) {
			// static @Bean method
			if (configClass.getMetadata() instanceof StandardAnnotationMetadata) {
				beanDef.setBeanClass(((StandardAnnotationMetadata) configClass.getMetadata()).getIntrospectedClass());
			}
			else {
				beanDef.setBeanClassName(configClass.getMetadata().getClassName());
			}
                        // 设置FactoryMethodName
			beanDef.setUniqueFactoryMethodName(methodName);
		}
		else {
			// 如果是非静态的@Bean方法,设置factoryBeanName,bean的初始化时会调用到
			beanDef.setFactoryBeanName(configClass.getBeanName());
                        // 设置FactoryMethodName
			beanDef.setUniqueFactoryMethodName(methodName);
		}

		·····

    ····· 
                // 注册beanDefinition
		this.registry.registerBeanDefinition(beanName, beanDefToRegister);
}

总结

这篇文章看起来会很枯燥,本来我想用画图的方式来帮助理解的,但是整个方法有大量的递归,不好画图,只能这样了