Spring源码分析之BeanFactoryPostProcessor调用过程(一)

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介: Spring源码分析之BeanFactoryPostProcessor调用过程

前文传送门:

  1. Spring源码分析之预启动流程
  2. Spring源码分析之BeanFactory体系结构

本文内容:

  1. AbstractApplicationContext#refresh前部分的一点小内容
  2. BeanFactoryPostProcessor调用过程详解
  3. mybatis是如何使用本节知识整合spring的?

正文:

在Spring中,一共分为BeanFactoryPostProcessorBeanPostProcessor两类后置处理器,他们主要的职责如下:

  • BeanFactoryPostProcessor:负责beanClassbeanDefinition的过程,包括但不限于寻找合适的beanClass,创建beanDefinition,修改beanDefinition,将beanDefinition注册到BeanFactory
  • BeanPostProcessor:负责beanDefinitionbean的过程,包括但不限于bean的属性赋值,初始化

本次主要分析BeanFactoryPostProcessor的调用过程,下面是BeanFactoryPostProcessor调用过程的大体流程图,也是本文想要表述的大概内容,原图链接: BeanFactoryPostProcessor调用过程

refresh的前半段流程

// 启动前的准备工作
prepareRefresh();
// 由于web项目中并不会先引入DefaultListableBeanFactory,在这里通知子类刷新BeanFactory
// 而我们是使用new AnnotationConfigApplicationContext()的方式,就是直接返回之前引入的DefaultListableBeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 准备工作,给DefaultListableBeanFactory填充属性
prepareBeanFactory(beanFactory);
// 留于子类调用的扩展方法
postProcessBeanFactory(beanFactory);
// 调用实现BeanFactoryPostProcessor的后置处理器,
// 其实就是我们在new AnnotatedBeanDefinitionReader时注册的解析配置类的后置处理器ConfigurationClassPostProcessor
// 这里会解析配置类以及处理解析配置类后所引入的所有BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(beanFactory);
// 注册上一步解析出来的所有的BeanPostProcessor
// 注册逻辑和上一步大致相同,PriorityOrdered-> Ordered -> 普通的
registerBeanPostProcessors(beanFactory);

prepareRefresh

// 设置容器状态
this.closed.set(false);
this.active.set(true);

prepareBeanFactory

// 添加一个ApplicationContextAwareProcessor,用于bean初始化前调用一系列的Aware接口回调
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
// 用于处理实现ApplicationListener接口的bean,bean初始化后添加监听
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

invokeBeanFactoryPostProcessors(重点)

此方法将解析配置类以及处理解析配置类后所引入的所有BeanFactoryPostProcessor

温馨提醒:内容较多,还请耐心阅读~

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    //由于之前注册的都是BeanDefinition,此时还并没有生产任何的BeanFactoryPostProcessor,所以getBeanFactoryPostProcessors是空的
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
}

invokeBeanFactoryPostProcessors

前部分主要是寻找ConfigurationClassPostProcessor并将它实例化

//放置已处理的beanName
Set<String> processedBeans = new HashSet<>();
//放置常规的后置处理器,就是只实现了BeanFactoryPostProcessor接口的
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
//放置实现了BeanDefinitionRegistryPostProcessor接口的,之前我们注册的后置处理器中只有ConfigurationClassPostProcessor实现了
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
//放置当前的RegistryProcessors
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
//查找实现了BeanDefinitionRegistryPostProcessor接口的BeanName,其实就只有一个ConfigurationClassPostProcessor
String[] postProcessorNames =
    beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
    //ConfigurationClassPostProcessor同样实现了PriorityOrdered接口
    if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
        //注意这里调用了getBean方法,生产了ConfigurationClassPostProcessor,放到currentRegistryProcessors集合中
        currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
        processedBeans.add(ppName);
    }
}
//排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
//将生产出来的后置处理器放到集合中
registryProcessors.addAll(currentRegistryProcessors);

接下来就开始调用ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法

//调用ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
private static void invokeBeanDefinitionRegistryPostProcessors(
    Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
  //循环BeanDefinitionRegistryPostProcessor进行调用
    for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
        postProcessor.postProcessBeanDefinitionRegistry(registry);
    }
}

