浅析mybatisPlus启动流程

文中都是与mybatis-spring比较,与之相同之处,本文不再赘述。
对于启动流程不清楚的,可参考浅析MybatisAutoConfiguration流程

1. MybatisPlusAutoConfiguration

区别MybatisAutoConfiguration:

  1. 类注解部分引入的配置类换成了MybatisPlus定义的。
  2. afterPropertiesSet方法多了一步设置自定义配置的过程
  3. sqlSessionFactory内部变更,使用MybatisSqlSessionFactoryBean替代MybatisSessionFactoryBean
@Configuration
@ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class})
@ConditionalOnSingleCandidate(DataSource.class)
@EnableConfigurationProperties(MybatisPlusProperties.class)
@AutoConfigureAfter({DataSourceAutoConfiguration.class, MybatisPlusLanguageDriverAutoConfiguration.class})
public class MybatisPlusAutoConfiguration implements InitializingBean {

	@Override
    public void afterPropertiesSet() {
    	// 这里可以实现自定义操作,例如设置主键生成策略
        if (!CollectionUtils.isEmpty(mybatisPlusPropertiesCustomizers)){
            mybatisPlusPropertiesCustomizers.forEach(i -> i.customize(properties));
        }
        checkConfigFileExists();
    }
    
    @Bean
    @ConditionalOnMissingBean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        // 使用 MybatisSqlSessionFactoryBean 而不是 SqlSessionFactoryBean
        MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean();
        // 省略常规配置
        .......
        // 此处必为非 NULL
        GlobalConfig globalConfig = this.properties.getGlobalConfig();
        // 注入填充器
        this.getBeanThen(MetaObjectHandler.class, globalConfig::setMetaObjectHandler);
        // 注入主键生成器
        this.getBeanThen(IKeyGenerator.class, i -> globalConfig.getDbConfig().setKeyGenerator(i));
        // 注入sql注入器
        this.getBeanThen(ISqlInjector.class, globalConfig::setSqlInjector);
        // 注入ID生成器
        this.getBeanThen(IdentifierGenerator.class, globalConfig::setIdentifierGenerator);
        // 设置 GlobalConfig 到 MybatisSqlSessionFactoryBean
        factory.setGlobalConfig(globalConfig);
        return factory.getObject();
    }
}

2.MybatisMapperAnnotationBuilder

MybatisSqlSessionFactoryBean的buildSqlSessionFactory方法类似,这里就不重复说明了。
沿着MybatisSqlSessionFactoryBean调用顺序(如下图),直接看MybatisMapperAnnotationBuilder的parse方法。
MybatisMapperAnnotationBuilder.parse方法是在

对应于MapperAnnotationBuilder用于解析dao接口上的注解等信息,MybatisMapperAnnotationBuilder不仅实现上述功能,而且再这里注入了通用的crud操作。

public class MybatisMapperAnnotationBuilder extends MapperAnnotationBuilder {

 	@Override
    public void parse() {
        String resource = type.toString();
        if (!configuration.isResourceLoaded(resource)) {
        	// 解析dao接口对应的xml文件,如果解析过则略过
            loadXmlResource();
            // 标识解析过资源了
            configuration.addLoadedResource(resource);
            final String typeName = type.getName();
            assistant.setCurrentNamespace(typeName);
            parseCache();
            parseCacheRef();
            SqlParserHelper.initSqlParserInfoCache(type);
            Method[] methods = type.getMethods();
            // 解析方法上的注解
            for (Method method : methods) {
                try {
                    if (!method.isBridge()) {
                        parseStatement(method);
                        SqlParserHelper.initSqlParserInfoCache(typeName, method);
                    }
                } catch (IncompleteElementException e) {
                	// 解析失败的后面会再次尝试解析
                    configuration.addIncompleteMethod(new MybatisMethodResolver(this, method));
                }
            }
			// 重点 MybatisPuls 自动注入crud
            if (GlobalConfigUtils.isSupperMapperChildren(configuration, type)) {
                GlobalConfigUtils.getSqlInjector(configuration).inspectInject(assistant, type);
            }
        }
        parsePendingMethods();
    }
}

接着看看AbstractSqlInjector类inspectInject方法

public abstract class AbstractSqlInjector implements ISqlInjector {

    @Override
    public void inspectInject(MapperBuilderAssistant builderAssistant, Class<?> mapperClass) {
        Class<?> modelClass = extractModelClass(mapperClass);
        if (modelClass != null) {
            String className = mapperClass.toString();
            Set<String> mapperRegistryCache = GlobalConfigUtils.getMapperRegistryCache(builderAssistant.getConfiguration());
            if (!mapperRegistryCache.contains(className)) {
            	// 这里可以重写getMethodList,定制属于自己的通用方法
                List<AbstractMethod> methodList = this.getMethodList(mapperClass);
                if (CollectionUtils.isNotEmpty(methodList)) {
                	// 映射解析table信息
                    TableInfo tableInfo = TableInfoHelper.initTableInfo(builderAssistant, modelClass);
                    // 循环注入自定义方法
                    methodList.forEach(m -> m.inject(builderAssistant, mapperClass, modelClass, tableInfo));
                } else {
                    logger.debug(mapperClass.toString() + ", No effective injection method was found.");
                }
                mapperRegistryCache.add(className);
            }
        }
    }
}

MybatisPlus启动过程中,做的初始化操作主要是上面这些地方。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
eFuse是一种电子设备中的可编程保护元件,用于在系统启动时进行安全验证和防止非法访问。eFuse通常由一个可编程的多级存储器和一个比较器组成,用于存储和比较系统的安全配置信息。 eFuse在系统启动时起到了关键的安全保护作用。在系统开始启动之前,eFuse会被预编程以存储预先定义的安全配置信息,如设备的唯一标识符、启动密钥、数字签名等。在启动过程中,eFuse会将存储的安全配置信息与实际配置进行比较,以验证系统的完整性和安全性。 安全启动是通过eFuse实现的一种技术,它在系统启动过程中提供了一系列认证和验证步骤,以确保系统只能启动可信任的软件和固件。安全启动的目的是防止恶意软件和未经授权的访问,从而保护系统的安全性和机密性。 安全启动通常包括以下步骤:首先,系统在启动时会将eFuse中存储的安全配置信息读取到比较器中进行比较。如果比较结果是一致的,系统将继续启动。如果比较结果不一致,系统可能会中断启动或采取其他安全措施,如锁定设备或报警。 除了对比eFuse中的配置信息,安全启动还涉及其他安全检查,如签名验证、启动密钥的匹配等。通过这些多层次的安全认证,系统可以确保只有经过授权的软件和固件才能被加载和执行,从而保证系统的安全性。 总结起来,eFuse是一种可编程保护元件,用于存储和比较系统的安全配置信息。安全启动是通过eFuse实现的一种技术,通过认证和验证步骤保证系统只能启动可信任的软件和固件。通过eFuse和安全启动,系统可以提供更高的安全保护,防止非法访问和恶意软件的攻击。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值