上文提到Spring在Bean扫描过程中,会手动将5个Processor类注册到beanDefinitionMap中,其中ConfigurationClassPostProcessor就是本文将要讲解的内容,该类会在refresh()方法中通过调用invokeBeanFactoryPosstProcessors(beanFactory)被调用。
5个Processor类列表如下:
类名 | 是否BeanDefinitionRegistryPostProcessor | 是否BeanFactoryPostProcessor | 是否BeanPostProcessor |
ConfigurationClassPostProcessor | 是 | 是 | 是 |
AutowiredAnnotationBeanPostProcessor | 否 | 否 | 是 |
CommonAnnotationBeanPostProcessor | 否 | 否 | 是 |
EventListenerMethodProcessor | 否 | 是 | 否 |
DefaultEventListenerFactory | 否 | 否 | 否 |
ConfigurationClassPostProcessor中两个核心方法将被调用,其主要作用如下:
方法名 | 作用 |
postProcessBeanDefinitionRegistry() | (1)@Conditional注解条件解析 (2)被以下注解标注的类及内部类 @Component、@PropertySources、@PropertySource、@ComponentScans、@ComponentScan、@Import、@ImportResource、@Bean、接口中的@Bean |
postProcessBeanFactory() | 对full模式的配置类BeanDefinition进行CGLib增强:把CGLib生成的子类型设置到beanDefinition中 |
postProcessBeanDefinitionRegistry()源码及注释如下:
@Overridepublic 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);}
进入processConfigBeanDefinitions(registry)方法,其主体逻辑流程图如下:
其中标红步骤为两个关键步骤:
1. 通过beanDefinition判断是否为配置类
Spring专门提供了一个工具类:ConfigurationClassUtils来检查是否为配置类,并标记full、lite模式,逻辑如下:
2. 解析配置类
doProcessConfigurationClass即为真正的对个注解的解析方法,其逻辑流程图如下:
具体的源码及详细注释如下:
1. 主流程processConfigBeanDefinitions方法:
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {// 候选配置类定义列表List<BeanDefinitionHolder> configCandidates = new ArrayList<>();// 获取容器中所有bean定义的名字String[] candidateNames = registry.getBeanDefinitionNames();for (String beanName : candidateNames) {// 获取bean定义BeanDefinition beanDef = registry.getBeanDefinition(beanName);// org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass// Bean Definition是否已经被标记为配置类(full、lite模式)if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {if (logger.isDebugEnabled()) {logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);}}// 查看bean是否是ConfigurationClass//被@Configuration、@Component、@ComponentScan、@Import、@ImportResource、@Bean标记else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {// 是配置类,则加入到候选列表configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));}}// Return immediately if no @Configuration classes were found// 如果为空,即找不到被@Configuration、@Component、@ComponentScan、@Import、@ImportResource、@Bean标记的类,则立即返回if (configCandidates.isEmpty()) {return;}// Sort by previously determined @Order value, if applicable// 对需要处理的BeanDefinition排序,值越小越靠前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// 检查是否有自定义的beanName生成器SingletonBeanRegistry sbr = null;if (registry instanceof SingletonBeanRegistry) {sbr = (SingletonBeanRegistry) registry;if (!this.localBeanNameGeneratorSet) {//获取自定义的beanName生成器BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);if (generator != null) {// 如果spring有自定义的beanName生成器,则重新赋值this.componentScanBeanNameGenerator = generator;this.importBeanNameGenerator = generator;}}}//如果环境对象为空,则创建新的环境对象if (this.environment == null) {this.environment = new StandardEnvironment();}// 构造一个配置类解析器,用来把bean定义的重要信息提取转化为ConfigurationClass// Parse each @Configuration classConfigurationClassParser 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 {// 解析配置类parser.parse(candidates);// 配置类不能被申明为final(因为CGLIB的限制),除非它声明proxyBeanMethods=false// 在@Configuration类中,@Bean方法的实例必须是可重写的,以适应CGLIBparser.validate();// 获取解析器中解析出的配置类ConfigurationClass: parser.getConfigurationClasses()Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());// 过滤掉已解析的配置类configClasses.removeAll(alreadyParsed);// 构造一个bean定义读取器// Read the model and create bean definitions based on its contentif (this.reader == null) {this.reader = new ConfigurationClassBeanDefinitionReader(registry, this.sourceExtractor, this.resourceLoader, this.environment,this.importBeanNameGenerator, parser.getImportRegistry());}// 读取ConfigurationClass获取衍生bean定义并注册到容器// 核心方法,将完全填充好的ConfigurationClass实例转化为BeanDefinition注册入IOC容器this.reader.loadBeanDefinitions(configClasses);// 加入已解析配置类alreadyParsed.addAll(configClasses);// 清空候选配置类定义列表candidates.clear();// 如果容器中bean定义有新增if (registry.getBeanDefinitionCount() > candidateNames.length) {// 查找出新增的配置类bean定义 startString[] 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);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// 如果想要在@Configuration类中使用ImportAware接口,需要将ImportRegistry注册为bean。这样,@Configuration类就可以// 使用ImportRegistry来获取导入的类信息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.// 如果MetadataReaderFactory是由外部提供的,则需要清楚其缓存。但是,如果MetadataReaderFactory是由ApplicationContext共享的,则不需要进行清除,// 因为ApplicationContext会自动清楚共享缓存((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();}}
2. 其中检查是否为配置类方法ConfigurationClassUtils.checkConfigurationClassCandidate
//检查给定的BeanDefinition是否是一个配置类的候选者(或一个在配置/组件类中声明的嵌套组件类)//并对其进行相应的标记处理//被@Configuration、@Component、@ComponentScan、@Import、@ImportResource、@Bean标记public static boolean checkConfigurationClassCandidate(BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {//获取bean定义信息中的class类名String className = beanDef.getBeanClassName();//如果className为空,或者bean定义信息中的factoryMethod不等于空,那么直接返回if (className == null || beanDef.getFactoryMethodName() != null) {return false;}AnnotationMetadata metadata;//通过注解注入的BeanDefinition都是AnnotatedGenericBeanDefinition,实现了AnnotatedBeanDefinition//Spring内部的BeanDefinition都是RootBeanDefiniton,实现了AbstractBeanDefinition//此处主要用于判断是否是归属于AnnotatedBeanDefinitionif (beanDef instanceof AnnotatedBeanDefinition &&className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {// Can reuse the pre-parsed metadata from the given BeanDefinition...// 从当前bean的定义信息中获取元素metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata();}//判断是否是Spring中默认的BeanDefinitionelse if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {// Check already loaded Class if present...// since we possibly can't even load the class file for this Class.//获取当前bean对象的Class对象Class<?> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass();//如果class实例是下面4种类或者接口的子类,父接口等任何一种情况,直接返回if (BeanFactoryPostProcessor.class.isAssignableFrom(beanClass) ||BeanPostProcessor.class.isAssignableFrom(beanClass) ||AopInfrastructureBean.class.isAssignableFrom(beanClass) ||EventListenerFactory.class.isAssignableFrom(beanClass)) {return false;}//为给定类创建新的AnnotationMetadatametadata = AnnotationMetadata.introspect(beanClass);}//如果上述两种情况都不符合else {try {//获取className的MetadataReader实例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;}}// 获取Bean Definition的元数据被@Configuration注解标注的属性字典值Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());// 如果bean被@Configuration注解标注,并且proxyBeanMethods属性的值为true,则标注当前配置类为full,即需要代理增强,为一个代理类if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);}// 如果存在,或者isConfigurationCandidate返回true,则标注当前配置类为lite,即不需要代理增强,为一个普通类// 标注了Configuration注解且proxyBeanMethods属性的值为false,则为lite模式// 没有标注Configuration注解,但是标注了Component、ComponentScan、Import、ImportResource、@Bean注解、则为lite模式else if (config != null || isConfigurationCandidate(metadata)) {beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);}// 组件类不存在@Configuration注解,直接返回falseelse {return false;}// 获取配置类的排序顺序,设置到组件定义属性中// It's a full or lite configuration candidate... Let's determine the order value, if any.//Bean Definition是一个标记为full/lite的候选项,如果有order属性就设置order属性Integer order = getOrder(metadata);if (order != null) {//设置bean的order值beanDef.setAttribute(ORDER_ATTRIBUTE, order);}return true;}
3. 真正干活的方法doProessConfigurationClass
// 通过读取源类的注释、成员和方法来构建完整的ConfigurationClass// 1.处理@Component// 2.处理每个@PropertySource// 3.处理每个@ComponentScan// 4.处理每个Impoit// 5.处理每个@ImportResource// 6.找配置类中@Bean注解的方法(找出Class中存在@Bean标注的方法,加入到ConfigurationClass的beanMethods属性)// 7.找接口中@Bean注解的方法// 8.存在父类则递归处理@Nullableprotected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)throws IOException {if (configClass.getMetadata().isAnnotated(Component.class.getName())) {// Recursively process any member (nested) classes first// 递归处理嵌套的成员类processMemberClasses(configClass, sourceClass, filter);}// Process any @PropertySource annotations// 处理@PropertySources和@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// 处理@ComponentScans和@ComponentScan注解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// 配置类使用了注解@ComponentScan -> 立即执行扫描。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 neededfor (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());}}}}// Process any @Import annotations// 处理@Import注解// getImports:递归获取@Import导入的类processImports(configClass, sourceClass, getImports(sourceClass), filter, true);// Process any @ImportResource annotations// 处理@ImportResource注解// 读取locations, reader属性,封装存放在importResources map集合中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);}}// Process individual @Bean methods// 处理@Bean方法Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);for (MethodMetadata methodMetadata : beanMethods) {configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));}// Process default methods on interfaces// 处理接口的默认方法实现,从jdk8开始,接口中的方法可以有自己的默认实现,因此如果这个接口的方法加了@Bean注解,也需要被解析processInterfaces(configClass, sourceClass);// Process superclass, if anyif (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 recursereturn sourceClass.getSuperClass();}}// No superclass -> processing is completereturn null;}