Mybatis源码--MapperScannerConfigurer类

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;
}

 


版权声明:本文为qq_28802119原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。