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