spring-源码03-配置类加载流程

2020-11-25  本文已影响0人  Coding626

配置类角色

配置类可作为spring容器的启动入口,在类上加@Configuration注解,则表示这是一个配置类,通常会搭配@ComponontScan注解扫描包使用,springboot框架中的@SpringBootApplication注解也是基于此注解封装的,所以学习配置类加载是整个spring ioc的入口和重点。
spring的配置类分为两种,一种叫正式配置类,即加了@Configuration注解的,还有一种是非正式的配置类,即加了@Component、@ComponentScan、@Import、@ImportResource、@Bean注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {

}

配置类作用

配置类作为程序的入口,可配置各种注解,如@ComponentScan-对指定包下的bean进行初始化(下文将着重写到spring是如何实现的),@EnableTransactionManagement-开启事务注解等。本文暂时只讲bean定义的初始化实现,其他注解比如EnableTransactionManagement会在后面章节提出。

配置类加载流程

1.注册解析配置类的后置处理器ConfigurationClassPostProcessor

ConfigurationClassPostProcessor属于spring的一个重要的初始化类,后面解析配置类讲用到。容器初始化的时候new AnnotatedBeanDefinitionReader()->AnnotationConfigUtils.registerAnnotationConfigProcessors,看到下面的set,初始化长度是8,该方法初始了8个beanFactory后置处理器,其中第一个就是配置类解析处理类。

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
            BeanDefinitionRegistry registry, @Nullable Object source) {

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

        //其他后置处理器
        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));
        }

        
        if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

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

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

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

2.准备@Compent注解,将该注解加入到自定义规则中

在上文的this()方法中,有一个this.scanner = new ClassPathBeanDefinitionScanner(this);点到registerDefaultFilters()方法中进去,发现里面
this.includeFilters.add(new AnnotationTypeFilter(Component.class));,在一个filter中加入了我们的@Compent,后面会用到

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
            Environment environment, @Nullable ResourceLoader resourceLoader) {

        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        this.registry = registry;

        
        if (useDefaultFilters) {
            registerDefaultFilters();
        }
        
        setEnvironment(environment);
        
        setResourceLoader(resourceLoader);
    }
  protected void registerDefaultFilters() {
        //加入扫描我们的@Component的
        this.includeFilters.add(new AnnotationTypeFilter(Component.class));
        ...
    }

3.读取配置类,转换成bean定义

配置类也是一个bean,所以也需要在进bean工厂之前转换成bean定义。转化入口如下,初始化容器的时候,有个register方法,就是注册配置类的方法,最终也会调用registerBeanDefinition方法。

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
        
        this();
        //注册配置类
        register(annotatedClasses);
        
        refresh();
    }

4.调用bean工厂后置处理器

该步骤很重要,我们在1步骤中注册了8个bean工厂的后置处理器,在这里开始调用,入口在AbstractApplicationContext.refresh()->AbstractApplicationContext.invokeBeanFactoryPostProcessors()->PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors
截取该方法一段,第一个if,判断了当前处理器是不是BeanDefinitionRegistryPostProcessor类型,而之前1步骤中注册的配置类处理器ConfigurationClassPostProcessor是该类型,所以调用ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry()方法。


image.png
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
                
                if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                    
                    BeanDefinitionRegistryPostProcessor registryProcessor =
                            (BeanDefinitionRegistryPostProcessor) postProcessor;
                    
                    registryProcessor.postProcessBeanDefinitionRegistry(registry);
                    
                    registryProcessors.add(registryProcessor);
                }
                else {//若没有实现BeanDefinitionRegistryPostProcessor 接口,那么他就是BeanFactoryPostProcessor
                    
                    regularPostProcessors.add(postProcessor);
                }
            }

ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry()方法,这里会循环所有的bean定义,将配置类加到候选configCandidates中,(Candidate英文翻译过来“候选”)候选配置类的标准在文章开头写了,下面两个if代表两种不同的配置类。


        for (String beanName : candidateNames) {
            
            BeanDefinition beanDef = registry.getBeanDefinition(beanName);
        
            if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
                    ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
                }
            }
        
            else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
                //满足添加 就加入到候选的配置类集合中
                configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
            }
        }

5.解析配置类

拿到4步骤中的候选配置类后,就开始真正的解析配置类了,入口在ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry()中会调用ConfigurationClassParser.parse()->ConfigurationClassParser.ddoProcessConfigurationClass(),第一行中拿到@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) {
                
                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());
                    }
                }
            }
        }


进入到ComponentScanAnnotationParser.parse(),

//设置CompentScan对象的includeFilters 包含的属性
        for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {
            for (TypeFilter typeFilter : typeFiltersFor(filter)) {
                scanner.addIncludeFilter(typeFilter);
            }
        }

然后调用ClassPathBeanDefinitionScanner.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) {
        
            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 (candidate instanceof AnnotatedBeanDefinition) {
                    AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
                }
                
                if (checkCandidate(beanName, candidate)) {
                    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
                    definitionHolder =
                            AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
                    beanDefinitions.add(definitionHolder);
                    registerBeanDefinition(definitionHolder, this.registry);
                }
            }
        }
        return beanDefinitions;
    }

进入findCandidateComponents->scanCandidateComponents->isCandidateComponent(筛选候选Component),这里就会从2步骤中的过滤器规则中得到@Component,放入到bean定义集合中

protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
        
        for (TypeFilter tf : this.excludeFilters) {
            if (tf.match(metadataReader, getMetadataReaderFactory())) {
                return false;
            }
        }
        
        for (TypeFilter tf : this.includeFilters) {
            if (tf.match(metadataReader, getMetadataReaderFactory())) {
                return isConditionMatch(metadataReader);
            }
        }
        return false;
    }


6.配置类读取到的bean定义集合加载成bean定义

回到ConfigurationClassPostProcessor.processConfigBeanDefinitions方法中,调用this.reader.loadBeanDefinitions(configClasses);这里真正的把我们解析出来的配置类注册成bean定义

do {
            
            parser.parse(candidates);
            

            ...
            
            this.reader.loadBeanDefinitions(configClasses);
            

            
        }
上一篇下一篇

猜你喜欢

热点阅读