BeanFactoryPostProcessor

# BeanFactoryPostProcessor

# 概述

# 源码分析

# AbstractApplicationContext$invokeBeanFactoryPostProcessors()

在Spring容器启动时的核心方法reflesh()的流程中,有一个invokeBeanFactoryPostProcessors()方法

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

    // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
    // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
    if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }
}

其中getBeanFactoryPostProcessors():获取容器上下文中已经注册的BeanFactoryPostProcessor。

所以这里把容器中已注册的BeanFactoryPostProcessor和当前beanFactory实例传进去,接下来调用BeanFactoryPostProcessor

# PostProcessorRegistrationDelegate$invokeBeanFactoryPostProcessors

下面来看看方法PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()的实现

  1. 判断参数beanFactory是BeanDefinitionRegistry类型:
  • 先创建两个集合,分别存储普通的BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor接口的子接口

BeanFactoryPostProcessor$postProcessBeanFactory:主要用来在Bean被实例化之前,修改Bean工厂

BeanDefinitionRegistryPostProcessor$postProcessBeanDefinitionRegistry:主要用来在Bean被实例化前,修改Bean定义信息。比如Mybatis的实现就依赖它

在整个执行Bean工厂后置处理器的过程中,BeanDefinitionRegistryPostProcessor的顺序优先于BeanFactoryPostProcessor

  • 把BeanDefinitionRegistryPostProcessor 与 beanFactoryPostProcessors区分开
// BeanDefinitionRegistryPostProcessor 与 beanFactoryPostProcessors区分开
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
    if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
        BeanDefinitionRegistryPostProcessor registryProcessor =
            (BeanDefinitionRegistryPostProcessor) postProcessor;
        // 直接执行
        // 这里执行了为什么还要添加到集合中后面执行
        registryProcessor.postProcessBeanDefinitionRegistry(registry);
        registryProcessors.add(registryProcessor);
    }
    else {
        regularPostProcessors.add(postProcessor);
    }
}
  • 首先调用实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
String[] postProcessorNames =
    beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
    if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
        currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
        processedBeans.add(ppName);
    }
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();

先从工厂中,按类型查找所有BeanDefinitionRegistryPostProcessor实现类对应的类名,判断是否实现了接口PriorityOrdered

根据类名,获取bean实例

对处理器排序

把这些处理器添加到保存postProcessBeanDefinitionRegistry的集合中,方便后面调用

最后调用当前这些后置处理器

  • 然后调用实现了Ordered接口的BeanDefinitionRegistryPostProcessor
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
    if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
        currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
        processedBeans.add(ppName);
    }
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();

整体流程与上面一致,这里重新查找了一遍,是因为上面的流程处理完,可能会新增processor

  • 最后调用其他BeanDefinitionRegistryPostProcessors,直到没有查找到新的processor出现
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
boolean reiterate = true;
while (reiterate) {
    reiterate = false;
    postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
    for (String ppName : postProcessorNames) {
        if (!processedBeans.contains(ppName)) {
            currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
            processedBeans.add(ppName);
            reiterate = true;
        }
    }
    sortPostProcessors(currentRegistryProcessors, beanFactory);
    registryProcessors.addAll(currentRegistryProcessors);
    invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
    currentRegistryProcessors.clear();
}
  • 然后调用集合中保存的两种processor
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
  1. 如果参数beanFactory不是BeanDefinitionRegistry类型,则直接调用入参的beanFactoryPostProcessors
else {
    // Invoke factory processors registered with the context instance.
    invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
  1. 至此,入参中的beanFactoryPostProcessors已经全部执行,接下来查找容器中所有实现了beanFactoryPostProcessors接口的类,进行调用
String[] postProcessorNames =
    beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
    if (processedBeans.contains(ppName)) {
        // skip - already processed in first phase above
    }
    else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
        priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
    }
    else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
        orderedPostProcessorNames.add(ppName);
    }
    else {
        nonOrderedPostProcessorNames.add(ppName);
    }
}

// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
for (String postProcessorName : orderedPostProcessorNames) {
    orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

// Finally, invoke all other BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
for (String postProcessorName : nonOrderedPostProcessorNames) {
    nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

同样会按照实现了PriorityOrdered、Ordered和其他没有实现排序接口的顺序

# 常用BeanFactoryPostProcessor

# ConfigurationClassPostProcessor

# 概述

可以扫描@ComponentScan @Bean @Import @ImportResource

# 源码分析

# MapperScannerConfigurer

可以扫描@MapperScanner

package com.prac.springbootdemo.bean_factory_post_processor;

import com.alibaba.druid.pool.DruidDataSource;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.GenericApplicationContext;

import javax.sql.DataSource;
import java.io.IOException;


/**
 * 2022/6/4
 */
public class BeanFactoryPostProcessorTests {

    public static void main(String[] args) throws IOException {
        GenericApplicationContext context = new GenericApplicationContext();

        context.registerBean("Config", Config.class);

        // @ComponentScan @Bean @Import @ImportResource
//        context.registerBean(ConfigurationClassPostProcessor.class);

        // @MapperScanner
//        context.registerBean(MapperScannerConfigurer.class, bd -> {
//            bd.getPropertyValues().add("basePackage", "com.prac.springbootdemo.bean_factory_post_processor.mapper");
//        });

        // 自己实现组件扫描 抽取出一个类
//        context.registerBean(ComponentScanPostProcessor.class);

        // 自己实现@Bean
        context.registerBean(BeanScanPostProcessor.class);

        // 实现Mapper扫描
        context.registerBean(MapperScanPostProcessor.class);

        context.refresh();

        for (String name : context.getBeanDefinitionNames()) {
            System.out.println("容器里bean: "+ name);
        }
    }

    /**
     * 2022/6/4
     */
    @Configuration
    @ComponentScan("com.prac.springbootdemo.bean_factory_post_processor.compoent")
    public static class Config {

        @Bean
        public Bean1 bean1() {
            return new Bean1();
        }

        @Bean
        public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource) {
            SqlSessionFactoryBean sqlsessionFactoryBean = new SqlSessionFactoryBean();
            sqlsessionFactoryBean.setDataSource(dataSource);
            return sqlsessionFactoryBean;
        }

        @Bean(initMethod = "init")
        public DruidDataSource dataSource() {
            DruidDataSource druidDataSource = new DruidDataSource();
            druidDataSource.setUrl("jdbc:mysql://120.79.93.88:3306");
            druidDataSource.setUsername("root");
            druidDataSource.setPassword("root");
            return druidDataSource;
        }

//        /**
//         * spring并不能管理接口 所以需要工厂来根据接口生产bean
//         * 这样一个个可以实现,但是没法批量添加包下所有mapper接口
//         * @param sqlSessionFactory
//         * @return
//         */
//        @Bean
//        public MapperFactoryBean<Mapper1> mapper1(SqlSessionFactory sqlSessionFactory){
//            MapperFactoryBean<Mapper1> factory = new MapperFactoryBean<>(Mapper1.class);
//            factory.setSqlSessionFactory(sqlSessionFactory);
//            return factory;
//        }
//
//        @Bean
//        public MapperFactoryBean<Mapper2> mapper2(SqlSessionFactory sqlSessionFactory){
//            MapperFactoryBean<Mapper2> factory = new MapperFactoryBean<>(Mapper2.class);
//            factory.setSqlSessionFactory(sqlSessionFactory);
//            return factory;
//        }
    }

    public static class Bean1 {
        public Bean1() {
            System.out.println("bean1 init");
        }
    }
}
package com.prac.springbootdemo.bean_factory_post_processor.compoent;

import org.springframework.stereotype.Component;

/**
 * 2022/6/4
 */
@Component
public class Bean2 {

    public Bean2() {
        System.out.println("bean2 init");
    }
}

package com.prac.springbootdemo.bean_factory_post_processor.mapper;

import org.apache.ibatis.annotations.Mapper;

/**
 * 2022/6/4
 */
@Mapper
public interface Mapper1 {
}


package com.prac.springbootdemo.bean_factory_post_processor.mapper;

import org.apache.ibatis.annotations.Mapper;

/**
 * 2022/6/4
 */
@Mapper
public interface Mapper2 {
}

# 自己实现BeanFactoryPostProcessor

# 自己实现@Component扫描

public class ComponentScanPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) {
        try {
            ComponentScan componentScan = AnnotationUtils.findAnnotation(BeanFactoryPostProcessorTests.Config.class, ComponentScan.class);
            CachingMetadataReaderFactory cachingMetadataReaderFactory = new CachingMetadataReaderFactory();
            AnnotationBeanNameGenerator generator = new AnnotationBeanNameGenerator();
            if (componentScan != null){
                for (String p : componentScan.basePackages()) {
                    String path = "classpath*:" + p.replace(".", "/") + "/**/*.class";
                    Resource[] resources = new PathMatchingResourcePatternResolver().getResources(path);
                    for (Resource resource : resources) {
                        MetadataReader reader = cachingMetadataReaderFactory.getMetadataReader(resource);
                        AnnotationMetadata annotationMetadata = reader.getAnnotationMetadata();

                        if (annotationMetadata.hasAnnotation(Component.class.getName()) ||
                                annotationMetadata.hasMetaAnnotation(Component.class.getName())){
                            // 获取bean定义信息
                            AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder
                                    .genericBeanDefinition(reader.getClassMetadata().getClassName())
                                    .getBeanDefinition();

                            if (configurableListableBeanFactory instanceof DefaultListableBeanFactory){
                                DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) configurableListableBeanFactory;

                                String beanName = generator.generateBeanName(beanDefinition, beanFactory);

                                // 注册bean
                                beanFactory.registerBeanDefinition(beanName,beanDefinition);
                            }
                        }
                    }
                }
            }
        }catch (Exception e){
        }
    }
}

