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