ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Mybatis-Spring(1)

2019-06-25 21:02:20  阅读:257  来源: 互联网

标签:basePackages scanner Spring ............ annoAttrs Mybatis new class


将Mybatis中的Mapper注册到Spring的ApplicationContext中,受Spring的生命周期管理。

Mapper扫描注解,用法

@Configuration
@MapperScan("org.mybatis.spring.sample.mapper")

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(MapperScannerRegistrar.class)
public @interface MapperScan

这里,注意到@MapperScan其中包装了一个注解:@Import(MapperScannerRegistrar.class)

@Import处理的环节:AbstractApplicationContext.refresh()

@Override
public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
	............
	  try {
		............
		// Invoke factory processors registered as beans in the context.
		invokeBeanFactoryPostProcessors(beanFactory);
		............
	  }
	}
}

@Import解析并且将BeanDefiniton注册环节:ConfigurationClassPostProcessor.processConfigBeanDefinitions

/**
 * Build and validate a configuration model based on the registry of
 * {@link Configuration} classes.
 */
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
	List<BeanDefinitionHolder> configCandidates = new ArrayList<BeanDefinitionHolder>();
	//1、所有的BeanDefiniton的name
	String[] candidateNames = registry.getBeanDefinitionNames();

	for (String beanName : candidateNames) {
		............
		//2、将所有的@Configuration的类放入configCandidates中
		else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
			configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
		}
	}
	............
	Set<BeanDefinitionHolder> candidates = new LinkedHashSet<BeanDefinitionHolder>(configCandidates);
	do {
		//3、解析所有的@Configuration类里面所有的注解(@Bean、@Profile、@Import、@ImportResource、@ComponentScan、@Lazy、@PropertySource)
		parser.parse(candidates);
		............
          Set<ConfigurationClass> configClasses = new LinkedHashSet<ConfigurationClass>(parser.getConfigurationClasses()); ............ //4、通过解析成的configClasses,将所有的配置转化成BeanDefinition this.reader.loadBeanDefinitions(configClasses); ............ } while (!candidates.isEmpty()); ............ }

 

下面我们看下MapperScannerRegistrar做了哪些事情

registerBeanDefinitions:注册Bean

public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

	// MapperScan配置的注解数据
    AnnotationAttributes annoAttrs = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName()));
    ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);

    Class<? extends Annotation> annotationClass = annoAttrs.getClass("annotationClass");
    if (!Annotation.class.equals(annotationClass)) {
	  // 设置需要注册的annotationClass
      scanner.setAnnotationClass(annotationClass);
    }
    Class<?> markerInterface = annoAttrs.getClass("markerInterface");
    if (!Class.class.equals(markerInterface)) {
      // 设置需要注册的markerInterface
	  scanner.setMarkerInterface(markerInterface);
    }

    Class<? extends BeanNameGenerator> generatorClass = annoAttrs.getClass("nameGenerator");
    if (!BeanNameGenerator.class.equals(generatorClass)) {
      // 设置自定义的BeanNameGenerator
	  scanner.setBeanNameGenerator(BeanUtils.instantiateClass(generatorClass));
    }

    Class<? extends MapperFactoryBean> mapperFactoryBeanClass = annoAttrs.getClass("factoryBean");
    if (!MapperFactoryBean.class.equals(mapperFactoryBeanClass)) {
      // 设置自定义的MapperFactoryBean.class
	  scanner.setMapperFactoryBean(BeanUtils.instantiateClass(mapperFactoryBeanClass));
    }
	// 设置sqlSessionTemplateRef的值到sqlSessionTemplateBeanName
    scanner.setSqlSessionTemplateBeanName(annoAttrs.getString("sqlSessionTemplateRef"));
	// 设置sqlSessionTemplateRef的值到sqlSessionFactoryBeanName
    scanner.setSqlSessionFactoryBeanName(annoAttrs.getString("sqlSessionFactoryRef"));

    List<String> basePackages = new ArrayList<String>();
    for (String pkg : annoAttrs.getStringArray("value")) {
      if (StringUtils.hasText(pkg)) {
        // 设置basePackages
		basePackages.add(pkg);
      }
    }
    for (String pkg : annoAttrs.getStringArray("basePackages")) {
      if (StringUtils.hasText(pkg)) {
        // 设置basePackages
		basePackages.add(pkg);
      }
    }
    for (Class<?> clazz : annoAttrs.getClassArray("basePackageClasses")) {
      // 设置basePackages
	  basePackages.add(ClassUtils.getPackageName(clazz));
    }
	// 根据annotationClass和markerInterface,设置addIncludeFilter
    scanner.registerFilters();
	// 开始扫描
    scanner.doScan(StringUtils.toStringArray(basePackages));
  }

scanner.doScan:扫描

@Override
public Set<BeanDefinitionHolder> doScan(String... basePackages) {
    // 调用ClassPathBeanDefinitionScanner.doScan,将包下所有的类都注册到容器中
    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 {
	// 为了beanDefinitions信息,1、让这些接口类可以被MapperFactoryBean动态代理 2、设置对应的SqlSession到被代理的对象中
        processBeanDefinitions(beanDefinitions);
    }
    return beanDefinitions;
}

processBeanDefinitions:处理BeanDefiniton

private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {
    GenericBeanDefinition definition;
    for (BeanDefinitionHolder holder : beanDefinitions) {
		definition = (GenericBeanDefinition) holder.getBeanDefinition();
		...........
		// the mapper interface is the original class of the bean
		// but, the actual class of the bean is MapperFactoryBean
		// 设置接口作为构造器入参,后面看MapperFactoryBean的构造器,就能理解这是干嘛的了
		definition.getConstructorArgumentValues().addGenericArgumentValue(definition.getBeanClassName()); // issue #59
		// 将MapperFactoryBean.class作为Mapper的类,是为了让Sprintg感知,这个Bean的实例是要通过定义的FactoryBean来创建的
		definition.setBeanClass(this.mapperFactoryBean.getClass());
		...........
		// 设置sqlSessionFactoryBeanName(sqlSessionFactoryRef的值)的运行时bean引用
		definition.getPropertyValues().add("sqlSessionFactory", new RuntimeBeanReference(this.sqlSessionFactoryBeanName));
		// 设置sqlSessionTemplateBeanName(sqlSessionTemplateRef的值)的运行时bean引用
		definition.getPropertyValues().add("sqlSessionTemplate", new RuntimeBeanReference(this.sqlSessionTemplateBeanName));
        ...........
    }
}

  

 

标签:basePackages,scanner,Spring,............,annoAttrs,Mybatis,new,class
来源: https://www.cnblogs.com/sleepingDogs/p/11085436.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有