AbstractApplicationContext#refresh前部分的一点小内容
BeanFactoryPostProcessor调用过程详解
mybatis是如何使用本节知识整合spring的?
正文:
在Spring中,一共分为BeanFactoryPostProcessor和BeanPostProcessor两类后置处理器,他们主要的职责如下:
BeanFactoryPostProcessor:负责beanClass到beanDefinition的过程,包括但不限于寻找合适的beanClass,创建beanDefinition,修改beanDefinition,将beanDefinition注册到BeanFactory中
BeanPostProcessor:负责beanDefinition到bean的过程,包括但不限于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()); }