zoukankan      html  css  js  c++  java
  • Mybatis-Spring(1)BeanDefinition

    将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));
            ...........
        }
    }
    

      

  • 相关阅读:
    android Context 持有导致的内存泄漏
    android PreferenceFragment
    android 修改 SwitchPreferenceCompat 高度,内边距,字体大小
    Android MPAndroidChart RadarChart (蜘蛛网图)
    Bugtags 测试平台(支持ios、android)
    BlockCanary 一个轻量的,非侵入式的性能监控组件(阿里)
    RecyclerView item 状态错乱
    RecyclerView android:layout_width="match_parent" 无效
    android-async-http cancelRequests
    Android MultiDex
  • 原文地址:https://www.cnblogs.com/sleepingDogs/p/11085436.html
Copyright © 2011-2022 走看看