国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Spring-Mybatis運行機制概括

qieangel2013 / 739人閱讀

摘要:使用這個類庫中的類將會加載必要的工廠類和類。最終它并不會依賴于或來構建應用程序代碼。下面對各部分作用總結下。和無縫整合的機制和的認識在講如何無縫整合進之前,我們先認識下和這兩個接口的作用。附上上篇博文地址原理概括。

前言

本篇是繼上篇MyBatis原理概括延伸的,所以如果有小伙伴還沒看上篇博文的話,可以先去看下,也不會浪費大家太多的時間,因為本篇會結合到上篇敘述的相關內容。

好,切入正題,這篇主要講一個點,就是我們在結合spring去使用mybatis的時候,spring為我們做了什么事。還是老套路,我們只講過程思路,具體細節還望各位小伙伴找時間去研究,如果我全講了,你們也都看懂了,那你們最多也就是感到一種獲得感,而不是成就感,獲得感是會隨著時間的推移而慢慢減少的,所以我這里主要提供給大家一個思路,然后大家可以順著這條思路慢慢摸索下去,從而獲得成就感!

使用spring-mybatis 1.spring-mybatis是什么

MyBatis-Spring 會幫助你將 MyBatis 代碼無縫地整合到 Spring 中。 使用這個類庫中的類, Spring 將會加載必要的 MyBatis 工廠類和 session 類。 這個類庫也提供一個簡單的方式來注入 MyBatis 數據映射器和 SqlSession 到業務層的 bean 中。 而且它也會處理事務, 翻譯 MyBatis 的異常到 Spring 的 DataAccessException 異常(數據訪問異常,譯者注)中。最終,它并 不會依賴于 MyBatis,Spring 或 MyBatis-Spring 來構建應用程序代碼。(這是官網解釋)

2.基于XML配置和注解形式使用 a.基于XML配置

一般情況下,我們使用xml的形式引入mybatis,一般的配置如下:


    
    
    
    
     
     
     
     
     
     
     
     
     
     




    
     
     


 
 
     
     

如上配置所示,我們一般需要申明dataSource、sqlSessionFactory以及MapperScannerConfigurer。如何我們還有其他mybatis的配置,比如plugin、typehandler等,我們可以另外申明一個mybaits-config.xml文件,在sqlSessionFactory配置中引入即可。下面對各部分作用總結下。
dataSource:申明一個數據源;
sqlSessionFactory:申明一個sqlSession的工廠;
MapperScannerConfigurer:讓spring自動掃描我們持久層的接口從而自動構建代理類。

b.基于注解形式

注解形式的話相當于將上述的xml配置一一對應成注解的形式

@Configuration  
@MapperScan(value="org.fhp.springmybatis.dao")  
public class DaoConfig {
  
    @Value("${jdbc.driverClass}")  
    private String driverClass;  
  
    @Value("${jdbc.user}")  
    private String user;  
  
    @Value("${jdbc.password}")  
    private String password;  
  
    @Value("${jdbc.jdbcUrl}")  
    private String jdbcUrl;  
  
    @Bean  
    public DataSource dataSource() {  
        DriverManagerDataSource dataSource = new DriverManagerDataSource();  
        dataSource.setDriverClassName(driverClass);  
        dataSource.setUsername(user);  
        dataSource.setPassword(password);  
        dataSource.setUrl(jdbcUrl);  
        return dataSource;  
    }  
  
    @Bean  
    public DataSourceTransactionManager transactionManager() {  
        return new DataSourceTransactionManager(dataSource());  
    }  
  
    @Bean  
    public SqlSessionFactory sqlSessionFactory() throws Exception {  
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();  
        sessionFactory.setDataSource(dataSource());  
        return sessionFactory.getObject();  
    }  
}  

很明顯,一樣需要一個dataSource,SqlSessionFactory以及一個@MapperScan的注解。這個注解的作用跟上述的
MapperScannerConfigurer的作用是一樣的。

3.spring和mybatis無縫整合的機制 a.BeanDefinitionRegistryPostProcessor和ImportBeanDefinitionRegistrar的認識

在講mybatis如何無縫整合進spring之前,我們先認識下BeanDefinitionRegistryPostProcessor和ImportBeanDefinitionRegistrar這兩個接口的作用。

