public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware {
}
上面是一个精简版的MapperScannerConfigurer类源码。MapperScannerConfigurer实现了BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry()方法,从而可以在Bean定义好后,实例化前做一些事情(Spring加载Bean的几个步骤)。代码如下:
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
if (this.processPropertyPlaceHolders) {
processPropertyPlaceHolders();
}
ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
scanner.setAddToConfig(this.addToConfig);
scanner.setAnnotationClass(this.annotationClass);
scanner.setMarkerInterface(this.markerInterface);
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.registerFilters();
scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS));
}
/*
*把配置文件中的属性值设置到Bean对象中
*/
private void processPropertyPlaceHolders() {
//获取所有PropertyResourceConfigurer类的子类map
Map<String, PropertyResourceConfigurer> prcs = applicationContext.getBeansOfType(PropertyResourceConfigurer.class);
//如果PPropertyResourceConfigurer类的子类map不为空
if (!prcs.isEmpty() && applicationContext instanceof ConfigurableApplicationContext) {
//获取MapperScannerConfigurer类的BeanDefinition对象
BeanDefinition mapperScannerBean = ((ConfigurableApplicationContext) applicationContext)
.getBeanFactory().getBeanDefinition(beanName);
//构造一个DefaultListableBeanFactory 对象
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
//给MapperScannerConfigurer类的BeanDefinition对象模拟一个Spring环境
factory.registerBeanDefinition(beanName, mapperScannerBean);
//遍历所有PropertyResourceConfigurer类的子类并执行postProcessBeanFactory()方法
for (PropertyResourceConfigurer prc : prcs.values()) {
prc.postProcessBeanFactory(factory);
}
//取出执行结果
PropertyValues values = mapperScannerBean.getPropertyValues();
//更新属性
this.basePackage = updatePropertyValue("basePackage", values);
this.sqlSessionFactoryBeanName = updatePropertyValue("sqlSessionFactoryBeanName", values);
this.sqlSessionTemplateBeanName = updatePropertyValue("sqlSessionTemplateBeanName", values);
}
}
首先需要注意的是processPropertyPlaceHolders属性。当processPropertyPlaceHolders为true时,它会执行processPropertyPlaceHolders()方法。为什么需要注意这一点呢?这要从processPropertyPlaceHolders()方法的作用说起:BeanDefinitionRegistries会在应用启动的时候调用,并且会早于BeanFactoryPostProcessors的调用,这就意味着PropertiesResourceConfigurers还没有被加载所有对于属性文件的引用将会失效,为避免此种情况发生,此方法手动地找出定义的PropertyResourceConfigurers并进行调用以以保证对于属性的引用可以正常工作。换言之,对于Mybatis而言,此时,已经定义好Bean了,但是配置文件中的属性值还没有注入Bean中,实例化完成后Bean中的属性将会是空值。
其次,可以看到在postProcessBeanDefinitionRegistry()方法中构造了一个ClassPathMapperScanner对象并设置了很多属性值,最后调用了它的父类ClassPathBeanDefinitionScanner的scan()方法。
public int scan(String... basePackages) {
int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
doScan(basePackages);
// Register annotation config processors, if necessary.
if (this.includeAnnotationConfig) {
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
}
doScan()方法的实现在子类ClassPathMapperScanner中:
public Set<BeanDefinitionHolder> doScan(String... basePackages) {
//先调用父类方法扫描指定路径下文件得到所有的beanDefinitions
Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);
if (beanDefinitions.isEmpty()) {
logger.warn("No MyBatis mapper was found in '" + Arrays.toString(basePackages) + "' package. Please check your configuration.");
} else {
processBeanDefinitions(beanDefinitions);
}
return beanDefinitions;
}
/*
*模仿后处理器的行为执行processBeanDefinitions后处理方法()
*/
private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {
GenericBeanDefinition definition;
//遍历所有的BeanDefinition状态下的Mapper接口类
for (BeanDefinitionHolder holder : beanDefinitions) {
definition = (GenericBeanDefinition) holder.getBeanDefinition();
definition.getConstructorArgumentValues().addGenericArgumentValue(definition.getBeanClassName()); // issue #59
//修改BeanClass为mapperFactoryBean类从而在后续步骤获得代理类
definition.setBeanClass(this.mapperFactoryBean.getClass());
definition.getPropertyValues().add("addToConfig", this.addToConfig);
//把其他属性注入BeanDefinition对象中
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)) {
definition.getPropertyValues().add("sqlSessionTemplate", new RuntimeBeanReference(this.sqlSessionTemplateBeanName));
explicitFactoryUsed = true;
} else if (this.sqlSessionTemplate != null) {
definition.getPropertyValues().add("sqlSessionTemplate", this.sqlSessionTemplate);
explicitFactoryUsed = true;
}
if (!explicitFactoryUsed) {
definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
}
}
}
以上,就是MapperScannerConfigurer类将Mapper接口的Bean替换为代理类的全过程了。那么,是谁主导这一切的完成的呢?换言之,为什么说这一切是在Bean定义好后,实例化之前呢?接下来,我们温习一下Spring初始化的过程,AbstractApplicationContext类中的refresh()方法完成了Spring启动的核心步骤,代码如下:
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
我们知道,创建BeanFactory和加载BeanDefinition是在obtainFreshBeanFactory()方法中完成的。在这个阶段,Bean已经被定义为BeanDefinition了。在执行invokeBeanFactoryPostProcessors(beanFactory)方法的时候,会将所有的BeanFactoryPostProcessor接口实现类的postProcessBeanFactory()方法都调用一次。invokeBeanFactoryPostProcessors(beanFactory)的实现如下:
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
PostProcessorRegistrationDelegate的invokeBeanFactoryPostProcessors ()方法开头部分如下:
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
Set<String> processedBeans = new HashSet<>();
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<>();
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
}
}
在文章开头提到了MapperScannerConfigurer类实现了BeanDefinitionRegistryPostProcessor接口,源码如下。可以看到它继承了BeanFactoryPostProcessor 接口。因此,我们可以推断出MapperScannerConfigurer的postProcessBeanDefinitionRegistry()会在此时被优先执行。也就是请问您张中提到的Bean定义完成后,Bean实例化前。
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}