Mybatis整合Spring之MapperFactoryBean怎么拿到的SqlSessionFactory

  Mybatis整合Spring源码之前也分析过一次了,这次刚好脑袋灵光一闪,想出来一个在

     SqlSessionDaoSupport.setSqlSessionFactory  是什么时候调用的呢?

一  BeanDefinition

  每一个mapper接口都会被扫描成一个BeanDefinition,这个BD开始会被强制转成MapperFactoryBean类型,并

  ClassPathMapperScanner.processBeanDefinitions

private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {
    GenericBeanDefinition definition;
    for (BeanDefinitionHolder holder : beanDefinitions) {
      definition = (GenericBeanDefinition) holder.getBeanDefinition();

      if (logger.isDebugEnabled()) {
        logger.debug("Creating MapperFactoryBean with name '" + holder.getBeanName() 
          + "' and '" + definition.getBeanClassName() + "' mapperInterface");
      }

      // the mapper interface is the original class of the bean
      // but, the actual class of the bean is MapperFactoryBean
      definition.getConstructorArgumentValues().addGenericArgumentValue(definition.getBeanClassName()); // issue #59
      definition.setBeanClass(this.mapperFactoryBean.getClass());

      definition.getPropertyValues().add("addToConfig", this.addToConfig);

      boolean explicitFactoryUsed = false;
      if (StringUtils.hasText(this.sqlSessionFactoryBeanName)) {
        definition.getPropertyValues().add("sqlSessionFactory", new RuntimeBeanReference(this.sqlSessionFactoryBeanName));
        explicitFactoryUsed = true;

在这个BD中,mapper的原始类加入到构造方法入参,sqlSessioinFactory放进了bd的属性里

二 生效时机

  通过构造方法, Class<T> mapperInterface 被注入了

public class MapperFactoryBean<T> extends SqlSessionDaoSupport implements FactoryBean<T> {

  private Class<T> mapperInterface;

  private boolean addToConfig = true;

  public MapperFactoryBean() {
    //intentionally empty 
  }
  
  public MapperFactoryBean(Class<T> mapperInterface) {
    this.mapperInterface = mapperInterface;
  }

sqlSessioinFactory的注入在对bean的初始化的第二步

  

protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
        PropertyValues pvs = mbd.getPropertyValues();

        if (hasInstAwareBpps || needsDepCheck) {//这部分是对@AutoWired或者@Resource进行注入的
            PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
            if (hasInstAwareBpps) {
                for (BeanPostProcessor bp : getBeanPostProcessors()) {
                    if (bp instanceof InstantiationAwareBeanPostProcessor) {
                        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                        pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                        if (pvs == null) {
                            return;
                        }
                    }
                }
            }
            if (needsDepCheck) {
                checkDependencies(beanName, mbd, filteredPds, pvs);
            }
        }
     //走完了上面的代码后这个bean的@AutoWired或者@Resource的属性就已经注入完了
     applyPropertyValues(beanName, mbd, bw, pvs); //这个方法处理的是BeanDefinition里的静态属性,也就是BeanDefinition里已经写好了的属性
}

 applyPropertyValues 会对BD中的全部属性进行处理,我看了下调用还有点复杂,不过底层应该还是通过Field的反射接口

这样,我们就知道了sqlSessioinFactory是怎么注入的了

上一篇:SqlSession获取的工具类(简单配置)


下一篇:SSM-Mybatis-生命周期