我們先看下這兩個接口是什么樣的。

//BeanDefinitionRegistryPostProcessor接口
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
    void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry var1) throws BeansException;
}

//ImportBeanDefinitionRegistrar接口
public interface ImportBeanDefinitionRegistrar {
    void registerBeanDefinitions(AnnotationMetadata var1, BeanDefinitionRegistry var2);
}

對于這兩個接口我們先看官方文檔給我們的解釋。

以下是BeanDefinitionRegistryPostProcessor的解釋:

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor

Extension to the standard BeanFactoryPostProcessor SPI, allowing for the registration of further bean definitions before regular BeanFactoryPostProcessor detection kicks in. In particular, BeanDefinitionRegistryPostProcessor may register further bean definitions which in turn define BeanFactoryPostProcessor instances.

意思大概就是我們可以擴展spring對于bean definitions的定義。也就是說可以讓我們實現自定義的注冊bean定義的邏輯。
再來看下ImportBeanDefinitionRegistrar的解釋:

public interface ImportBeanDefinitionRegistrar Interface to be implemented by types that register additional bean definitions when processing @Configuration classes. Useful when operating at the bean definition level (as opposed to @Bean method/instance level) is desired or necessary.

Along with @Configuration and ImportSelector, classes of this type may be provided to the @Import annotation (or may also be returned from an ImportSelector).

通俗解釋來講就是在@Configuration上使用@Import時可以自定義beanDefinition,或者作為ImportSelector接口的返回值(有興趣的小伙伴可以自行研究)。

所以總結下就是如果我想擴展beanDefinition那么我可以繼承這兩個接口實現。下面我們就從mybatis配置方式入手講講spring和mybatis是如何無縫整合的。

b.基于XML配置mybatis是如何整合進spring的

首先,容器啟動的時候,我們在xml配置中的SqlSessionFactoryBean會被初始化,所以我們先看下SqlSessionFactoryBean是在初始化的時候作了哪些工作。

public class SqlSessionFactoryBean implements FactoryBean, InitializingBean, ApplicationListener {
    private static final Log LOGGER = LogFactory.getLog(SqlSessionFactoryBean.class);
    private Resource configLocation;
    private Configuration configuration;
    private Resource[] mapperLocations;
    private DataSource dataSource;
    private TransactionFactory transactionFactory;
    private Properties configurationProperties;
    private SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
    private SqlSessionFactory sqlSessionFactory;
    private String environment = SqlSessionFactoryBean.class.getSimpleName();
    private boolean failFast;
    private Interceptor[] plugins;
    private TypeHandler[] typeHandlers;
    private String typeHandlersPackage;
    private Class[] typeAliases;
    private String typeAliasesPackage;
    private Class typeAliasesSuperType;
    private DatabaseIdProvider databaseIdProvider;
    private Class vfs;
    private Cache cache;
    private ObjectFactory objectFactory;
    private ObjectWrapperFactory objectWrapperFactory;

    public SqlSessionFactoryBean() {
    }
    ...
}

我們可以看到這個類實現了FactoryBean、InitializingBean和ApplicationListener接口,對應的接口在bean初始化的時候為執行些特定的方法(如果不清楚的小伙伴請自行百度,這里不作過多敘述)。現在我們來看看都有哪些方法會被執行,這些方法又作了哪些工作。

//FactoryBean
public SqlSessionFactory getObject() throws Exception {
    if (this.sqlSessionFactory == null) {
        this.afterPropertiesSet();
    }

    return this.sqlSessionFactory;
}

//InitializingBean
public void afterPropertiesSet() throws Exception {
    Assert.notNull(this.dataSource, "Property "dataSource" is required");
    Assert.notNull(this.sqlSessionFactoryBuilder, "Property "sqlSessionFactoryBuilder" is required");
    Assert.state(this.configuration == null && this.configLocation == null || this.configuration == null || this.configLocation == null, "Property "configuration" and "configLocation" can not specified with together");
    this.sqlSessionFactory = this.buildSqlSessionFactory();
}

