美文网首页
spring-源码03-配置类加载流程

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

作者: Coding626 | 来源:发表于2020-11-25 17:49 被阅读0次

    配置类角色

    配置类可作为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);
                
    
                
            }
    

    相关文章

      网友评论

          本文标题:spring-源码03-配置类加载流程

          本文链接:https://www.haomeiwen.com/subject/ywyliktx.html