MapperScannerConfigurer执行流程:
一、spring启动
ContextLoaderListener
->initWebApplicationContext 调用
父类 ContextLoader initWebApplicationContext 方法中 configureAndRefreshWebApplicationContext 调用 refresh
二、MapperScannerConfigurer在spring启动时的加载时机
refresh
->invokeBeanFactoryPostProcessors 中循环执行所有实现BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry
MapperScannerConfigurer 实现 BeanDefinitionRegistryPostProcessor
会执行 postProcessBeanDefinitionRegistry 中的 ClassPathMapperScanner 中 scan 方法。
ClassPathMapperScanner 继承了 ClassPathBeanDefinitionScanner 先执行父类中的 scan。
父类scan 中 调用 doScan 方法,此方法在ClassPathMapperScanner被重写所以进入ClassPathMapperScanner 的doScan,
在ClassPathMapperScanner的doScan中先调用父类的doScan,然后循环父类返回的 Set 集合。
把扫描到的dao全类名和对象类型放入到definition 并返回。
definition.getPropertyValues().add(“mapperInterface”, definition.getBeanClassName());//要创建bean的全类名
definition.setBeanClass(MapperFactoryBean.class);//创建bean的类型
扫描到的Mapper接口设置为mapperFactoryBean类型, AutowireMode 设置为2。
definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
三、dao创建过程
创建Service时,service中@Autowired xxxdao
AutowiredAnnotationBeanPostProcessor
->postProcessPropertyValues
->inject
->beanFactory.resolveDependency
->getBean
->doGetBean
->createBean
->doCreateBean
->createBeanInstance
在populateBean中给xxxdao中的属性赋值。
调用方法applyPropertyValues传入pvs(PropertyValues类型)给对象属性赋值。给xxxdao中sqlsessionFactory赋值。
以上是bean创建并给dao中sqlsessionfactory属性赋值。
以下是把创建好的MapperFactoryBean放入到configuretion
->initializeBean
->invokeInitMethods
执行 DaoSupport
->afterPropertiesSet
—>checkDaoConfig
MapperFactoryBean 继承了SqlSessionDaoSupport 继承了 DaoSupport
所以调用MapperFactoryBean中checkDaoConfig
if (this.addToConfig && !configuration.hasMapper(this.mapperInterface))
先判断configuration中是否有这个Mapper。如果已有则不执行下面。
Configuration configuration = this.getSqlSession().getConfiguration();
configuration.addMapper(this.mapperInterface);
——> this.mapperRegistry.addMapper(type);
创建代理类放入到knownMappers
-> this.knownMappers.put(type, new MapperProxyFactory(type));
类创建成功后,调用getObject方法,获取knownMappers中MapperProxyFactory,返回代理MapperPoxy,获取MapperPoxy最后返回。
注意:在SqlSessionFactoryBean中也会有addMapper,从执行顺序上SqlSessionFactoryBean先执行。MapperFactoryBean的checkDaoConfig判断configuration中是否有这个Mapper,如果没有则
addMapper执行。
SqlSessionFactoryBean
->afterPropertiesSet ->buildSqlSessionFactory
-> xmlMapperBuilder.parse();
->bindMapperForNamespace
this.configuration.addMapper(boundType);
四、dao获取过程
创建dao 后调用getObjectForBeanInstance,最后MapperFactoryBean 中的getObject
在自动注入给某个组件属性赋值的时候获取
this.getSqlSession().getMapper(this.mapperInterface);
->defaultSqlSession this.configuration.getMapper(type, this);
——》Configuration mapperRegistry.getMapper(type, sqlSession);
->MapperRegistry 获取代理类从 knownMappers
MapperProxyFactory mapperProxyFactory = (MapperProxyFactory)this.knownMappers.get(type);
return mapperProxyFactory.newInstance(sqlSession);
代理成 MapperProxy
五、dao执行过程
MapperProxy
执行代理方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (Object.class.equals(method.getDeclaringClass())) {
try {
return method.invoke(this, args);
} catch (Throwable var5) {
throw ExceptionUtil.unwrapThrowable(var5);
}
} else {
MapperMethod mapperMethod = this.cachedMapperMethod(method);
return mapperMethod.execute(this.sqlSession, args);
}
执行mapperMethod.execute判断需要执行增、删、改、查操作
public Object execute(SqlSession sqlSession, Object[] args) {
Object param;
Object result;
if (SqlCommandType.INSERT == this.command.getType()) {
param = this.method.convertArgsToSqlCommandParam(args);
result = this.rowCountResult(sqlSession.insert(this.command.getName(), param));
} else if (SqlCommandType.UPDATE == this.command.getType()) {
param = this.method.convertArgsToSqlCommandParam(args);
result = this.rowCountResult(sqlSession.update(this.command.getName(), param));
} else if (SqlCommandType.DELETE == this.command.getType()) {
param = this.method.convertArgsToSqlCommandParam(args);
result = this.rowCountResult(sqlSession.delete(this.command.getName(), param));
} else {
if (SqlCommandType.SELECT != this.command.getType()) {
throw new BindingException("Unknown execution method for: " + this.command.getName());
}
if (this.method.returnsVoid() && this.method.hasResultHandler()) {
this.executeWithResultHandler(sqlSession, args);
result = null;
} else if (this.method.returnsMany()) {
result = this.executeForMany(sqlSession, args);
} else if (this.method.returnsMap()) {
result = this.executeForMap(sqlSession, args);
} else {
param = this.method.convertArgsToSqlCommandParam(args);
result = sqlSession.selectOne(this.command.getName(), param);
}
}
if (result == null && this.method.getReturnType().isPrimitive() && !this.method.returnsVoid()) {
throw new BindingException("Mapper method '" + this.command.getName() + " attempted to return null from a method with a primitive return type (" + this.method.getReturnType() + ").");
} else {
return result;
}
}