postProcessBeanDefinitionRegistry

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
    processConfigBeanDefinitions(registry);
}
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
  //放置候选配置类
    List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
    String[] candidateNames = registry.getBeanDefinitionNames();
    //遍历之前注册的所有bean定义,找到其中的配置类,其实就是我们自己传进来的配置类
    for (String beanName : candidateNames) {
        //...省略校验过程...
        BeanDefinition beanDef = registry.getBeanDefinition(beanName);
        //检查是否是有@Configuration注解的BeanDifinition -> full类型的配置类 -> 会把配置类替换成动态代理类
        //或者该类包含@Component @ComponentScan @Import @ImportResource @Bean 注解的其中之一 -> lite类型的配置类  -> 不会替换成动态代理类
        else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
            configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
        }
    }
    //....省略片段....
    //实例化一个配置类解析器
    ConfigurationClassParser parser = new ConfigurationClassParser(
        this.metadataReaderFactory, this.problemReporter, this.environment,
        this.resourceLoader, this.componentScanBeanNameGenerator, registry);
    do {
        //解析配置类
        parser.parse(candidates);
        parser.validate();
        //parser.getConfigurationClasses()就是拿到刚刚解析完放到map中的配置类
        Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
        configClasses.removeAll(alreadyParsed);
        //这里处理@Import导入的beanDefintion和配置类中的@Bean
        this.reader.loadBeanDefinitions(configClasses);
        alreadyParsed.addAll(configClasses);
    //以下逻辑是找出未解析的配置类,如@Bean和ImportBeanDefinitionRegistrar所引入的
        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放到候选集合中继续解析
                    if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
                        !alreadyParsedClasses.contains(bd.getBeanClassName())) {
                        candidates.add(new BeanDefinitionHolder(bd, candidateName));
                    }
                }
            }
            candidateNames = newCandidateNames;
        }
    }
    while (!candidates.isEmpty());
}

ConfigurationClassUtils.checkConfigurationClassCandidate中的摘取片段

//检查是否有标识@Configuration
Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
    //设置配置属性值为full
    beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
}
//检查是否包含@Component @ComponentScan @Import @ImportResource @Bean
else if (config != null || isConfigurationCandidate(metadata)) {
    //设置配置属性值为lite
    beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
}
else {
    return false;
}

配置类解析流程(parser.parse(candidates))

public void parse(Set<BeanDefinitionHolder> configCandidates) {
    for (BeanDefinitionHolder holder : configCandidates) {
        BeanDefinition bd = holder.getBeanDefinition();
        //配置类的beanDefinition为AnnotatedGenericBeanDefinition,true
        if (bd instanceof AnnotatedBeanDefinition) {
            //传入配置类的元数据与beanName
            parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
        }
    }
}
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
    processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
}

processConfigurationClass

protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
    SourceClass sourceClass = asSourceClass(configClass, filter);
    do {
        //解析配置类,这里可能返回配置类的父类,需要继续处理
        sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
    }
    while (sourceClass != null);
    //将配置类放入map中
    this.configurationClasses.put(configClass, configClass);
}

doProcessConfigurationClass

//@Configuration 本身也是 @Component的组合注解
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
    // 处理内置类,如果内置类也是个配置类,递归处理内置类
    processMemberClasses(configClass, sourceClass, filter);
}

处理@ComponentScan

// Process any @ComponentScan annotations
// 找出配置类上的@ComponentScan注解属性
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
    sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
for (AnnotationAttributes componentScan : componentScans) {
    //将@ComponentScan引入的所有类扫描成BeanDefinition并注册到容器中
    Set<BeanDefinitionHolder> scannedBeanDefinitions =
        this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
    //这里循环是为了判断扫描出来的beanDefinition是否是配置类,如果是配置类的话需要递归解析
    for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
        BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
        //这里是必然为true, 能被扫描出来的必然有@Component注解,而@Component注解为lite配置类
        //这里主要是为了在检查的同时设置一下full或者lite的类型
        if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
            //配置类就继续递归解析
            parse(bdCand.getBeanClassName(), holder.getBeanName());
        }
    }
}
this.componentScanParser.parse
public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
    //重新new了一个classpath的bean定义扫描器,没用我们最开始创建的
    // 这里添加了一个默认的过滤器,过滤@Component注解的
    ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
                                                                        componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
    //添加自己配置的过滤器
    for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {
        for (TypeFilter typeFilter : typeFiltersFor(filter)) {
            scanner.addIncludeFilter(typeFilter);
        }
    }
    for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) {
        for (TypeFilter typeFilter : typeFiltersFor(filter)) {
            scanner.addExcludeFilter(typeFilter);
        }
    }
    //如果配置的为懒加载,则扫描出来的所有BeanDefinition都默认为懒加载的
    boolean lazyInit = componentScan.getBoolean("lazyInit");
    if (lazyInit) {
        scanner.getBeanDefinitionDefaults().setLazyInit(true);
    }
    //将配置的basePackages中所有的包路径放到set集合中,保证最终所有的包路径唯一
    Set<String> basePackages = new LinkedHashSet<>();
    String[] basePackagesArray = componentScan.getStringArray("basePackages");
    for (String pkg : basePackagesArray) {
        String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),
                                                               ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
        Collections.addAll(basePackages, tokenized);
    }
    //添加一个排除过滤器,排除该配置类
    scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
        @Override
        protected boolean matchClassName(String className) {
            return declaringClass.equals(className);
        }
    });
    //开始扫描
    return scanner.doScan(StringUtils.toStringArray(basePackages));
}
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) {
        //找到所有候选的bean -> 默认过滤器为过滤标识了@Component注解的class
        Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
        for (BeanDefinition candidate : candidates) {
            String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
            if (candidate instanceof AbstractBeanDefinition) {
                //设置默认值,比如上一个方法刚刚设置的是否懒加载
                postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
            }
            if (candidate instanceof AnnotatedBeanDefinition) {
                //解析beanClass的所有注解填充到beanDefinition中,@Lazy @Primary @DependsOn @Role @Description
                AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
            }
            //检查之前是否注册过,未注册返回true
            if (checkCandidate(beanName, candidate)) {
                BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
                beanDefinitions.add(definitionHolder);
                //将beanDefinition注册到容器中
                registerBeanDefinition(definitionHolder, this.registry);
            }
        }
    }
    return beanDefinitions;
}
寻找候选组件#findCandidateComponents
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
    return scanCandidateComponents(basePackage);
}
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
    Set<BeanDefinition> candidates = new LinkedHashSet<>();
    //将类路径替换成绝对路径
    String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
        resolveBasePackage(basePackage) + '/' + this.resourcePattern;
    //找出该路径下的所有类资源
    Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
    for (Resource resource : resources) {
        if (resource.isReadable()) {
            MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
            //调用刚刚配置的过滤器进行匹配,
            //默认过滤器逻辑:是否标识了@Component注解(包括组合的,如@Service)
            if (isCandidateComponent(metadataReader)) {
                //通过扫描方式创建的BeanDefintion为ScannedGenericBeanDefinition
                ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
                sbd.setSource(resource);
                //不是接口和抽象类,或者是抽象类但标识了@Lookup
                if (isCandidateComponent(sbd)) {
                    //将beanDefinition存到集合中
                    candidates.add(sbd);
                }
            }
        }
    }
    return candidates;
}