//ApplicationListener
public void onApplicationEvent(ApplicationEvent event) {
    if (this.failFast && event instanceof ContextRefreshedEvent) {
        this.sqlSessionFactory.getConfiguration().getMappedStatementNames();
    }

}

通過觀察代碼我們可以知道前面兩個都是在做同一件事情,那就是在構建sqlSessionFactory,在構建sqlSessionFactory時mybatis會去解析配置文件,構建configuation。后面的onApplicationEvent主要是監聽應用事件時做的一些事情(不詳講,有興趣的同學可以自己去了解下)。

其次,我們回憶下我們在xml配置中還配置了MapperScannerConfigurer,或者也可以配置多個的MapperFactoryBean,道理都是一樣的,只是MapperScannerConfigurer幫我們封裝了這一個過程,可以實現自動掃描指定包下的mapper接口構建MapperFactoryBean。

問題1:為什么我們從spring容器中能直接獲取對應mapper接口的實現類?而不用使用sqlSession去getMapper呢?
答案其實在上面就已經為大家解答了,就是MapperFactoryBean。我們先看看這個類。

public class MapperFactoryBean extends SqlSessionDaoSupport implements FactoryBean {
    private Class mapperInterface;
    private boolean addToConfig = true;

    public MapperFactoryBean() {
    }

    public MapperFactoryBean(Class mapperInterface) {
        this.mapperInterface = mapperInterface;
    }
    ...
}

這個類繼承了SqlSessionDaoSupport,實現了FactoryBean。
我們先講講SqlSessionDaoSupport這個類

public abstract class SqlSessionDaoSupport extends DaoSupport {
    private SqlSession sqlSession;
    private boolean externalSqlSession;

    public SqlSessionDaoSupport() {
    }

    public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
        if (!this.externalSqlSession) {
            this.sqlSession = new SqlSessionTemplate(sqlSessionFactory);
        }

    }

    public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
        this.sqlSession = sqlSessionTemplate;
        this.externalSqlSession = true;
    }

    public SqlSession getSqlSession() {
        return this.sqlSession;
    }

    protected void checkDaoConfig() {
        Assert.notNull(this.sqlSession, "Property "sqlSessionFactory" or "sqlSessionTemplate" are required");
    }
}

可以看到這個類繼承了DaoSupport,我們再來看下這個類。

public abstract class DaoSupport implements InitializingBean {
    protected final Log logger = LogFactory.getLog(this.getClass());

    public DaoSupport() {
    }

    public final void afterPropertiesSet() throws IllegalArgumentException, BeanInitializationException {
        this.checkDaoConfig();

        try {
            this.initDao();
        } catch (Exception var2) {
            throw new BeanInitializationException("Initialization of DAO failed", var2);
        }
    }

    protected abstract void checkDaoConfig() throws IllegalArgumentException;

    protected void initDao() throws Exception {
    }
}

可以看到實現了InitializingBean接口,所以在類初始化時為執行afterPropertiesSet方法,我們看到afterPropertiesSet方法里面有checkDaoConfig方法和initDao方法,其中initDao是模板方法,提供子類自行實現相關dao初始化的操作,我們看下checkDaoConfig方法作了什么事。

//MapperFactoryBean
protected void checkDaoConfig() {
    super.checkDaoConfig();
    Assert.notNull(this.mapperInterface, "Property "mapperInterface" is required");
    Configuration configuration = this.getSqlSession().getConfiguration();
    if (this.addToConfig && !configuration.hasMapper(this.mapperInterface)) {
        try {
            configuration.addMapper(this.mapperInterface);
        } catch (Exception var6) {
            this.logger.error("Error while adding the mapper "" + this.mapperInterface + "" to configuration.", var6);
            throw new IllegalArgumentException(var6);
        } finally {
            ErrorContext.instance().reset();
        }
    }

}

這個方法具體的實現是在MapperFactoryBean類里面的,主要作用就是對驗證mapperInterface是否存在configuration對象里面。

然后我們再來看下MapperFactoryBean實現了FactoryBean的目的是什么。我們都知道FactoryBean有一個方法是getObject,這個方法的作用就是在spring容器初始化bean時,如果判斷這個類是否繼承自FactoryBean,那么在獲取真正的bean實例時會調用getObject,將getObject方法返回的值注冊到spring容器中。在明白了這些知識點之后,我們看下MapperFactoryBean的getObject方法是如何實現的。

