zoukankan      html  css  js  c++  java
  • Mybatis源码之XXMapper.java的扫描,然后注册IOC容器

    xxMapper的扫描,然后注册IOC容器

    注解中@Import的类获取

    先看注解中@Import的类是如何获取。首先启动类中有@SpringBootApplication、@MapperScan注解,其中在ConfigurationClassParser#doProcessConfigurationClass()中会进行对@Import的处理,去调用processImports方法。

    在看processImports之前,先看下启动类@MapperScan有什么作用,MapperScan上面的注解@Import又怎么import

    protected final SourceClass doProcessConfigurationClass(
    		ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
    		throws IOException {
    
    	if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
    		// Recursively process any member (nested) classes first
    		processMemberClasses(configClass, sourceClass, filter);
    	}
    
    	// Process any @PropertySource annotations
    	...
    
    	// Process any @ComponentScan annotations
        ...
    
    	// Process any @Import annotations
    	processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
    	
    	// Process individual @Bean methods
    	...
    	// Process default methods on interfaces
    	...
    	// Process superclass, if any
    	...
    }
    
    

    其中第三个入参为getImports(sourceClass),所以调用ConfigurationClassParser#getImports()

    /**
     * Returns {@code @Import} class, considering all meta-annotations.
     */
    private Set<SourceClass> getImports(SourceClass sourceClass) throws IOException {
    	Set<SourceClass> imports = new LinkedHashSet<>();
    	Set<SourceClass> visited = new LinkedHashSet<>();
    	collectImports(sourceClass, imports, visited);
    	return imports;
    }
    

    再调用ConfigurationClassParser#collectImports()。所以先sourceClass为启动类,先对sourceClass.getAnnotations()获得的MapperScan进行判断,发现注解名字不是Import,继续把MapperScan作为sourceClass,从而此次获取注解中属性值MapperScannerRegistrar

    private void collectImports(SourceClass sourceClass, Set<SourceClass> imports, Set<SourceClass> visited)
    		throws IOException {
    
    	if (visited.add(sourceClass)) {
    		for (SourceClass annotation : sourceClass.getAnnotations()) {
    			String annName = annotation.getMetadata().getClassName();
    			if (!annName.equals(Import.class.getName())) {
    				collectImports(annotation, imports, visited);
    			}
    		}
    		imports.addAll(sourceClass.getAnnotationAttributes(Import.class.getName(), "value"));
    	}
    }
    

    @MapperScan的源码

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    @Documented
    @Import(MapperScannerRegistrar.class)
    @Repeatable(MapperScans.class)
    public @interface MapperScan {
    
      /**
       * Alias for the {@link #basePackages()} attribute. Allows for more concise annotation declarations e.g.:
       * {@code @MapperScan("org.my.pkg")} instead of {@code @MapperScan(basePackages = "org.my.pkg"})}.
       *
       * @return base package names
       */
      String[] value() default {};
    }
    
    将@Import注解的类先在ConfigurationClass.importBeanDefinitionRegistrars中进行存储

    接下来可以继续processImports分析。从上面分析可知,因为importCandidates会传入MapperScannerRegistrar,而它实现了ImportBeanDefinitionRegistrar

    public class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware {
    }
    

    所以会在ConfigurationClass.importBeanDefinitionRegistrars中进行缓存

    private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
    		Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
    		boolean checkForCircularImports) {
    
    	if (checkForCircularImports && isChainedImportOnStack(configClass)) {
    		......
    	}
    	else {
    		this.importStack.push(configClass);
    		try {
    			for (SourceClass candidate : importCandidates) {
    				......
    				
    				}
    				else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
    					// Candidate class is an ImportBeanDefinitionRegistrar ->
    					// delegate to it to register additional bean definitions
    					Class<?> candidateClass = candidate.loadClass();
    					ImportBeanDefinitionRegistrar registrar =
    							ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
    									this.environment, this.resourceLoader, this.registry);
    					configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
    				}
    			}
    		}
    	}
    }
    

    下面是ConfigurationClass类源码

    private final Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> importBeanDefinitionRegistrars =
    		new LinkedHashMap<>();
    
    public void addImportBeanDefinitionRegistrar(ImportBeanDefinitionRegistrar registrar, AnnotationMetadata importingClassMetadata) {
    	this.importBeanDefinitionRegistrars.put(registrar, importingClassMetadata);
    }
    
    loadBeanDefinitionsFromRegistrars处理MapperScannerRegistrar

    上面将MapperScannerRegistrar 在ConfigurationClass.importBeanDefinitionRegistrars中进行存储,所以在对BeanDefinition加载注册时,会进行loadBeanDefinitionsFromRegistrars处理

    先贴下调用到此步的代码:

    ConfigurationClassParser类中:
    public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
    		...
    		//上面分析都是通过此入口调用的,将自动配置一些类都放到ConfigurationClassParser.configurationClasses中
            parser.parse(candidates);
            ...
            //进行BeanDefinition的解析注册入口
            this.reader.loadBeanDefinitions(configClasses);
    }
    
    ConfigurationClassBeanDefinitionReader类中:
    public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
    	TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
    	for (ConfigurationClass configClass : configurationModel) {
    		loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
    	}
    }
    
    ConfigurationClassBeanDefinitionReader类中:
    private void loadBeanDefinitionsForConfigurationClass(
    		ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
        ......
    	loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
    }
    			
    

    下面开始分析loadBeanDefinitionsFromRegistrars中过程。
    遍历获取registrar,然后去调用MapperScannerRegistrar#registerBeanDefinitions()

    private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
    	registrars.forEach((registrar, metadata) ->
    			registrar.registerBeanDefinitions(metadata, this.registry, this.importBeanNameGenerator));
    }
    

    在MapperScannerRegistrar#registerBeanDefinitions()将添加此BeanDefinition中basePackage属性值。

    public class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware {
    
      @Override
      public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        AnnotationAttributes mapperScanAttrs = AnnotationAttributes
            .fromMap(importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName()));
        if (mapperScanAttrs != null) {
          registerBeanDefinitions(importingClassMetadata, mapperScanAttrs, registry,
              generateBaseBeanName(importingClassMetadata, 0));
        }
      }
      
      void registerBeanDefinitions(AnnotationMetadata annoMeta, AnnotationAttributes annoAttrs,
          BeanDefinitionRegistry registry, String beanName) {
        //Bean类型为MapperScannerConfigurer.class
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MapperScannerConfigurer.class);
        ......
    
        List<String> basePackages = new ArrayList<>();
        basePackages.addAll(
            Arrays.stream(annoAttrs.getStringArray("value")).filter(StringUtils::hasText).collect(Collectors.toList()));
    
        basePackages.addAll(Arrays.stream(annoAttrs.getStringArray("basePackages")).filter(StringUtils::hasText)
            .collect(Collectors.toList()));
    
        basePackages.addAll(Arrays.stream(annoAttrs.getClassArray("basePackageClasses")).map(ClassUtils::getPackageName)
            .collect(Collectors.toList()));
    
        if (basePackages.isEmpty()) {
          basePackages.add(getDefaultBasePackage(annoMeta));
        }
    
        builder.addPropertyValue("basePackage", StringUtils.collectionToCommaDelimitedString(basePackages));
        //将  启动类全路径#MapperScannerRegistrar#0
        registry.registerBeanDefinition(beanName, builder.getBeanDefinition());
    
      }
    }
    

    最后将beanName为 启动类全路径#MapperScannerRegistrar#0在IOC容器中进行注册,Bean类型为MapperScannerConfigurer.class
    名字生成逻辑是:

    private static String generateBaseBeanName(AnnotationMetadata importingClassMetadata, int index) {
        return importingClassMetadata.getClassName() + "#" + MapperScannerRegistrar.class.getSimpleName() + "#" + index;
    }
    
    @MapperScan注解中package下文件扫描并注册IOC容器

    回到PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(). 此次再去通过type(BeanDefinitionRegistryPostProcessor.class)能获取到上面存储的BeanDefinitionRegistryPostProcessor,此时再去invokeBeanDefinitionRegistryPostProcessors

    // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
    boolean reiterate = true;
    while (reiterate) {
    	reiterate = false;
    	postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
    	for (String ppName : postProcessorNames) {
    		if (!processedBeans.contains(ppName)) {
    			currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
    			processedBeans.add(ppName);
    			reiterate = true;
    		}
    	}
    	sortPostProcessors(currentRegistryProcessors, beanFactory);
    	registryProcessors.addAll(currentRegistryProcessors);
    	//主要
    	invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
    	currentRegistryProcessors.clear();
    }
    

    此时postProcessor类型为上一步分析的MapperScannerConfigurer

    private static void invokeBeanDefinitionRegistryPostProcessors(
    		Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry, ApplicationStartup applicationStartup) {
    	for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
    		
    		postProcessor.postProcessBeanDefinitionRegistry(registry);
    		
    	}
    }
    

    调用MapperScannerConfigurer#postProcessBeanDefinitionRegistry(),对package中类进行扫描

      @Override
      public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
        if (this.processPropertyPlaceHolders) {
          processPropertyPlaceHolders();
        }
    
        ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
        ......
        scanner.scan(
            StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS));
      }
    

    此时仍然调用spring的ClassPathBeanDefinitionScanner#scan()

    public int scan(String... basePackages) {
    	int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
    
    	doScan(basePackages);
        ......
    }
    

    实际工作的是doscan,调用ClassPathMapperScanner#doScan(),再调用ClassPathBeanDefinitionScanner#doScan()

      @Override
      public Set<BeanDefinitionHolder> doScan(String... basePackages) {
        Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);
        ......
      }
    

    将@MapperScan注解package下类注册到IOC容器

    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) {
    		Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
    		for (BeanDefinition candidate : candidates) {
    			ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
    			
    			if (checkCandidate(beanName, candidate)) {
    				BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
    				definitionHolder =
    						AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
    				beanDefinitions.add(definitionHolder);
    			    //package下的mapper注册到IOC容器
    			    registerBeanDefinition(definitionHolder, this.registry);
    			}
    		}
    	}
    	return beanDefinitions;
    }
    

    xxMapper代理类的生成

    调用链:

    AbstractBeanFactory#getBean() --> AbstractBeanFactory#doGetBean() --> AbstractAutowireCapableBeanFactory#getObjectForBeanInstance() --> AbstractBeanFactory#getObjectForBeanInstance() --> FactoryBeanRegistrySupport#getObjectFromFactoryBean() --> FactoryBeanRegistrySupport#doGetObjectFromFactoryBean() --> MapperFactoryBean#getObject() --> SqlSessionTemplate#getMapper() --> Configuration#getMapper() --> MapperRegistry#getMapper() --> MapperProxyFactory#newInstance()

    在AbstractBeanFactory#doGetBean() 创建bean 对象后,调用getObjectForBeanInstance,由于xxMapper是非&开头的FactoryBean,所以执行getObjectFromFactoryBean逻辑代码

    // Create bean instance.
    if (mbd.isSingleton()) {
    	sharedInstance = getSingleton(beanName, () -> {
    		try {
    			return createBean(beanName, mbd, args);
    		}
    		...
    	});
    	bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    }
    

    AbstractBeanFactory#getObjectForBeanInstance()

    protected Object getObjectForBeanInstance(
    		Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
    
    	// Don't let calling code try to dereference the factory if the bean isn't a factory.
    	//name为 & 开头的FactoryBean
    	if (BeanFactoryUtils.isFactoryDereference(name)) {
    		......
    		return beanInstance;
    	}
    
    	// Now we have the bean instance, which may be a normal bean or a FactoryBean.
    	// If it's a FactoryBean, we use it to create a bean instance, unless the
    	// caller actually wants a reference to the factory.
    	if (!(beanInstance instanceof FactoryBean)) {
    		return beanInstance;
    	}
    
    	Object object = null;
    	if (mbd != null) {
    		mbd.isFactoryBean = true;
    	}
    	else {
    		object = getCachedObjectForFactoryBean(beanName);
    	}
    	if (object == null) {
    		// Return bean instance from factory.
    		FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
    		// Caches object obtained from FactoryBean if it is a singleton.
    		if (mbd == null && containsBeanDefinition(beanName)) {
    			mbd = getMergedLocalBeanDefinition(beanName);
    		}
    		boolean synthetic = (mbd != null && mbd.isSynthetic());
    		object = getObjectFromFactoryBean(factory, beanName, !synthetic);
    	}
    	return object;
    }
    

    最后再看下MapperProxyFactory#newInstance(), 调用JDK Proxy.newProxyInstance()生成代理类,其中是由MapperProxy实现InvocationHandler,构造器中将SqlSession和被代理的mapperInterface传入

    protected T newInstance(MapperProxy<T> mapperProxy) {
        return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
    }
    
    public class MapperProxy<T> implements InvocationHandler, Serializable {
    
      public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface, Map<Method, MapperMethodInvoker> methodCache) {
        this.sqlSession = sqlSession;
        this.mapperInterface = mapperInterface;
        this.methodCache = methodCache;
      }
    
      @Override
      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        try {
          if (Object.class.equals(method.getDeclaringClass())) {
            return method.invoke(this, args);
          } else {
            return cachedInvoker(method).invoke(proxy, method, args, sqlSession);
          }
        } catch (Throwable t) {
          throw ExceptionUtil.unwrapThrowable(t);
        }
      }
    }
    
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出。
  • 相关阅读:
    Java-使用IO流对大文件进行分割和分割后的合并
    Java-单向链表算法
    Java-二分查找算法
    Java-二叉树算法
    Java-对象比较器
    Android中Activity的四种开发模式
    Struts2工作原理
    C++实现单例模式
    数组中有一个数字出现的次数超过数组的一半,请找出这个数字
    c++ enum用法【转】
  • 原文地址:https://www.cnblogs.com/caozibiao/p/14040653.html
Copyright © 2011-2022 走看看