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);
    }
  }
}
posted @ 2020-11-26 09:38  曹自标  阅读(263)  评论(0编辑  收藏  举报