//MapperFactoryBean
public T getObject() throws Exception {
    return this.getSqlSession().getMapper(this.mapperInterface);
}

看到這里是否就已經明白為什么在結合spring時我們不需要使用sqlSession對象去獲取我們的mapper實現類了吧。因為spring幫我們作了封裝!
之后的操作可以結合上面博文去看mybatis如何獲取到對應的Mapper對象的了。附上上篇博文地址:MyBatis原理概括。

接下來我們看下mybatis是如何結合spring構建MapperFactoryBean的beanDefinition的。這里我們需要看看MapperScannerConfigurer這個類,這個類的目的就是掃描我們指定的dao層(持久層)對應的包(package),構建相應的beanDefinition提供給spring容器去實例化我們的mapper接口對象。

//MapperScannerConfigurer
public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware {
    private String basePackage;
    private boolean addToConfig = true;
    private SqlSessionFactory sqlSessionFactory;
    private SqlSessionTemplate sqlSessionTemplate;
    private String sqlSessionFactoryBeanName;
    private String sqlSessionTemplateBeanName;
    private Class annotationClass;
    private Class markerInterface;
    private ApplicationContext applicationContext;
    private String beanName;
    private boolean processPropertyPlaceHolders;
    private BeanNameGenerator nameGenerator;

    public MapperScannerConfigurer() {
    }
    ...
}

通過代碼,我們可以看到這個類實現了BeanDefinitionRegistryPostProcessor這個接口,通過前面對BeanDefinitionRegistryPostProcessor的講解,我們去看看MapperScannerConfigurer中的postProcessBeanDefinitionRegistry方法的實現。

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
    if (this.processPropertyPlaceHolders) {
        this.processPropertyPlaceHolders();
    }

    ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
    scanner.setAddToConfig(this.addToConfig);
    scanner.setAnnotationClass(this.annotationClass);
    scanner.setMarkerInterface(this.markerInterface);
    scanner.setSqlSessionFactory(this.sqlSessionFactory);
    scanner.setSqlSessionTemplate(this.sqlSessionTemplate);
    scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName);
    scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName);
    scanner.setResourceLoader(this.applicationContext);
    scanner.setBeanNameGenerator(this.nameGenerator);
    scanner.registerFilters();
    scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ",; 	
"));
}

可以看這里就是在構建ClassPathMapperScanner對象,然后調用scan方法掃描。接下來我們繼續看這個掃描的操作,因為這個類繼承了ClassPathBeanDefinitionScanner,調用的scan方法是在ClassPathBeanDefinitionScanner里申明的。

//ClassPathBeanDefinitionScanner
public int scan(String... basePackages) {
    int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
    this.doScan(basePackages);
    if (this.includeAnnotationConfig) {
        AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
    }

    return this.registry.getBeanDefinitionCount() - beanCountAtScanStart;
}

這里我們需要注意doScan這個方法,這個方法在ClassPathMapperScanner中重寫了。

//ClassPathMapperScanner
public Set doScan(String... basePackages) {
    Set beanDefinitions = super.doScan(basePackages);
    if (beanDefinitions.isEmpty()) {
        this.logger.warn("No MyBatis mapper was found in "" + Arrays.toString(basePackages) + "" package. Please check your configuration.");
    } else {
        this.processBeanDefinitions(beanDefinitions);
    }

    return beanDefinitions;
}

這里調用了父類的doScan得到beanDefinitions的集合。這里的父類的doScan方法是spring提供的包掃描操作,這里不過多敘述,感興趣的小伙伴可以自行研究。我們還注意到在得到beanDefinitions集合后,這里還調用了processBeanDefinitions方法,這里是對beanDefinition做了一些特殊的處理以滿足mybaits的需求。我們先來看下這個方法。

