java解析yaml,MyBatis3源碼解析(8)MyBatis與Spring的結合

 2023-10-12 阅读 32 评论 0

摘要:簡介 在上幾篇文章中,解析了MyBatis的核心原理部分,我們大致對其有了一定的了解,接下來我們看看在日常的開發中MyBatis是如何與Spring框架結合的 源碼解析 在我們的日常開發中,使用Spring框架結合MyBatis,只需簡單的進行相關的配置,

簡介

在上幾篇文章中,解析了MyBatis的核心原理部分,我們大致對其有了一定的了解,接下來我們看看在日常的開發中MyBatis是如何與Spring框架結合的

源碼解析

在我們的日常開發中,使用Spring框架結合MyBatis,只需簡單的進行相關的配置,在代碼中使用注解即可輕松使用,而不用像下面示例中的,需要很多的代碼:

public class MybatisTest {// 從SqlSessionFactory中獲取Mapper進行使用@Testpublic void test() {try(SqlSession session = buildSqlSessionFactory().openSession()) {PersonMapper personMapper = session.getMapper(PersonMapper.class);personMapper.createTable();personMapper.save(Person.builder().id(1L).name(new String[]{"1", "2"}).build());personMapper.save(Person.builder().id(2L).name(new String[]{"1", "2"}).build());Map<String, Object> query = new HashMap<>(2);query.put("id", 1);query.put("name", new String[]{"1", "2"});System.out.println(personMapper.getPersonByMap(query));}}// 初始化SqlSessionFactorypublic static SqlSessionFactory buildSqlSessionFactory() {String JDBC_DRIVER = "org.h2.Driver";String DB_URL = "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1";String USER = "sa";String PASS = "";DataSource dataSource = new PooledDataSource(JDBC_DRIVER, DB_URL, USER, PASS);Environment environment = new Environment("Development", new JdbcTransactionFactory(), dataSource);Configuration configuration = new Configuration(environment);configuration.getTypeHandlerRegistry().register(String[].class, JdbcType.VARCHAR, StringArrayTypeHandler.class);configuration.addMapper(PersonMapper.class);SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();return builder.build(configuration);}
}

在上面的代碼中,我們可以明顯的看到大段的SqlSessionFactory初始化和Mapper的獲取的繁瑣代碼,但我們在Spring中沒有這些繁瑣的操作,如下變可以使用:

@AllArgsConstructor
@Service
public class PersonService {private final PersonMapper personMapper;public void select() {personMapper.getPersonById(0);}
}

可以說非常省心和簡單了

以前自己也不知道其原理,通過這段時間的學習,了解了MyBatis的原始使用和Spring的相關原理,知道了其背后的原理,在開發中使用起來感覺心中比以前有數了,希望通過這些源碼解析的文章,也能對大家有所幫助

SqlSessionFactory的初始化

java解析yaml?這部分涉及到Spring的Bean和Spring Boot自動配置

可以嘗試去自己寫一個Spring Boot Starter,這樣會有比較大幫助(以前好像寫過一篇,但找不到了,可以參考下下面其他人的鏈接):

  • SpringBoot自定義starter及自動配置
  • spring boot 自定義配置屬性的各種方式

這里我們直接去看包:org.mybatis.spring.boot.autoconfigure

可以看到下面一段我們熟悉的內容:

