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;
    	}
    }
    
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出。
  • 相关阅读:
    C# 使用NPOI 实现Excel的简单导入导出
    C# 根据Excel模版导出文件
    移动通信第九组网络抓包作业
    武金龙老师的教导(第9小组)
    【Python核心编程笔记】一、Python中一切皆对象
    自己喜欢的几个前端框架
    2018-1-6-个人博客、博客园、微信公众号、Github、本地同步写博客
    2018-1-6-IDEA快速代码生成
    CodeMirror动态修改代码(关键: editor.getDoc().setValue(data); editor.refresh();)
    FaceId枚举表(用于VBA的加载项)
  • 原文地址:https://www.cnblogs.com/caozibiao/p/14040679.html
Copyright © 2011-2022 走看看