zoukankan      html  css  js  c++  java
  • SqlSessionFactory的Bean的注册容器

    SqlSessionFactory的Bean的注册容器

    总的流程如下:

    1. 在ConfigurationClassParser#parse()中会对deferredImportSelectorHandler进行处理
    2. 处理过程中会调用SpringFactoriesLoader#loadFactoryNames(),去查找所有jar下面META-INF/spring.factories中key为org.springframework.boot.autoconfigure.EnableAutoConfiguration的值,其中有org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
    3. 由于MybatisAutoConfiguration被@Configuratin注解,解析出里面有两个BeanMethod,name分别为SqlSessionFactory、SqlSessionTemplate
    4. 在ConfigurationClassPostProcessor#processConfigBeanDefinitions()中loadBeanDefinitions时,调用ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForBeanMethod(),对beanName分别为SqlSessionFactory、SqlSessionTemplate进行 BeanDefinition的属性设置,并注册IOC容器

    具体自动配置加载过程可参考前文《Spring之事务源码》

    mybatis-spring-boot-autoconfigure-xx.jar下面META-INF/spring.factories

    # Auto Configure
    org.springframework.boot.autoconfigure.EnableAutoConfiguration=
    org.mybatis.spring.boot.autoconfigure.MybatisLanguageDriverAutoConfiguration,
    org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
    

    MybatisAutoConfiguration类源码如下:

    @org.springframework.context.annotation.Configuration
    @ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class })
    @ConditionalOnSingleCandidate(DataSource.class)
    @EnableConfigurationProperties(MybatisProperties.class)
    @AutoConfigureAfter({ DataSourceAutoConfiguration.class, MybatisLanguageDriverAutoConfiguration.class })
    public class MybatisAutoConfiguration implements InitializingBean {
    
      @Override
      public void afterPropertiesSet() {
        checkConfigFileExists();
      }
    
      private void checkConfigFileExists() {
        if (this.properties.isCheckConfigLocation() && StringUtils.hasText(this.properties.getConfigLocation())) {
          Resource resource = this.resourceLoader.getResource(this.properties.getConfigLocation());
        }
      }
    
      @Bean
      @ConditionalOnMissingBean
      public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
        factory.setDataSource(dataSource);
        applyConfiguration(factory);
        ......
        return factory.getObject();
      }
      
      @Bean
      @ConditionalOnMissingBean
      public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
        ExecutorType executorType = this.properties.getExecutorType();
        if (executorType != null) {
          return new SqlSessionTemplate(sqlSessionFactory, executorType);
        } else {
          return new SqlSessionTemplate(sqlSessionFactory);
        }
      }
    }
    

    SqlSessionFactory的实例化

    调用链:

    AbstractAutowireCapableBeanFactory#createBean() -->
    AbstractAutowireCapableBeanFactory#doCreateBean() -->
    AbstractAutowireCapableBeanFactory#createBeanInstance() --> AbstractAutowireCapableBeanFactory#instantiateUsingFactoryMethod() --> ConstructorResolver#instantiateUsingFactoryMethod() --> ConstructorResolver#instantiate() --> SimpleInstantiationStrategy#instantiate() --> MybatisAutoConfiguration#sqlSessionFactory() --> SqlSessionFactory#getObject()-->SqlSessionFactory#afterPropertiesSet() --> SqlSessionFactory#buildSqlSessionFactory() --> XMLMapperBuilder#parse() --> XMLMapperBuilder#configurationElement() --> XMLMapperBuilder#buildStatementFromContext() --> XMLMapperBuilder#buildStatementFromContext() -->
    XMLStatementBuilder#parseStatementNode() --> MapperBuilderAssistant#addMappedStatement() -- MappedStatement$Builder#()

    和normal bean实例化不一样,sqlSessionFactory的实例化从instantiateUsingFactoryMethod()入口实现

    protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    	// Make sure bean class is actually resolved at this point.
    	Class<?> beanClass = resolveBeanClass(mbd, beanName);
        //sqlSessionFactory
    	if (mbd.getFactoryMethodName() != null) {
    		return instantiateUsingFactoryMethod(beanName, mbd, args);
    	}
    }
    

    其中afterPropertiesSet会进行sqlSessionFactory的build,进入后面重点

    public class MybatisAutoConfiguration implements InitializingBean {
      @Bean
      @ConditionalOnMissingBean
      public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
          ......
          return factory.getObject();
      }
    }
    
      @Override
      public SqlSessionFactory getObject() throws Exception {
        if (this.sqlSessionFactory == null) {
          afterPropertiesSet();
        }
    
        return this.sqlSessionFactory;
      }
    
      @Override
      public void afterPropertiesSet() throws Exception {
        this.sqlSessionFactory = buildSqlSessionFactory();
      }
    
    mbd.factoryMethodToIntrospect

    MybatisAutoConfiguration为factoryBean,取出里面所有满足条件的factoryMethod,其中包括public org.apache.ibatis.session.SqlSessionFactory org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration.sqlSessionFactory(javax.sql.DataSource) throws java.lang.Exception,将其赋值给 mbd.factoryMethodToIntrospect

    protected Class<?> getTypeForFactoryMethod(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch) {
    
    	Method uniqueCandidate = mbd.factoryMethodToIntrospect;
    
    	if (uniqueCandidate == null) {
            ......
    		Method[] candidates = this.factoryMethodCandidateCache.computeIfAbsent(factoryClass,
    				clazz -> ReflectionUtils.getUniqueDeclaredMethods(clazz, ReflectionUtils.USER_DECLARED_METHODS));
    
    		for (Method candidate : candidates) {
    			if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate) &&
    					candidate.getParameterCount() >= minNrOfArgs) {
    				// Declared type variables to inspect?
    				if (candidate.getTypeParameters().length > 0) {
    					......
    				}
    				else {
    					uniqueCandidate = (commonType == null ? candidate : null);
    				}
    			}
    		}
    		mbd.factoryMethodToIntrospect = uniqueCandidate;
    	}
    }
    
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出。
  • 相关阅读:
    将Nginx添加到windows服务中
    springboot使用redis管理session
    GIT常用命令
    阻止360、谷歌浏览器表单自动填充
    谈谈对Spring IOC的理解
    同一个Nginx服务器同一端口配置多个代理服务
    LeetCode 653. Two Sum IV
    109. Convert Sorted List to Binary Search Tree(根据有序链表构造平衡的二叉查找树)
    108. Convert Sorted Array to Binary Search Tree(从有序数组中构造平衡的BST)
    LeetCode 236. Lowest Common Ancestor of a Binary Tree(二叉树求两点LCA)
  • 原文地址:https://www.cnblogs.com/caozibiao/p/14040679.html
Copyright © 2011-2022 走看看