可以看到Spring 在啟動時便自動初始化了SqlSessionFactory,其中的細節這里就不贅述了

    @Bean@ConditionalOnMissingBeanpublic SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {SqlSessionFactoryBean factory = new SqlSessionFactoryBean();factory.setDataSource(dataSource);factory.setVfs(SpringBootVFS.class);if (StringUtils.hasText(this.properties.getConfigLocation())) {factory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation()));}this.applyConfiguration(factory);if (this.properties.getConfigurationProperties() != null) {factory.setConfigurationProperties(this.properties.getConfigurationProperties());}if (!ObjectUtils.isEmpty(this.interceptors)) {factory.setPlugins(this.interceptors);}if (this.databaseIdProvider != null) {factory.setDatabaseIdProvider(this.databaseIdProvider);}if (StringUtils.hasLength(this.properties.getTypeAliasesPackage())) {factory.setTypeAliasesPackage(this.properties.getTypeAliasesPackage());}if (this.properties.getTypeAliasesSuperType() != null) {factory.setTypeAliasesSuperType(this.properties.getTypeAliasesSuperType());}if (StringUtils.hasLength(this.properties.getTypeHandlersPackage())) {factory.setTypeHandlersPackage(this.properties.getTypeHandlersPackage());}if (!ObjectUtils.isEmpty(this.typeHandlers)) {factory.setTypeHandlers(this.typeHandlers);}if (!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) {factory.setMapperLocations(this.properties.resolveMapperLocations());}Set<String> factoryPropertyNames = (Set)Stream.of((new BeanWrapperImpl(SqlSessionFactoryBean.class)).getPropertyDescriptors()).map(FeatureDescriptor::getName).collect(Collectors.toSet());Class<? extends LanguageDriver> defaultLanguageDriver = this.properties.getDefaultScriptingLanguageDriver();if (factoryPropertyNames.contains("scriptingLanguageDrivers") && !ObjectUtils.isEmpty(this.languageDrivers)) {factory.setScriptingLanguageDrivers(this.languageDrivers);if (defaultLanguageDriver == null && this.languageDrivers.length == 1) {defaultLanguageDriver = this.languageDrivers[0].getClass();}}if (factoryPropertyNames.contains("defaultScriptingLanguageDriver")) {factory.setDefaultScriptingLanguageDriver(defaultLanguageDriver);}this.applySqlSessionFactoryBeanCustomizers(factory);return factory.getObject();}

Mapper的生成使用

這部分涉及到Spring的依賴注入相關的原理了,自己以前寫過一個demo,但文章還沒完善,后面抽空完善后,再發出來

Springboot注解、簡答來說,核心是:

  • 1.應用啟動時,自動生成需要的類實例放入容器中, 比如加了Service注解的類
  • 2.對類實例進行初始化,在構造函數中,將其需要的類實例給傳遞進去

比如下面的:

@AllArgsConstructor
@Service
public class PersonService {private final PersonMapper personMapper;
}

在Spring容器中已經有了類 PersonService 和 PersonMapper 的實例

在初始化階段,調用 PersonService 構造函數時,發現需要 PersonMapper,由于從容器中取PersonMapper給其傳遞進去

大體的意思應該是這樣,可能細節上會有些出入

下面是大致一些Debug的信息,通過調試就會發現,SqlSessionFactory 和 Mapper 初始化和獲取等代碼都是在應用程序其中就會執行觸發

maven java。這個是PersonService這個bean初始化的相關棧函數:

   @Nullableprotected Object resolveAutowiredArgument(MethodParameter param, String beanName, @Nullable Set<String> autowiredBeanNames, TypeConverter typeConverter, boolean fallback) {Class<?> paramType = param.getParameterType();if (InjectionPoint.class.isAssignableFrom(paramType)) {InjectionPoint injectionPoint = (InjectionPoint)currentInjectionPoint.get();if (injectionPoint == null) {throw new IllegalStateException("No current InjectionPoint available for " + param);} else {return injectionPoint;}} else {try {return this.beanFactory.resolveDependency(new DependencyDescriptor(param, true), beanName, autowiredBeanNames, typeConverter);} catch (NoUniqueBeanDefinitionException var8) {throw var8;} catch (NoSuchBeanDefinitionException var9) {if (fallback) {if (paramType.isArray()) {return Array.newInstance(paramType.getComponentType(), 0);}if (CollectionFactory.isApproximableCollectionType(paramType)) {return CollectionFactory.createCollection(paramType, 0);}if (CollectionFactory.isApproximableMapType(paramType)) {return CollectionFactory.createMap(paramType, 0);}}throw var9;}}}

調試的相關信息如下:

image.png

這個beanName是PersonService,需要的構造函數參數是 PersonMapper

一直跟著下面,它會從SqlSessionTemplate中取

    public <T> T getMapper(Class<T> type) {return this.getConfiguration().getMapper(type, this);}

然后就跳到我們熟悉的 Mybatis類中 Configuration:

  public <T> T getMapper(Class<T> type, SqlSession sqlSession) {return mapperRegistry.getMapper(type, sqlSession);}

總結

Mybatis框架、本篇中大致探索了:

  • MyBatis初始化 SqlSessionFactory:Spring boot 自動配置
  • Mapper初始化和使用:基于依賴注入,方便快捷的使用

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/4/135530.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息