1. 程式人生 > 實用技巧 >10.25

10.25

  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是怎麼注入的了