MapperScannerConfigurer执行流程

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;
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值