龙空技术网

spring源码-配置类加载流程

架构师之行 107

前言:

现时兄弟们对“spring 动态配置”大概比较重视,兄弟们都想要知道一些“spring 动态配置”的相关内容。那么小编同时在网络上网罗了一些关于“spring 动态配置””的相关资讯,希望看官们能喜欢,看官们一起来学习一下吧!

配置类角色

配置类可作为spring容器的启动入口,在类上加@Configuration注解,则表示这是一个配置类,通常会搭配@ComponontScan注解扫描包使用,springboot框架中的@SpringBootApplication注解也是基于此注解封装的,所以学习配置类加载是整个spring ioc的入口和重点。

spring的配置类分为两种,一种叫正式配置类,即加了@Configuration注解的,还有一种是非正式的配置类,即加了@Component、@ComponentScan、@Import、@ImportResource、@Bean注解

@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Configurationpublic @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 动态配置