//ClassPathMapperScanner#doScan
private void processBeanDefinitions(Set beanDefinitions) {
    Iterator var3 = beanDefinitions.iterator();

    while(var3.hasNext()) {
        BeanDefinitionHolder holder = (BeanDefinitionHolder)var3.next();
        GenericBeanDefinition definition = (GenericBeanDefinition)holder.getBeanDefinition();
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Creating MapperFactoryBean with name "" + holder.getBeanName() + "" and "" + definition.getBeanClassName() + "" mapperInterface");
        }

        definition.getConstructorArgumentValues().addGenericArgumentValue(definition.getBeanClassName());
        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;
        } else if (this.sqlSessionFactory != null) {
            definition.getPropertyValues().add("sqlSessionFactory", this.sqlSessionFactory);
            explicitFactoryUsed = true;
        }

        if (StringUtils.hasText(this.sqlSessionTemplateBeanName)) {
            if (explicitFactoryUsed) {
                this.logger.warn("Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored.");
            }

            definition.getPropertyValues().add("sqlSessionTemplate", new RuntimeBeanReference(this.sqlSessionTemplateBeanName));
            explicitFactoryUsed = true;
        } else if (this.sqlSessionTemplate != null) {
            if (explicitFactoryUsed) {
                this.logger.warn("Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored.");
            }

            definition.getPropertyValues().add("sqlSessionTemplate", this.sqlSessionTemplate);
            explicitFactoryUsed = true;
        }

        if (!explicitFactoryUsed) {
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Enabling autowire by type for MapperFactoryBean with name "" + holder.getBeanName() + "".");
            }

            definition.setAutowireMode(2);
        }
    }

}

這里我們注意到有這么一行代碼:definition.setBeanClass(this.mapperFactoryBean.getClass()),看到這里我們就可以知道為什么spring在加載初始化我們的mapper接口對象會初始化成MapperFactoryBean對象了

好了,到這里我們也就明白了spring是如何幫我們加載注冊我們的mapper接口對應的實現類了。對于代碼里涉及到的其他細節,這里暫時不作過多講解,還是老套路,只講解總體思路。

c.基于注解配置mybatis是如何整合進spring的

基于注解形式的配置其實就是將xml配置對應到注解中來,本質上的流程還是一樣的。所以這里我就簡單講講。我們先看看MapperScannerRegistrar這個類,因為這個類是spring構建MapperFactoryBean的核心類。

//MapperScannerRegistrar
public class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware {
    private ResourceLoader resourceLoader;

    public MapperScannerRegistrar() {
    }
    ...
}

這里我們注意到MapperScannerRegistrar實現了ImportBeanDefinitionRegistrar接口,在前面的敘述中我們已經知道了實現ImportBeanDefinitionRegistrar接口的作用是什么了,所以我們直接看看這里具體做了什么操作。

public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    AnnotationAttributes annoAttrs = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName()));
    ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
    if (this.resourceLoader != null) {
        scanner.setResourceLoader(this.resourceLoader);
    }

    Class annotationClass = annoAttrs.getClass("annotationClass");
    if (!Annotation.class.equals(annotationClass)) {
        scanner.setAnnotationClass(annotationClass);
    }

    Class markerInterface = annoAttrs.getClass("markerInterface");
    if (!Class.class.equals(markerInterface)) {
        scanner.setMarkerInterface(markerInterface);
    }

    Class generatorClass = annoAttrs.getClass("nameGenerator");
    if (!BeanNameGenerator.class.equals(generatorClass)) {
        scanner.setBeanNameGenerator((BeanNameGenerator)BeanUtils.instantiateClass(generatorClass));
    }

    Class mapperFactoryBeanClass = annoAttrs.getClass("factoryBean");
    if (!MapperFactoryBean.class.equals(mapperFactoryBeanClass)) {
        scanner.setMapperFactoryBean((MapperFactoryBean)BeanUtils.instantiateClass(mapperFactoryBeanClass));
    }

    scanner.setSqlSessionTemplateBeanName(annoAttrs.getString("sqlSessionTemplateRef"));
    scanner.setSqlSessionFactoryBeanName(annoAttrs.getString("sqlSessionFactoryRef"));
    List basePackages = new ArrayList();
    String[] var10 = annoAttrs.getStringArray("value");
    int var11 = var10.length;

    int var12;
    String pkg;
    for(var12 = 0; var12 < var11; ++var12) {
        pkg = var10[var12];
        if (StringUtils.hasText(pkg)) {
            basePackages.add(pkg);
        }
    }

    var10 = annoAttrs.getStringArray("basePackages");
    var11 = var10.length;

    for(var12 = 0; var12 < var11; ++var12) {
        pkg = var10[var12];
        if (StringUtils.hasText(pkg)) {
            basePackages.add(pkg);
        }
    }

    Class[] var14 = annoAttrs.getClassArray("basePackageClasses");
    var11 = var14.length;

    for(var12 = 0; var12 < var11; ++var12) {
        Class clazz = var14[var12];
        basePackages.add(ClassUtils.getPackageName(clazz));
    }

    scanner.registerFilters();
    scanner.doScan(StringUtils.toStringArray(basePackages));
}