# 自己实现扫描@Bean

  • 可以一个个定义
//        /**
//         * spring并不能管理接口 所以需要工厂来根据接口生产bean
//         * 这样一个个可以实现,但是没法批量添加包下所有mapper接口
//         * @param sqlSessionFactory
//         * @return
//         */
//        @Bean
//        public MapperFactoryBean<Mapper1> mapper1(SqlSessionFactory sqlSessionFactory){
//            MapperFactoryBean<Mapper1> factory = new MapperFactoryBean<>(Mapper1.class);
//            factory.setSqlSessionFactory(sqlSessionFactory);
//            return factory;
//        }
//
//        @Bean
//        public MapperFactoryBean<Mapper2> mapper2(SqlSessionFactory sqlSessionFactory){
//            MapperFactoryBean<Mapper2> factory = new MapperFactoryBean<>(Mapper2.class);
//            factory.setSqlSessionFactory(sqlSessionFactory);
//            return factory;
//        }
    }
  • 也可以批量扫描某路径下所有接口
public class BeanScanPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        try {
            CachingMetadataReaderFactory cachingMetadataReaderFactory = new CachingMetadataReaderFactory();
            // 这里要注意内部类classpath的写法
            MetadataReader metadataReader = cachingMetadataReaderFactory.getMetadataReader(new ClassPathResource("com/prac/springbootdemo/bean_factory_post_processor/BeanFactoryPostProcessorTests$Config.class"));
            Set<MethodMetadata> annotatedMethods = metadataReader.getAnnotationMetadata().getAnnotatedMethods(Bean.class.getName());

            for (MethodMetadata method : annotatedMethods) {
                BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
                builder.setFactoryMethodOnBean(method.getMethodName(),"Config");
                builder.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR); // 不加的话SqlSessionFactoryBean无法注入

                String initMethod = method.getAnnotationAttributes(Bean.class.getName()).get("initMethod").toString();
                System.out.println("获取到initMethod: "+ initMethod);
                if (initMethod.length() > 0){
                    builder.setInitMethodName(initMethod);
                }

                AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();

                if (configurableListableBeanFactory instanceof DefaultListableBeanFactory){
                    DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) configurableListableBeanFactory;
                    beanFactory.registerBeanDefinition(method.getMethodName(),beanDefinition);
                }
            }
        }catch (Exception e){

        }

    }
}

# 自己实现@Mapper扫描

/**
 * 2022/6/4
 * 这里实现BeanDefinitionRegistryPostProcessor 方法里就不用强转工厂来注册BeanDefinition
 */
public class MapperScanPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
    }

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanFactory) throws BeansException {
        try {
            PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
            Resource[] resources = resolver.getResources("classpath:com/prac/springbootdemo/bean_factory_post_processor/mapper/**/*.class");
            CachingMetadataReaderFactory cachingMetadataReaderFactory = new CachingMetadataReaderFactory();
            AnnotationBeanNameGenerator generator = new AnnotationBeanNameGenerator();
            for (Resource resource : resources) {
                MetadataReader metadataReader = cachingMetadataReaderFactory.getMetadataReader(resource);
                ClassMetadata classMetadata = metadataReader.getClassMetadata();
                if (classMetadata.isInterface()){
                    AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(MapperFactoryBean.class)
                            .addConstructorArgValue(classMetadata.getClassName())
                            .setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE)
                            .getBeanDefinition();
                    // 这里获取beanName不能这样做 这样获取到的是MapperFactoryBean
//                    String beanName = generator.generateBeanName(beanDefinition, beanFactory);

                    // 应该重新获取mapper的bean定义信息
                    AbstractBeanDefinition mapperBeanDefinition = BeanDefinitionBuilder.genericBeanDefinition(metadataReader.getClassMetadata().getClassName()).getBeanDefinition();
                    String beanName = generator.generateBeanName(mapperBeanDefinition, beanFactory);
                    beanFactory.registerBeanDefinition(beanName,beanDefinition);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

# 总结

最近更新
01
深入理解Java虚拟机读书笔记(四)
05-03
02
深入理解Java虚拟机(三)
04-30
03
深入理解Java虚拟机读书笔记(二)
04-24
更多文章>