spring集成mybatis底层原理及BeanDefinitionRegistryPostProcessor+ BeanFactoryPostProcessor源码分析
文章目录
- 【README】
- 【1】SqlSessionFactory
- 【2】MapperScannerConfigurer-映射器扫描配置器
- 【3】AbstractApplicationContext-invokeBeanFactoryPostProcessors()作用及源码分析
- 【4】总结
【README】
- 本文总结了spring集成mybatis的底层原理及源码分析;
- 本文借助 mybatis的MapperScannerConfigurer是 BeanDefinitionRegistryPostProcessor,扩展分析了 BeanDefinitionRegistryPostProcessor与BeanFactoryPostProcessor的源码及使用场景;
【1】SqlSessionFactory
【1.1】spring集成mybatis操作数据库开发事例
【 spring-mybatis-beans-mapperscan.xml 】spring集成mybatis的bean定义xml
- SqlSessionFactory的bean创建依赖于 SqlSessionFactoryBean,所以定义SqlSessionFactory的class为SqlSessionFactoryBean。
- userMapper的bean创建依赖于 MapperFactoryBean, 所以定义了userMapper的class为MapperFactoryBean ;
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/myspring" />
<property name="username" value="root" />
<property name="password" value="rootroot" />
<property name="initialSize" value="2" />
<property name="maxIdle" value="2" />
<property name="minIdle" value="1" />
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="classpath:a_src_deep_analysis/chapter9/mybatis-config.xml"/>
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">-->
<!-- <property name="mapperInterface" value="com.tom.srccode.deep.analysis.chapter9.UserMapper" />-->
<!-- <property name="sqlSessionFactory" ref="sqlSessionFactory" />-->
<!-- </bean>-->
<!-- 使用MapperScannerConfigurer,扫描特定包,自动成批创建映射器Mapper -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.tom.srccode.deep.analysis.chapter9" />
<property name="processPropertyPlaceHolders" value="true" />
</bean>
</beans>
【 mybatis-config.xml 】 mybaits配置xml文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="defaultExecutorType" value="SIMPLE"/>
</settings>
<typeAliases>
<typeAlias alias="UserPO" type="com.tom.srccode.deep.analysis.chapter9.UserPO" />
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="jdbc" />
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/myspring"/>
<property name="username" value="root"/>
<property name="password" value="rootroot"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="a_src_deep_analysis/chapter9/UserMapper.xml" />
</mappers>
</configuration>
【使用UserMapper的单元测试案例】
@Slf4j
public class SpringMybatisIntegrateUnitTest {
@Test
public void test() {
// ApplicationContext context = new ClassPathXmlApplicationContext("a_src_deep_analysis/chapter9/spring-mybatis-beans.xml");
ApplicationContext context = new ClassPathXmlApplicationContext("a_src_deep_analysis/chapter9/spring-mybatis-beans-mapperscan.xml");
UserMapper userMapper = context.getBean(UserMapper.class);
log.info("user = {}", userMapper.getUser("3"));
}
【使用SqlSession操作db的单元测试案例】
@Test
public void test3() {
ApplicationContext context = new ClassPathXmlApplicationContext("a_src_deep_analysis/chapter9/spring-mybatis-beans-mapperscan.xml");
// 获取 SqlSessionFactory bean
SqlSessionFactory sqlSessionFactory = context.getBean("sqlSessionFactory", SqlSessionFactory.class);
Map<String, Object> paramMap = new HashMap<>(2);
paramMap.put("id", "3");
// 使用SqlSessionFactory获取 SqlSession , 并通过 SqlSession操作数据库
try(SqlSession sqlSession = sqlSessionFactory.openSession(true)) {
List<UserPO> userPOList = sqlSession.selectList("com.tom.srccode.deep.analysis.chapter9.UserMapper.getUser", paramMap);
log.info("userPOList = {}", userPOList);
}
}
【使用SqlSession.getMapper()操作db的单元测试案例】
/**
* @description 使用SqlSession获取UserMapper,操作数据库
*
* @author tomx
* @datetime 2026/7/4 20:15
*/
@Test
public void test4() {
ApplicationContext context = new ClassPathXmlApplicationContext("a_src_deep_analysis/chapter9/spring-mybatis-beans-mapperscan.xml");
SqlSessionFactory sqlSessionFactory = context.getBean("sqlSessionFactory", SqlSessionFactory.class);
Map<String, Object> paramMap = new HashMap<>(2);
paramMap.put("id", "3");
try(SqlSession sqlSession = sqlSessionFactory.openSession(true)) {
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
log.info("userPOList = {}", userMapper.getUser("3"));
}
}
【1.2】SqlSessionFactory-bean的创建依赖SqlSessionFactoryBean
- SqlSessionFactory的bean创建依赖于 SqlSessionFactoryBean,其类层次结构如下。
public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ContextRefreshedEvent> {
public void afterPropertiesSet() throws Exception {
Assert.notNull(this.dataSource, "Property 'dataSource' is required");
Assert.notNull(this.sqlSessionFactoryBuilder, "Property 'sqlSessionFactoryBuilder' is required");
Assert.state(this.configuration == null && this.configLocation == null || this.configuration == null || this.configLocation == null, "Property 'configuration' and 'configLocation' can not specified with together");
this.sqlSessionFactory = this.buildSqlSessionFactory();
}
protected SqlSessionFactory buildSqlSessionFactory() throws Exception {
XMLConfigBuilder xmlConfigBuilder = null;
Configuration targetConfiguration;
if (this.configuration != null) {
// ...
}
}
public SqlSessionFactory getObject() throws Exception {
if (this.sqlSessionFactory == null) {
this.afterPropertiesSet();
}
return this.sqlSessionFactory;
}
}
【代码解说】
- InitializingBean的实现类,在bean初始化为bean属性赋值时会调用其afterPropertiesSet(), 该方法旨在创建 SqlSessionFactory;
- FactoryBean的实现类,当applicationContext.get(‘beanName’)时,若bean的class为FactoryBean,则会调用其getObject()方法获取bean实例;
【1.3】UserMapper或业务Mapper的创建过程依赖 MapperFactoryBean
- 单元测试中, UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 因UserMapper的class定义为org.mybatis.spring.mapper.MapperFactoryBean,所以调用MapperFactoryBean#getObject()方法;
- org.mybatis.spring.mapper.MapperFactoryBean定义如下(继承SqlSessionDaoSupport):
public class MapperFactoryBean<T> extends SqlSessionDaoSupport implements FactoryBean<T> {
private Class<T> mapperInterface;
private boolean addToConfig = true;
public MapperFactoryBean() {
}
public MapperFactoryBean(Class<T> mapperInterface) {
this.mapperInterface = mapperInterface;
}
protected void checkDaoConfig() {
super.checkDaoConfig();
Assert.notNull(this.mapperInterface, "Property 'mapperInterface' is required");
Configuration configuration = this.getSqlSession().getConfiguration();
if (this.addToConfig && !configuration.hasMapper(this.mapperInterface)) {
try {
configuration.addMapper(this.mapperInterface);
} catch (Exception e) {
this.logger.error("Error while adding the mapper '" + String.valueOf(this.mapperInterface) + "' to configuration.", e);
throw new IllegalArgumentException(e);
} finally {
ErrorContext.instance().reset();
}
}
}
// spring容器ApplicationContext.getBean(..)方法,会调用 MapperFactoryBean的getObject()方法获取bean实例
// 其中 mapperInterface 就是 MapperFactoryBean对应Mapper接口class
public T getObject() throws Exception {
return (T)this.getSqlSession().getMapper(this.mapperInterface);
}
//...
}
// SqlSessionDaoSupport 定义:
public abstract class SqlSessionDaoSupport extends DaoSupport {
private SqlSessionTemplate sqlSessionTemplate;
// 装配SqlSessionFactory时,创建SqlSessionTemplate并赋值
public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
if (this.sqlSessionTemplate == null || sqlSessionFactory != this.sqlSessionTemplate.getSqlSessionFactory()) {
this.sqlSessionTemplate = this.createSqlSessionTemplate(sqlSessionFactory);
}
}
protected SqlSessionTemplate createSqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
public final SqlSessionFactory getSqlSessionFactory() {
return this.sqlSessionTemplate != null ? this.sqlSessionTemplate.getSqlSessionFactory() : null;
}
public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
this.sqlSessionTemplate = sqlSessionTemplate;
}
public SqlSession getSqlSession() {
return this.sqlSessionTemplate;
}
public SqlSessionTemplate getSqlSessionTemplate() {
return this.sqlSessionTemplate;
}
protected void checkDaoConfig() {
Assert.notNull(this.sqlSessionTemplate, "Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required");
}
}
【代码解说】
- SqlSessionDaoSupport装配SqlSessionFactory时,会创建SqlSessionTemplate并赋值;也就是MapperFactoryBean初始化时会调用setSqlSessionFactory(…)方法注入SqlSessionFactory; 注入前,会调用createSqlSessionTemplate()创建 SqlSessionTemplate并注入;
【2】MapperScannerConfigurer-映射器扫描配置器
- MapperScannerConfigurer作用:使用MapperScannerConfigurer,扫描特定包,自动成批创建映射器Mapper,而无需单个单个创建业务Mapper,如UserMapper,就可以删除单个配置业务Mapper的bean定义xml代码 ;
【2.1】MapperScannerConfigurer的bean定义配置
文件 spring-mybatis-beans-mapperscan.xml 中有关于MapperScannerConfigurer的配置,如下。
<!-- 使用MapperScannerConfigurer,扫描特定包,自动成批创建映射器Mapper -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.tom.srccode.deep.analysis.chapter9" />
<property name="processPropertyPlaceHolders" value="true" />
</bean>
注意:processPropertyPlaceHolders=true表示开启占位符替换;
配置了 MapperScannerConfigurrer后, 就可以删除UseMapper的配置了。
<!-- userMapper的bean定义代码,可以删除;因为MapperScannerConfigurer可以自动扫描basePackage下的Mapper接口并自动注册 -->
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="com.tom.srccode.deep.analysis.chapter9.UserMapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
【2.2】MapperScannerConfigurer的类层次结构
- MapperScannerConfigurer类继承结构:
public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware {
// ...
public void afterPropertiesSet() throws Exception {
Assert.notNull(this.basePackage, "Property 'basePackage' is required");
}
}
【代码解说】InitializingBean的实现类的afterPropertiesSet方法,没有做任何事情,忽略;
下面,本文主要关注 BeanDefinitionRegistryPostProcessor 对MapperScannerConfigurer的作用;
【2.2.1】BeanDefinitionRegistryPostProcessor-bean定义注册器后置处理器
【BeanDefinitionRegistryPostProcessor】继承结构
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
default void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// do nothing.
}
}
public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
【代码解说】综上, 本文主要关注postProcessBeanDefinitionRegistry,也就是重点关注 MapperScannerConfigurer 的postProcessBeanDefinitionRegistry方法;
【2.2.2】MapperScannerConfigurer 的postProcessBeanDefinitionRegistry方法
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
if (this.processPropertyPlaceHolders) {
// 占位符的属性处理
this.processPropertyPlaceHolders();
}
ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry, this.getEnvironment());
scanner.setAddToConfig(this.addToConfig);
scanner.setAnnotationClass(this.annotationClass);
scanner.setMarkerInterface(this.markerInterface);
scanner.setExcludeFilters(this.excludeFilters = this.mergeExcludeFilters());
scanner.setSqlSessionFactory(this.sqlSessionFactory);
scanner.setSqlSessionTemplate(this.sqlSessionTemplate);
scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName);
scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName);
scanner.setResourceLoader(this.applicationContext);
scanner.setBeanNameGenerator(this.nameGenerator);
scanner.setMapperFactoryBeanClass(this.mapperFactoryBeanClass);
if (StringUtils.hasText(this.lazyInitialization)) {
scanner.setLazyInitialization(Boolean.parseBoolean(this.lazyInitialization));
}
if (StringUtils.hasText(this.defaultScope)) {
scanner.setDefaultScope(this.defaultScope);
}
// 注册过滤器,定义规则,用于扫描时找出满足规则的bean; 因为scanner是扫描所有bean,需要根据一定规则筛选出Mapper接口的bean
scanner.registerFilters();
// 扫描basePackage指定包名下的mapper接口
scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ",; \t\n"));
}
// 处理属性占位符
private void processPropertyPlaceHolders() {
// 获取所有实现了 PropertyResourceConfigurer 的接口的bean的map,其中key为beanName,value为PropertyResourceConfigurer实现类bean
Map<String, PropertyResourceConfigurer> prcs = this.applicationContext.getBeansOfType(PropertyResourceConfigurer.class, false, false);
if (!prcs.isEmpty() && this.applicationContext instanceof ConfigurableApplicationContext) {
BeanDefinition mapperScannerBean = ((ConfigurableApplicationContext)this.applicationContext).getBeanFactory().getBeanDefinition(this.beanName);
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
factory.registerBeanDefinition(this.beanName, mapperScannerBean);
for(PropertyResourceConfigurer prc : prcs.values()) {
prc.postProcessBeanFactory(factory);
}
PropertyValues values = mapperScannerBean.getPropertyValues();
this.basePackage = this.getPropertyValue("basePackage", values);
this.sqlSessionFactoryBeanName = this.getPropertyValue("sqlSessionFactoryBeanName", values);
this.sqlSessionTemplateBeanName = this.getPropertyValue("sqlSessionTemplateBeanName", values);
this.lazyInitialization = this.getPropertyValue("lazyInitialization", values);
this.defaultScope = this.getPropertyValue("defaultScope", values);
this.rawExcludeFilters = this.getPropertyValueForTypeFilter("rawExcludeFilters", values);
}
Optional var10001 = Optional.ofNullable(this.basePackage);
Environment var10002 = this.getEnvironment();
Objects.requireNonNull(var10002);
this.basePackage = (String)var10001.map(var10002::resolvePlaceholders).orElse((Object)null);
var10001 = Optional.ofNullable(this.sqlSessionFactoryBeanName);
var10002 = this.getEnvironment();
Objects.requireNonNull(var10002);
this.sqlSessionFactoryBeanName = (String)var10001.map(var10002::resolvePlaceholders).orElse((Object)null);
var10001 = Optional.ofNullable(this.sqlSessionTemplateBeanName);
var10002 = this.getEnvironment();
Objects.requireNonNull(var10002);
this.sqlSessionTemplateBeanName = (String)var10001.map(var10002::resolvePlaceholders).orElse((Object)null);
var10001 = Optional.ofNullable(this.lazyInitialization);
var10002 = this.getEnvironment();
Objects.requireNonNull(var10002);
this.lazyInitialization = (String)var10001.map(var10002::resolvePlaceholders).orElse((Object)null);
var10001 = Optional.ofNullable(this.defaultScope);
var10002 = this.getEnvironment();
Objects.requireNonNull(var10002);
this.defaultScope = (String)var10001.map(var10002::resolvePlaceholders).orElse((Object)null);
}
【代码解说】
-
this.applicationContext.getBeansOfType(PropertyResourceConfigurer.class, false, false): 获取spring容器中class=PropertyResourceConfigurer.class的所有bean,其中key为beanName, value为bean实例;
-
postProcessBeanDefinitionRegistry()方法内部最后会调用scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, “,; \t\n”));
- 有代码可知,scanner的类型为 ClassPathMapperScanner ;
【ClassPathMapperScanner#scan()方法】 扫描给定路径的Mapper接口
public int scan(String... basePackages) {
int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
// 调用doScan()方法执行实际扫描
this.doScan(basePackages);
if (this.includeAnnotationConfig) {
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
return this.registry.getBeanDefinitionCount() - beanCountAtScanStart;
}
调用ClassPathMapperScanner.doScan(basePackages);
注意: ClassPathMapperScanner的父类super是 ClassPathBeanDefinitionScanner ;
public Set<BeanDefinitionHolder> doScan(String... basePackages) {
// 调用super父类的doScan方法, 父类是 ClassPathBeanDefinitionScanner
Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);
if (beanDefinitions.isEmpty()) {
if (this.printWarnLogIfNotFoundMappers) {
LOGGER.warn(() -> "No MyBatis mapper was found in '" + Arrays.toString(basePackages) + "' package. Please check your configuration.");
}
} else {
// 处理Mapper的bean定义
this.processBeanDefinitions(beanDefinitions);
}
return beanDefinitions;
}
调用 ClassPathBeanDefinitionScanner#doScan()方法, 接着调用ClassPathMapperScanner#processBeanDefinitions() 方法处理bean定义;
第1步:先分析 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) {
for(BeanDefinition candidate : this.findCandidateComponents(basePackage)) {
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition abstractBeanDefinition) {
this.postProcessBeanDefinition(abstractBeanDefinition, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition annotatedBeanDefinition) {
AnnotationConfigUtils.processCommonDefinitionAnnotations(annotatedBeanDefinition);
}
if (this.checkCandidate(beanName, candidate)) {
// 创建bean定义持有器
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
this.registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
【代码解说】 doScan()方法的作用: 根据给定pacakge路径扫描到满足规则的Mapper,并创建该Mapper的BeanDefinition;
第2步:调用ClassPathMapperScanner#processBeanDefinitions() 方法处理bean定义;
private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {
BeanDefinitionRegistry registry = this.getRegistry();
for(BeanDefinitionHolder holder : beanDefinitions) {
AbstractBeanDefinition definition = (AbstractBeanDefinition)holder.getBeanDefinition();
boolean scopedProxy = false;
if (ScopedProxyFactoryBean.class.getName().equals(definition.getBeanClassName())) {
definition = (AbstractBeanDefinition)Optional.ofNullable(((RootBeanDefinition)definition).getDecoratedDefinition()).map(BeanDefinitionHolder::getBeanDefinition).orElseThrow(() -> new IllegalStateException("The target bean definition of scoped proxy bean not found. Root bean definition[" + String.valueOf(holder) + "]"));
scopedProxy = true;
}
String beanClassName = definition.getBeanClassName();
LOGGER.debug(() -> {
String var10000 = holder.getBeanName();
return "Creating MapperFactoryBean with name '" + var10000 + "' and '" + beanClassName + "' mapperInterface";
});
definition.getConstructorArgumentValues().addGenericArgumentValue(beanClassName);
try {
// 为bean定义新增属性,如 factoryBeanObjectType=beanClass,beanClass就是Mapper接口class;
// 新增属性mapperInterface, 值同样也是 mapperInterface
Class<?> beanClass = Resources.classForName(beanClassName);
definition.setAttribute("factoryBeanObjectType", beanClass);
definition.getPropertyValues().add("mapperInterface", beanClass);
} catch (ClassNotFoundException var10) {
}
// ********** 这行代码非常重要,设置BeanClass为 mapperFactoryBeanClass,其值为MapperFactoryBean的clazz
definition.setBeanClass(this.mapperFactoryBeanClass);
definition.getPropertyValues().add("addToConfig", this.addToConfig);
boolean explicitFactoryUsed = false;
if (StringUtils.hasText(this.sqlSessionFactoryBeanName)) {
definition.getPropertyValues().add("sqlSessionFactory", new RuntimeBeanReference(this.sqlSessionFactoryBeanName));
explicitFactoryUsed = true;
} else if (this.sqlSessionFactory != null) {
definition.getPropertyValues().add("sqlSessionFactory", this.sqlSessionFactory);
explicitFactoryUsed = true;
}
if (StringUtils.hasText(this.sqlSessionTemplateBeanName)) {
if (explicitFactoryUsed) {
LOGGER.warn(() -> "Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored.");
}
definition.getPropertyValues().add("sqlSessionTemplate", new RuntimeBeanReference(this.sqlSessionTemplateBeanName));
explicitFactoryUsed = true;
} else if (this.sqlSessionTemplate != null) {
if (explicitFactoryUsed) {
LOGGER.warn(() -> "Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored.");
}
新增属性 sqlSessionTemplate
definition.getPropertyValues().add("sqlSessionTemplate", this.sqlSessionTemplate);
explicitFactoryUsed = true;
}
if (!explicitFactoryUsed) {
LOGGER.debug(() -> "Enabling autowire by type for MapperFactoryBean with name '" + holder.getBeanName() + "'.");
definition.setAutowireMode(2);
}
definition.setLazyInit(this.lazyInitialization);
if (!scopedProxy) {
if ("singleton".equals(definition.getScope()) && this.defaultScope != null) {
definition.setScope(this.defaultScope);
}
if (!definition.isSingleton()) {
BeanDefinitionHolder proxyHolder = ScopedProxyUtils.createScopedProxy(holder, registry, true);
if (registry.containsBeanDefinition(proxyHolder.getBeanName())) {
registry.removeBeanDefinition(proxyHolder.getBeanName());
}
registry.registerBeanDefinition(proxyHolder.getBeanName(), proxyHolder.getBeanDefinition());
}
}
}
}
【代码解说】 definition.setBeanClass(this.mapperFactoryBeanClass): 这行代码非常重要,this.mapperFactoryBeanClass值为 MapperFactoryBean ;
【3】AbstractApplicationContext-invokeBeanFactoryPostProcessors()作用及源码分析
- AbstractApplicationContext-invokeBeanFactoryPostProcessors()方法作用: spring启动时,解析BeanDefinition,并将其注册到BeanFactory; 然后执行AbstractApplicationContext-invokeBeanFactoryPostProcessors(),该方法会执行所有 BeanDefinitionRegistryPostProcessor实现类bean的postProcessBeanDefinitionRegistry方法,然后再执行所有BeanFactoryPostProcessor实现类bean的postProcessBeanFactory()方法;
- 调用 BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry方法;
- 作用: 在 BeanDefinition 加载完成后、BeanFactoryPostProcessor 执行之前,可以动态注册、删除或修改 BeanDefinition;如 MapperScannerConfigurer根据basePackage解析Mapper并注册Mapper定义到spring容器; 【可以注册,删除,修改BeanDefinition】
- BeanDefinitionRegistryPostProcessor-BeanDefinition注册后置处理器的实现类举例:
- MapperScannerConfigurer: 负责扫描Mapper并注册Mapper bean,key为Mapper接口clazz,value为MapperFactoryBean;
- ConfigurationClassPostProcessor:解析@Configuration注解,扫描 @Bean, @Import, @ComponentScan,@PropertySource注释;
- 调用 BeanFactoryPostProcessor#postProcessBeanFactory() 方法;
- BeanFactoryPostProcessor-Bean工厂后置处理器的作用: 在 Spring 实例化任何 Bean 之前,修改 Bean 的定义(BeanDefinition),而不是修改 Bean 对象本身;【仅可以删除BeanDefinition】
- 执行BeanFactoryPostProcessor#postProcessBeanFactory() 方法修改BeanDefinition属性;属性包括:beanName,beanClass,scope,lazyInit,constructor,propertyValues,initMethod,destroyMethod;
- BeanFactoryPostProcessor-bean工厂后置处理器的实现类举例:
- PropertySourcesPlaceholderConfigurer: 属性源占位符配置器;
- BeanFactoryPostProcessor-Bean工厂后置处理器的作用: 在 Spring 实例化任何 Bean 之前,修改 Bean 的定义(BeanDefinition),而不是修改 Bean 对象本身;【仅可以删除BeanDefinition】
- 调用 BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry方法;
【3.1】背景
- 由 MapperScannerConfigurer 的postProcessBeanDefinitionRegistry()方法的调用入口, 扩展出 BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry方法调用入口,如下:
- AbstractApplicationContext#refresh() -> this.invokeBeanFactoryPostProcessors(beanFactory) -> PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(…) 方法, 如下:
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, this.getBeanFactoryPostProcessors());
if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null && beanFactory.containsBean("loadTimeWeaver")) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
接着,本文分析PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, this.getBeanFactoryPostProcessors())源码;
【3.2】调用Bean工厂后置处理器
- PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(): 调用Bean工厂后置处理器
【PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()】这段代码,看似复杂,但实际逻辑简单,本文下面进行分析;
public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
Set<String> processedBeans = new HashSet();
// beanFactory 实现类 BeanDefinitionRegistry,所以为true
if (beanFactory instanceof BeanDefinitionRegistry registry) {
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList();
// 传入的postProcessor为null,所以不进入
for(BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor registryProcessor) {
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
} else {
regularPostProcessors.add(postProcessor);
}
}
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList();
// 获取 BeanDefinitionRegistryPostProcessor 类型的bean名称
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for(String ppName : postProcessorNames) {
// 【步骤1】筛选出 实现 PriorityOrdered 接口的BeanDefinitionRegistryPostProcessor类型的bean
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add((BeanDefinitionRegistryPostProcessor)beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
// 对实现了 PriorityOrdered接口的 BeanDefinitionRegistryPostProcessor进行优先调用
// 因为 PriorityOrdered ,顾名思义就是 优先级排序接口,它比Ordered的实现类要优先调用
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// 调用【步骤1】筛选出的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for(String ppName : postProcessorNames) {
// 【步骤2】筛选出 实现 Ordered 接口的 BeanDefinitionRegistryPostProcessor 类型的bean
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add((BeanDefinitionRegistryPostProcessor)beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
// 对 Ordered接口的 BeanDefinitionRegistryPostProcessor进行排序并调用
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// 调用【步骤2】筛选出的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();
boolean reiterate = true;
while(reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for(String ppName : postProcessorNames) {
// 【步骤3】筛选出 没有实现 Ordered 接口且没有实现PriorityOrdered接口的 BeanDefinitionRegistryPostProcessor 类型的bean
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add((BeanDefinitionRegistryPostProcessor)beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
// 排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// 调用【步骤3】筛选出的 BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();
}
invokeBeanFactoryPostProcessors((Collection)registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors((Collection)regularPostProcessors, beanFactory);
} else {
invokeBeanFactoryPostProcessors((Collection)beanFactoryPostProcessors, beanFactory);
}
// 我是分割线:至此,BeanDefinitionRegistryPostProcessor所有bean的postProcessBeanDefinitionRegistry方法调用完成
// 找出 类型为 BeanFactoryPostProcessor 的 beanName数组
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList();
List<String> orderedPostProcessorNames = new ArrayList();
List<String> nonOrderedPostProcessorNames = new ArrayList();
for(String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
// 【步骤4】筛选实现 PriorityOrdered接口的 BeanFactoryPostProcessor
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add((BeanFactoryPostProcessor)beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
} else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
// 【步骤5】筛选实现 Ordered接口的 BeanFactoryPostProcessor
orderedPostProcessorNames.add(ppName);
} else {
// 【步骤6】筛选没有实现 PriorityOrdered且没有实现 Ordered接口的 BeanFactoryPostProcessor
nonOrderedPostProcessorNames.add(ppName);
}
}
}
// 排序
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
// 调用【步骤4】筛选出的 BeanFactoryPostProcessor 的 postProcessBeanFactory 方法
invokeBeanFactoryPostProcessors((Collection)priorityOrderedPostProcessors, beanFactory);
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList(orderedPostProcessorNames.size());
for(String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add((BeanFactoryPostProcessor)beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
// 调用【步骤5】筛选出的 BeanFactoryPostProcessor 的 postProcessBeanFactory 方法
invokeBeanFactoryPostProcessors((Collection)orderedPostProcessors, beanFactory);
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList(nonOrderedPostProcessorNames.size());
for(String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add((BeanFactoryPostProcessor)beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
// 调用【步骤6】筛选出的 BeanFactoryPostProcessor 的 postProcessBeanFactory 方法
invokeBeanFactoryPostProcessors((Collection)nonOrderedPostProcessors, beanFactory);
beanFactory.clearMetadataCache();
}
【补充】关于 PriorityOrdered接口, Ordered接口定义:
// 优先有序接口
public interface PriorityOrdered extends Ordered {
}
// 有序接口
public interface Ordered {
int HIGHEST_PRECEDENCE = Integer.MIN_VALUE;
int LOWEST_PRECEDENCE = Integer.MAX_VALUE;
int getOrder();
}
【4】总结
【4.1】(非常重要)总结:调用BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry()方法与BeanFactoryPostProcessor 的 postProcessBeanFactory()方法总结
-
调用入口: PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()
- 该方法有两个作用:
- 调用 BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry()方法;
- 调用 BeanFactoryPostProcessor 的 postProcessBeanFactory()方法;
- 该方法有两个作用:
-
调用 BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry()方法的步骤:
- 【步骤1】筛选出 实现 PriorityOrdered 接口的BeanDefinitionRegistryPostProcessor类型的bean,并根据排序策略排序,按照顺序执行其postProcessBeanDefinitionRegistry方法;
- 【步骤2】筛选出 实现 Ordered 接口的 BeanDefinitionRegistryPostProcessor 类型的bean, 并根据排序策略排序,按照顺序执行其postProcessBeanDefinitionRegistry方法;
- 【步骤3】筛选出 没有实现 PriorityOrdered接口且没有实现 Ordered 接口 的 BeanDefinitionRegistryPostProcessor 类型的bean, 并根据排序策略排序,按照顺序执行其postProcessBeanDefinitionRegistry方法;
-
调用 BeanFactoryPostProcessor 的 postProcessBeanFactory()方法的步骤:
- 【步骤4】筛选 实现 PriorityOrdered接口 的 BeanFactoryPostProcessor类型的bean,并根据排序策略排序,按照顺序执行其 postProcessBeanFactory()方法;
- 【步骤5】筛选 实现 Ordered接口 的 BeanFactoryPostProcessor类型的bean,并根据排序策略排序,按照顺序执行其 postProcessBeanFactory()方法;
- 【步骤6】筛选 没有实现 PriorityOrdered接口且没有实现 Ordered接口 的 BeanFactoryPostProcessor类型的bean,并根据排序策略排序,按照顺序执行其 postProcessBeanFactory()方法;
【注意】上述过程的调用,都是在bean实例化前,因为:
- BeanDefinitionRegistryPostProcessor的作用:在 BeanDefinition 加载完成后、BeanFactoryPostProcessor 执行之前,可以动态注册、删除或修改 BeanDefinition,是在bean实例化前;
- BeanFactoryPostProcessor的作用:在 Spring 实例化任何 Bean 之前,修改 Bean 的定义(BeanDefinition),而不是修改 Bean 对象本身
【4.2】BeanDefinitionRegistryPostProcessor与BeanFactoryPostProcessor使用总结
- 调用入口: spring启动时,解析BeanDefinition,并将其注册到BeanFactory; 然后执行AbstractApplicationContext-invokeBeanFactoryPostProcessors(),该方法会执行所有 BeanDefinitionRegistryPostProcessor实现类bean的postProcessBeanDefinitionRegistry方法,然后再执行所有BeanFactoryPostProcessor实现类bean的postProcessBeanFactory()方法;
- 也就是说:BeanDefinitionRegistryPostProcessor比BeanFactoryPostProcessor执行得早 ;
- 使用场景:
- BeanDefinitionRegistryPostProcessor使用场景:在 BeanDefinition 加载完成后、BeanFactoryPostProcessor 执行之前,可以动态注册、删除或修改 BeanDefinition。它是 Spring 向容器动态添加 Bean 的核心扩展点;它是 Spring 底层大量功能(如 @Configuration、@Value、占位符解析等)的基础;
- BeanFactoryPostProcessor使用场景: 在所有BeanDefinitionRegistryPostProcessor实现类bean#postProcessBeanDefinitionRegistry方法执行后,在 Spring 实例化任何 Bean 之前,修改 Bean 定义(BeanDefinition),而不是修改 Bean 对象本身。
- 两者区别与联系:
- 区别:BeanDefinitionRegistryPostProcessor可以注册,修改,修改BeanDefinition; 而BeanFactoryPostProcessor只能修改BeanDefinition;
- 联系: BeanDefinitionRegistryPostProcessor 继承自 BeanFactoryPostProcessor,可以重写后者的postProcessBeanFactory方法;
- 所以BeanDefinitionRegistryPostProcessor会被执行两次:
- 第1次,执行其postProcessBeanDefinitionRegistry方法;【可以动态注册,删除,修改BeanDefinition】
- 第2次,执行其postProcessBeanFactory方法; 【仅可以动态修改BeanDefinition属性,属性包括:beanName,beanClass,scope,lazyInit,constructor,propertyValues,initMethod,destroyMethod】
- BeanDefinitionRegistryPostProcessor与BeanFactoryPostProcessor的执行顺序:
读取配置(XML、注解)
│
▼
解析 BeanDefinition
│
▼
注册 BeanDefinition 到 BeanDefinitionRegistry
│
▼
★★★★★ BeanDefinitionRegistryPostProcessor #postProcessBeanDefinitionRegistry()方法★★★★★
│
▼
★★★★★ BeanFactoryPostProcessor #postProcessBeanFactory()方法 ★★★★★
│
▼
实例化 Bean
│
▼
BeanPostProcessor
│
▼
初始化 Bean
【4.2.1】BeanDefinitionRegistryPostProcessor使用场景(注册,删除,修改BeanDefinition)
public class TomBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
// 注册bean定义,以便spring后续对该bean实例化与初始化
BeanDefinition bd = BeanDefinitionBuilder.genericBeanDefinition(DiyUserServiceManualRegistry.class).getBeanDefinition();
registry.registerBeanDefinition("diyUserServiceManualRegistry", bd);
// 删除BeanDefinition
registry.removeBeanDefinition("diyUserServiceManualRegistry2");
// 修改BeanDefinition属性,属性包括:beanName,beanClass,scope,lazyInit,constructor,propertyValues,initMethod,destroyMethod
bd.setPrimary(true);
}
}
bean.xml文件定义TomBeanDefinitionRegistryPostProcessor ;
<!-- 自定义BeanDefinition注册后置处理器 -->
<bean class="com.tom.srccode.deep.analysis.chapter9.beanfactorypostprocessor.TomBeanDefinitionRegistryPostProcessor" />
【测试案例】
@Test
public void test5() {
ApplicationContext context = new ClassPathXmlApplicationContext("a_src_deep_analysis/chapter9/spring-mybatis-beans-mapperscan.xml");
DiyUserServiceManualRegistry bean = context.getBean(DiyUserServiceManualRegistry.class);
log.info(" DiyUserServiceManualRegistry = {}", bean);
}
【打印结果】
com.tom.srccode.deep.analysis.chapter9.beanfactorypostprocessor.DiyUserServiceManualRegistry - DiyUserServiceManualRegistry: 构造器被调用
com.tom.srccode.deep.analysis.chapter9.SpringMybatisIntegrateUnitTest - DiyUserServiceManualRegistry = com.tom.srccode.deep.analysis.chapter9.beanfactorypostprocessor.DiyUserServiceManualRegistry@6865c751
【4.2.2】BeanFactoryPostProcessor使用场景(修改BeanDefinition)
参见: PropertySourcesPlaceholderConfigurer-属性源占位符配置器
public class PropertySourcesPlaceholderConfigurer extends PlaceholderConfigurerSupport implements EnvironmentAware {
//...
}
public abstract class PlaceholderConfigurerSupport extends PropertyResourceConfigurer implements BeanNameAware, BeanFactoryAware {
//...
}
// 显然,由传递性可知,PropertySourcesPlaceholderConfigurer是BeanFactoryPostProcessor实现类
public abstract class PropertyResourceConfigurer extends PropertiesLoaderSupport implements BeanFactoryPostProcessor, PriorityOrdered {
//...
}
更多推荐



所有评论(0)