通過觀察我們看到最后還是調用了ClassPathMapperScanner的doScan去掃描指定包下的mapper接口(持久層),然后構建對應的beanDefinition類。前面我們知道是通過MapperScan這個注解去指定包的,然后我們也可以看到,在這個方法一開始就取出這個注解的值,然后進行接下來的操作的。

 AnnotationAttributes annoAttrs = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName()));

之后的過程其實跟xml形式配置的一樣了。

后序

好啦,這篇沒想啰理八嗦說了那么多,可能有好多小伙伴看到最后也是懵逼狀態,這里有個建議,打開IDE,邊看邊對著代碼跟蹤,如果哪里覺得不對,可以直接debug。

這里給大家提個看源碼的建議,就是猜想+驗證。先猜想自己的想法,然后通過查找相關問題或者debug代碼去驗證自己的思路。

好啦,到這里為止,mybatis和spring-mybatis的基本原理都跟大家說了一遍,不知道小伙伴們有沒有收獲呢,下一篇,我會帶大家手寫一遍mybatis,是純手寫而且還能跑起來的那種哦!

:本人不才,以上如有錯誤的地方或者不規范的敘述還望各位小伙伴批評指點。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/69636.html

相關文章

  • 教你手寫Mybatis框架

    摘要:前言嗨,小伙伴們,這篇博文將帶大家手寫,讓大家對的核心原理以及工作流程有更加深刻的理解。模塊顧名思義,就是框架配置類,用于解析配置文件加載相關環境。配置模塊這里的對框架的配置使用了簡單的,主要原因還是簡單易懂然后節省時間。 前言 (????)??嗨,小伙伴們,這篇博文將帶大家手寫mybatis,讓大家對mybaits的核心原理以及工作流程有更加深刻的理解。在上篇Spring-Mybat...

    antyiwei 評論0 收藏0
  • 分布式軟件架構整合(一)

    摘要:通過整合及可以實現數據庫查詢后將數據持久化。但是可能出現幻像讀這是花費最高代價但是最可靠的事務隔離級別。事務被處理為順序執行。 所需技術:spring、mybatis、druid、flyway、logback、nodejs、html、css3 ;目標:創建一個業務框架,后端采用spring+mybatis,中間層采用node,前端html5,css3等; showImg(https:/...

    mochixuan 評論0 收藏0
  • MyBatis原理概括

    摘要:避免了幾乎所有的代碼和手動設置參數以及獲取結果集。這個對象主要是獲取方法對應的命令和執行相應操作等的處理,具體細節同學們可以抽空研究。所以這里的方法主要使用了和對象幫助我們處理語句集和參數的處理。 博文目標:希望大家看了這篇博文后,對Mybatis整體運行過程有一個清晰的認識和把握。 1.什么是 MyBatis ? MyBatis 是一款優秀的持久層框架,它支持定制化 SQL、存儲過程...

    mikasa 評論0 收藏0
  • 事件循環機制和task執行順序的一些概括(javascript)

    摘要:而當響應成功了以后,瀏覽器的事件表則會將回調函數添加至事件隊列中等待執行。事件循環器會不停的檢查事件隊列,如果不為空,則取出隊首壓入執行棧執行。類型的任務目前包括了以及的回調函數。 事件循環(event loop) : 首先說事件隊列(task queue) 事件隊列是一個存儲著待執行任務的隊列,其中的任務嚴格按照時間先后順序執行,排在隊頭的任務將會率先執行,而排在隊尾的任務會最后執行...

    未東興 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<