目录
相关文章
|
1月前
|
监控 Java 应用服务中间件
Spring Boot整合Tomcat底层源码分析
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置和起步依赖等特性,大大简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是其与Tomcat的整合。
61 1
|
3天前
|
设计模式 XML Java
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
本文详细介绍了Spring框架的核心功能,并通过手写自定义Spring框架的方式,深入理解了Spring的IOC(控制反转)和DI(依赖注入)功能,并且学会实际运用设计模式到真实开发中。
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
|
1月前
|
前端开发 Java Spring
Spring MVC源码分析之DispatcherServlet#getHandlerAdapter方法
`DispatcherServlet`的 `getHandlerAdapter`方法是Spring MVC处理请求的核心部分之一。它通过遍历预定义的 `HandlerAdapter`列表,找到适用于当前处理器的适配器,并调用适配器执行具体的处理逻辑。理解这个方法有助于深入了解Spring MVC的工作机制和扩展点。
38 1
|
1月前
|
前端开发 Java Spring
Spring MVC源码分析之DispatcherServlet#getHandlerAdapter方法
`DispatcherServlet`的 `getHandlerAdapter`方法是Spring MVC处理请求的核心部分之一。它通过遍历预定义的 `HandlerAdapter`列表,找到适用于当前处理器的适配器,并调用适配器执行具体的处理逻辑。理解这个方法有助于深入了解Spring MVC的工作机制和扩展点。
35 1
|
2月前
|
缓存 JavaScript Java
Spring之FactoryBean的处理底层源码分析
本文介绍了Spring框架中FactoryBean的重要作用及其使用方法。通过一个简单的示例展示了如何通过FactoryBean返回一个User对象,并解释了在调用`getBean()`方法时,传入名称前添加`&`符号会改变返回对象类型的原因。进一步深入源码分析,详细说明了`getBean()`方法内部对FactoryBean的处理逻辑,解释了为何添加`&`符号会导致不同的行为。最后,通过具体代码片段展示了这一过程的关键步骤。
Spring之FactoryBean的处理底层源码分析
|
1月前
|
前端开发 Java Spring
Spring MVC源码分析之DispatcherServlet#getHandlerAdapter方法
`DispatcherServlet`的 `getHandlerAdapter`方法是Spring MVC处理请求的核心部分之一。它通过遍历预定义的 `HandlerAdapter`列表,找到适用于当前处理器的适配器,并调用适配器执行具体的处理逻辑。理解这个方法有助于深入了解Spring MVC的工作机制和扩展点。
30 0
|
6月前
|
存储 安全 Java
Spring Security 6.x OAuth2登录认证源码分析
上一篇介绍了Spring Security框架中身份认证的架构设计,本篇就OAuth2客户端登录认证的实现源码做一些分析。
277 2
Spring Security 6.x OAuth2登录认证源码分析
|
6月前
|
存储 Java Spring
Spring IOC 源码分析之深入理解 IOC
Spring IOC 源码分析之深入理解 IOC
205 2
|
7月前
|
Dubbo Java 应用服务中间件
Dubbo 第四节: Spring与Dubbo整合原理与源码分析
DubboConfigConfigurationRegistrar的主要作⽤就是对propties⽂件进⾏解析并根据不同的配置项项⽣成对应类型的Bean对象。
164 0
|
7月前
|
安全 Java 数据安全/隐私保护
【Spring Security】Spring Security 认证过程源码分析
【Spring Security】Spring Security 认证过程源码分析
84 0