开发者

基于Spring整合mybatis的mapper生成过程

开发者 https://www.devze.com 2023-03-08 10:36 出处:网络 作者: asLightYouAre
目录Spring整合myBATis的mapper生成过程ClassPathMapperScanner#DOScanClassPathBeanDefinitionScanner#doScan总结Spring整合mybatis的mapper生成过程
目录
  • Spring整合myBATis的mapper生成过程
    • ClassPathMapperScanner#DOScan
    • ClassPathBeanDefinitionScanner#doScan
  • 总结

    Spring整合mybatis的mapper生成过程

    基于Spring整合mybatis的mapper生成过程

    mapperScannerConfigurer实现了BeandifinitionRegistryPostProcessor

    后置处理beanFactory时会调用其postProcessBeanDefinitionRegistry

    基于Spring整合mybatis的mapper生成过程

    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
        if (this.processPropertyPlaceHolders) {
          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)WCCoEaqbH;
        scanner.setResourceLoader(this.applicationContext);
        scanner.setBeanNameGenerator(this.nameGenerator);
        scanner.setMapperFactoryBeanClass(this.mapperFactoryBeanClass);
        scanner.registerFilters();
    //扫描包集合,注册mapper的beandifinition
        scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS));
      }

    基于Spring整合mybatis的mapper生成过程

    ClassPathMapperScanner#doScan

    public Set<BeanDefinitionHolder> doScan(String... basePackages) {
        Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);
     
        if (beanDefinitions.isEmpty()) {
          LOGGER.warn(() -> "No MyBatis mapper was found in '" + Arrays.toString(basePackages) + "' package. Please check your configuration.");
        } else {
    //会对bean信息进行一些更改和添加,如设置propertyValues,向其中添加sqlsessionFactory等属性信息等
          processBeanDefinitions(beanDefinitions);
        }
     
        return beanDefinitions;
      }

    ClassPathBeanDefinitionScanner#doScan

    protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
    		Assert.notEmpty(basePackages, "At least one base package must be specified");
    		Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
    		for (String basePackage : basePackages) {
    //遍历集合扫描包,获取包下的可用的mapper信息
    			Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
    			for (BeanDefinition candidate : candidates) {
    				ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
    				candidate.setScope(scopeMetadata.getScopeName());
    				String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
    				if (candidate instanceof AbstractBeanDefinition) {
    					postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
    				}
    				if (candidate instanceof AnnotatedBeanDefinition) {
    					AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
    				}
    				if (checkCandidate(beanName, candidate)) {
    					BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
    					definitionHolder =
    							AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
    					beanDefinitions.add(definitionHolder);
    					registerBeanDefinition(definitionHolder, this.registry);
    				}
    			}
    		}
    		return beanDefinitions;
    	}

     

    基于Spring整合mybatis的mapper生成过程

    如上在进行包扫描时,会调用ClassPathBeanDefinitionScanner#doScan,进行beanDefinition的扫描和注册

    执行完后调用ClassPathMapperScanner#processBeanDefinitions

    private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {
    //有省略部分
           
        //这里有遍历所有mapper
    //将所有mapper的beanClass改为了mapperFactoryBean,最后生成的bean也是该类型的,只有在用到的
    //时候才会调用getObject生成mapper
          definition.setBeanClass(this.mapperFactoryBeanClass);
    //接下来是添加一些MapperFactoryBean的属性信息到beandefinition里,在生成实例的时候,会根据
    //此处传入的值来进行具体设置,如sqlsessionFactory
          definition.getPropertyValues().add("addToConfig", this.addToConfig);
     
          
          if (StringUtils.hasText(this.sqlSessionFactoryBeanName)) {
            definition.getPrpythonopertyValues().add("sqlSessionFactory", new RuntimeBeanReference(this.sqlSessionFactoryBeanName));
          
          } else if (this.sqlSessionFactory != null) {
            definition.getPropertyValuejavascripts().add("sqlSessionFactory", this.sqlSessionFactory);
            
          }
     
          if (StringUtils.hasText(this.sqlSessionTemplateBeanName)) {
            
            definition.getPropertyValues().add("sqlSessionTemplate", newjs RuntimeBeanhttp://www.devze.comReference(this.sqlSessionTemplateBeanName));
            
          } else if (this.sqlSessionTemplate != null) {
            
            definition.getPropertyValues().add("sqlSessionTemplate", this.sqlSessionTemplate);
            
          }
      }

    确定了所有的mapper的beanDefinition为MapperFactoryBean类型后,

    确定在生成的bean皆为MapperFactoryBean,在getBean时会调用开发者_JAVA教程MapperFactoryBean#getObject

    基于Spring整合mybatis的mapper生成过程

    mapperInterface是在MapperFactoryBean创建时,会调用有参构造创建实例,值是创建是

    基于Spring整合mybatis的mapper生成过程

    基于Spring整合mybatis的mapper生成过程

     构造方法参数的获取从mdb中

    基于Spring整合mybatis的mapper生成过程

    创建除了传入mapperInterface,还会在设置属性值时调用MapperFactoryBean的父类SqlSessionDaoSupport#setSqFactory 将mdb中的sqlsessionfactory传入其中

    基于Spring整合mybatis的mapper生成过程

    mdb的sqlsessionFactory信息来历

    基于Spring整合mybatis的mapper生成过程

    查看方法栈调用,可以看到在开始填充属性时会去mdb中判断是否有propertyValue,如果有就返回,这就是之前扫描mapper后ClassPathMapperScanner#processBeanDefinitions对mdb的一些设置

    在创造service时,如果有@Autowire 注入mapper,在createBean时会调用getObject

    mdb只有一份,可得sqlsessionfactory即只有一份,sqlsessionTemplate一个mapper一份

    总结

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

    0

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    关注公众号