Mybatis启动加载过程一:自动装配类的加载
前言
参考代码
根据SpringBoot的自动装配机制,加载到了mybatis的自动装配类MybatisAutoConfiguration,然后由 ConfigurationClassBeanDefinitionReader类调用loadBeanDefinitions方法对configClass自动装配类进行加载。
MyBatis自动装配类的加载
ConfigurationClassBeanDefinitionReader.loadBeanDefinitions根据configClass加载BeanDefinition
在Mybatis的自动装配过程中,首先我们加载到了MyBatisAutoConfiguration类,然后调用isImported方法判断当前配置类是否是由配置类引入而来,此处MyBatisAutoConfiguration的引入类是启动类MybatisApplication,然后调用registerBeanDefinitionForImportedConfigurationClass方法注册MyBatisAutoConfigurationBeanDefinition,随后调用getBeanMethods方法获取当前配置类中定义的Bean配置类,然后调用loadBeanDefinitionsForBeanMethod方法加载BeanMethod定义的BeanDefinition;
在调用loadBeanDefinitionsForBeanMethod方法的过程中,首先调用了条件评估者的shouldSkip方法来判断当前Bean是否应该加载,判断过程依次为:一:当前方法上是否有@Conditional注解,如果没有,不用跳过 二:获取方法上的对应注解,并根据注解实例化注解对应的条件类实例对象。
此处根据@ConditionalOnMissingBean注解加载的对象是OnBeanCondition对象,然后调用OnBeanCondition对象的父类SpringBootCondition的matches方法,判断当前环境是否满足条件;
在matches方法中,根据模板方法,首先调用了OnBeanCondition对象的getMatchOutcome方法,来获取符合条件的输出对象。在getMatchOutcome方法中,根据注解的类型,此处的注解类型为ConditionalOnMissingBean,所以调用满足此注解的逻辑,首先根据加载类类型从BeanFactory工厂对象中获取已加载的BeanDefinition,如果有任一 一个Bean符合对象,则构建一个匹配失败的结果,否则返回一个匹配成功的结果。
而在ConditionalOnBean类型的注解下:判断如果所有需要的类没有加载完毕,则构建一个匹配失败的结果,并将需要匹配的BeanName返回给调用者,否则返回匹配成功的结果。
而在ConditionalOnSingleCandidate注解条件下,需要的是只有一个满足条件的BeanDefinition,所以当返回结果为空或者需要的Bean Size>1的时候,会返回匹配失败的结果,否则返回成功。
当判断完当前Bean满足条件注入的时候,赋值Bean名称,如果bean名称为空,则将当前方法的名称作为Bean名称,设置自动织入模式为构造函数织入,加载完BeanMethod方法根据条件匹配加载的BeanDefinition之后,
继续调用loadBeanDefinitionsFromImportedResources方法从引入资源文件中加载BeanDefinition;
调用loadBeanDefinitionsFromRegistrars方法,从ImportBeanDefinitionRegistrar注册器中引入BeanDefinition,此处注入的是MybatisProperties对象。
class ConfigurationClassBeanDefinitionReader {
// 读取configurationModel,根据其内容向注册中心注册bean定义
public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
for (ConfigurationClass configClass : configurationModel) {
loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
}
}
//读取特定的ConfigurationClass,为类本身及其所有bean方法注册bean定义。
private void loadBeanDefinitionsForConfigurationClass(
ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
if (trackedConditionEvaluator.shouldSkip(configClass)) {
String beanName = configClass.getBeanName();
if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
this.registry.removeBeanDefinition(beanName);
}
this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
return;
}
// 查看该配置类的引入类,当前引入类是mybatisApplication启动类
if (configClass.isImported()) {
// 为引入的配置类注册Bean定义
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
// 获取BeanMethods,并从beanMethod中加载BeanDefinition
// sqlSessionFactory(javax.sql.DataSource)
// sqlSessionTemplate(org.apache.ibatis.session.SqlSessionFactory)
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
loadBeanDefinitionsForBeanMethod(beanMethod);
}
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
// 注册Bean定义
private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) {
AnnotationMetadata metadata = configClass.getMetadata();
AnnotatedGenericBeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata);
ScopeMetadata scopeMetadata = scopeMetadataResolver.resolveScopeMetadata(configBeanDef);
configBeanDef.setScope(scopeMetadata.getScopeName());
String configBeanName = this.importBeanNameGenerator.generateBeanName(configBeanDef, this.registry);
// 处理BeanDefinition通用属性注解
AnnotationConfigUtils.processCommonDefinitionAnnotations(configBeanDef, metadata);
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(configBeanDef, configBeanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
// 注册Bean定义
this.registry.registerBeanDefinition(definitionHolder.getBeanName(), definitionHolder.getBeanDefinition());
configClass.setBeanName(configBeanName);
if (logger.isTraceEnabled()) {
logger.trace("Registered bean definition for imported class '" + configBeanName + "'");
}
}
// 从BeanMethod中获取BeanDefinition,已SqlSessionFactory为例
private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
ConfigurationClass configClass = beanMethod.getConfigurationClass();
MethodMetadata metadata = beanMethod.getMetadata();
String methodName = metadata.getMethodName();
// 我们需要将bean标记为被它的条件跳过吗?
if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) {
configClass.skippedBeanMethods.add(methodName);
return;
}
if (configClass.skippedBeanMethods.contains(methodName)) {
return;
}
AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);
Assert.state(bean != null, "No @Bean annotation attributes");
// Consider name and any aliases 确定Bean的名称,如果Bean的名称为空,则以methodName为bean名称。
List<String> names = new ArrayList<>(Arrays.asList(bean.getStringArray("name")));
String beanName = (!names.isEmpty() ? names.remove(0) : methodName);
// Register aliases even when overridden
for (String alias : names) {
this.registry.registerAlias(beanName, alias);
}
// Has this effectively been overridden before (e.g. via XML)? 这在以前被有效地重写过吗
if (isOverriddenByExistingDefinition(beanMethod, beanName)) {
if (beanName.equals(beanMethod.getConfigurationClass().getBeanName())) {
throw new BeanDefinitionStoreException(beanMethod.getConfigurationClass().getResource().getDescription(),
beanName, "Bean name derived from @Bean method '" + beanMethod.getMetadata().getMethodName() +
"' clashes with bean name for containing configuration class; please make those names unique!");
}
return;
}
ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata, beanName);
beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));
if (metadata.isStatic()) {
// static @Bean method
if (configClass.getMetadata() instanceof StandardAnnotationMetadata) {
beanDef.setBeanClass(((StandardAnnotationMetadata) configClass.getMetadata()).getIntrospectedClass());
}
else {
beanDef.setBeanClassName(configClass.getMetadata().getClassName());
}
beanDef.setUniqueFactoryMethodName(methodName);
}
else {
// instance @Bean method 设置当前BeanDefinition的工厂Bean名称,此时是MybatisAutoConfiguration
beanDef.setFactoryBeanName(configClass.getBeanName());
beanDef.setUniqueFactoryMethodName(methodName);
}
if (metadata instanceof StandardMethodMetadata) {
beanDef.setResolvedFactoryMethod(((StandardMethodMetadata) metadata).getIntrospectedMethod());
}
// 设置织入模式为构造织入
beanDef.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
beanDef.setAttribute(org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor.
SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);
// 处理通用注解属性
AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);
Autowire autowire = bean.getEnum("autowire");
if (autowire.isAutowire()) {
beanDef.setAutowireMode(autowire.value());
}
boolean autowireCandidate = bean.getBoolean("autowireCandidate");
if (!autowireCandidate) {
beanDef.setAutowireCandidate(false);
}
String initMethodName = bean.getString("initMethod");
if (StringUtils.hasText(initMethodName)) {
beanDef.setInitMethodName(initMethodName);
}
String destroyMethodName = bean.getString("destroyMethod");
beanDef.setDestroyMethodName(destroyMethodName);
// Consider scoping
ScopedProxyMode proxyMode = ScopedProxyMode.NO;
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(metadata, Scope.class);
if (attributes != null) {
beanDef.setScope(attributes.getString("value"));
proxyMode = attributes.getEnum("proxyMode");
if (proxyMode == ScopedProxyMode.DEFAULT) {
proxyMode = ScopedProxyMode.NO;
}
}
// Replace the original bean definition with the target one, if necessary
BeanDefinition beanDefToRegister = beanDef;
if (proxyMode != ScopedProxyMode.NO) {
BeanDefinitionHolder proxyDef = ScopedProxyCreator.createScopedProxy(
new BeanDefinitionHolder(beanDef, beanName), this.registry,
proxyMode == ScopedProxyMode.TARGET_CLASS);
beanDefToRegister = new ConfigurationClassBeanDefinition(
(RootBeanDefinition) proxyDef.getBeanDefinition(), configClass, metadata, beanName);
}
if (logger.isTraceEnabled()) {
logger.trace(String.format("Registering bean definition for @Bean method %s.%s()",
configClass.getMetadata().getClassName(), beanName));
}
this.registry.registerBeanDefinition(beanName, beanDefToRegister);
}
}
ConditionEvaluator 条件判断者
class ConditionEvaluator {
//根据注解上的条件判断是否跳过注册
public boolean shouldSkip(@Nullable AnnotatedTypeMetadata metadata, @Nullable ConfigurationPhase phase) {
// 当不存在@Condition注解的时候,不跳过
if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) {
return false;
}
if (phase == null) {
if (metadata instanceof AnnotationMetadata &&
ConfigurationClassUtils.isConfigurationCandidate((AnnotationMetadata) metadata)) {
return shouldSkip(metadata, ConfigurationPhase.PARSE_CONFIGURATION);
}
return shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN);
}
List<Condition> conditions = new ArrayList<>();
// 获取注解上的条件对象
for (String[] conditionClasses : getConditionClasses(metadata)) {
for (String conditionClass : conditionClasses) {
Condition condition = getCondition(conditionClass, this.context.getClassLoader());
conditions.add(condition);
}
}
AnnotationAwareOrderComparator.sort(conditions);
for (Condition condition : conditions) {
ConfigurationPhase requiredPhase = null;
if (condition instanceof ConfigurationCondition) {
requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
}
if ((requiredPhase == null || requiredPhase == phase) && !condition.matches(this.context, metadata)) {
return true;
}
}
return false;
}
// 从元信息中获取@Conditional注解信息
private List<String[]> getConditionClasses(AnnotatedTypeMetadata metadata) {
MultiValueMap<String, Object> attributes = metadata.getAllAnnotationAttributes(Conditional.class.getName(), true);
Object values = (attributes != null ? attributes.get("value") : null);
return (List<String[]>) (values != null ? values : Collections.emptyList());
}
// 实例化条件对象
private Condition getCondition(String conditionClassName, @Nullable ClassLoader classloader) {
Class<?> conditionClass = ClassUtils.resolveClassName(conditionClassName, classloader);
return (Condition) BeanUtils.instantiateClass(conditionClass);
}
}
SpringBootCondition.matches判断当前元信息在当前条件下是否满足
public abstract class SpringBootCondition implements Condition {
public final boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// metadata = sqlSessionTemplate
String classOrMethodName = getClassOrMethodName(metadata);
try {
//得到符合条件的输出
ConditionOutcome outcome = getMatchOutcome(context, metadata);
//得到一个没有符合条件的结果
logOutcome(classOrMethodName, outcome);
recordEvaluation(context, classOrMethodName, outcome);
return outcome.isMatch();
}
catch (NoClassDefFoundError ex) {
throw new IllegalStateException("Could not evaluate condition on " + classOrMethodName + " due to "
+ ex.getMessage() + " not found. Make sure your own configuration does not rely on "
+ "that class. This can also happen if you are "
+ "@ComponentScanning a springframework package (e.g. if you "
+ "put a @ComponentScan in the default package by mistake)", ex);
}
catch (RuntimeException ex) {
throw new IllegalStateException("Error processing condition on " + getName(metadata), ex);
}
}
}
OnBeanCondition及其内部类Spec搜索规范
@Order(Ordered.LOWEST_PRECEDENCE)
class OnBeanCondition extends FilteringSpringBootCondition implements ConfigurationCondition {
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
ConditionMessage matchMessage = ConditionMessage.empty();
//得到元信息上的注解信息:SqlSessionTemplate的元注解信息有 :@Bean ;@ConditionalOnMissingBean,
MergedAnnotations annotations = metadata.getAnnotations();
if (annotations.isPresent(ConditionalOnBean.class)) {
Spec<ConditionalOnBean> spec = new Spec<>(context, metadata, annotations, ConditionalOnBean.class);
MatchResult matchResult = getMatchingBeans(context, spec);
if (!matchResult.isAllMatched()) {
String reason = createOnBeanNoMatchReason(matchResult);
return ConditionOutcome.noMatch(spec.message().because(reason));
}
matchMessage = spec.message(matchMessage).found("bean", "beans").items(Style.QUOTE,
matchResult.getNamesOfAllMatches());
}
if (metadata.isAnnotated(ConditionalOnSingleCandidate.class.getName())) {
// 构建一个规范:从基础注释中提取的搜索规范
Spec<ConditionalOnSingleCandidate> spec = new SingleCandidateSpec(context, metadata, annotations);
MatchResult matchResult = getMatchingBeans(context, spec);
if (!matchResult.isAllMatched()) {
return ConditionOutcome.noMatch(spec.message().didNotFind("any beans").atAll());
}
else if (!hasSingleAutowireCandidate(context.getBeanFactory(), matchResult.getNamesOfAllMatches(),
spec.getStrategy() == SearchStrategy.ALL)) {
return ConditionOutcome.noMatch(spec.message().didNotFind("a primary bean from beans")
.items(Style.QUOTE, matchResult.getNamesOfAllMatches()));
}
matchMessage = spec.message(matchMessage).found("a primary bean from beans").items(Style.QUOTE,
matchResult.getNamesOfAllMatches());
}
// 此处我们进入ConditionalOnMissingBean逻辑判断
if (metadata.isAnnotated(ConditionalOnMissingBean.class.getName())) {
Spec<ConditionalOnMissingBean> spec = new Spec<>(context, metadata, annotations,
ConditionalOnMissingBean.class);
MatchResult matchResult = getMatchingBeans(context, spec);
if (matchResult.isAnyMatched()) {
String reason = createOnMissingBeanNoMatchReason(matchResult);
return ConditionOutcome.noMatch(spec.message().because(reason));
}
matchMessage = spec.message(matchMessage).didNotFind("any beans").atAll();
}
return ConditionOutcome.match(matchMessage);
}
// 获取符合的Bean
protected final MatchResult getMatchingBeans(ConditionContext context, Spec<?> spec) {
ClassLoader classLoader = context.getClassLoader();
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
boolean considerHierarchy = spec.getStrategy() != SearchStrategy.CURRENT;
Set<Class<?>> parameterizedContainers = spec.getParameterizedContainers();
if (spec.getStrategy() == SearchStrategy.ANCESTORS) {
BeanFactory parent = beanFactory.getParentBeanFactory();
Assert.isInstanceOf(ConfigurableListableBeanFactory.class, parent,
"Unable to use SearchStrategy.ANCESTORS");
beanFactory = (ConfigurableListableBeanFactory) parent;
}
MatchResult result = new MatchResult();
Set<String> beansIgnoredByType = getNamesOfBeansIgnoredByType(classLoader, beanFactory, considerHierarchy,
spec.getIgnoredTypes(), parameterizedContainers);
for (String type : spec.getTypes()) {
Collection<String> typeMatches = getBeanNamesForType(classLoader, considerHierarchy, beanFactory, type,
parameterizedContainers);
Iterator<String> iterator = typeMatches.iterator();
while (iterator.hasNext()) {
String match = iterator.next();
if (beansIgnoredByType.contains(match) || ScopedProxyUtils.isScopedTarget(match)) {
iterator.remove();
}
}
if (typeMatches.isEmpty()) {
result.recordUnmatchedType(type);
}
else {
result.recordMatchedType(type, typeMatches);
}
}
for (String annotation : spec.getAnnotations()) {
Set<String> annotationMatches = getBeanNamesForAnnotation(classLoader, beanFactory, annotation,
considerHierarchy);
annotationMatches.removeAll(beansIgnoredByType);
if (annotationMatches.isEmpty()) {
result.recordUnmatchedAnnotation(annotation);
}
else {
result.recordMatchedAnnotation(annotation, annotationMatches);
}
}
for (String beanName : spec.getNames()) {
if (!beansIgnoredByType.contains(beanName) && containsBean(beanFactory, beanName, considerHierarchy)) {
result.recordMatchedName(beanName);
}
else {
result.recordUnmatchedName(beanName);
}
}
return result;
}
private static class Spec<A extends Annotation> {
private final ClassLoader classLoader;
private final Class<? extends Annotation> annotationType;
private final Set<String> names;
private final Set<String> types;
private final Set<String> annotations;
private final Set<String> ignoredTypes;
private final Set<Class<?>> parameterizedContainers;
private final SearchStrategy strategy;
Spec(ConditionContext context, AnnotatedTypeMetadata metadata, MergedAnnotations annotations,
Class<A> annotationType) {
MultiValueMap<String, Object> attributes = annotations.stream(annotationType)
.filter(MergedAnnotationPredicates.unique(MergedAnnotation::getMetaTypes))
.collect(MergedAnnotationCollectors.toMultiValueMap(Adapt.CLASS_TO_STRING));
MergedAnnotation<A> annotation = annotations.get(annotationType);
this.classLoader = context.getClassLoader();
this.annotationType = annotationType;
this.names = extract(attributes, "name");
this.annotations = extract(attributes, "annotation");
this.ignoredTypes = extract(attributes, "ignored", "ignoredType");
this.parameterizedContainers = resolveWhenPossible(extract(attributes, "parameterizedContainer"));
this.strategy = annotation.getValue("search", SearchStrategy.class).orElse(null);
Set<String> types = extractTypes(attributes);
BeanTypeDeductionException deductionException = null;
if (types.isEmpty() && this.names.isEmpty()) {
try {
// 推断bean类型:org.mybatis.spring.SqlSessionTemplate
types = deducedBeanType(context, metadata);
}
catch (BeanTypeDeductionException ex) {
deductionException = ex;
}
}
this.types = types;
validate(deductionException);
}
}
ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsFromRegistrars注册器注册BeanDefinition
此处由于@EnableConfigurationProperties注解的功能,引入了EnableConfigurationPropertiesRegistrar注册器,所以在MybatisAutoConfiguration注解中,调用EnableConfigurationPropertiesRegistrar的registerBeanDefinitions方法,在方法中构建了ConfigurationPropertiesBeanRegistrar配置属性Bean注册器,随后先调用EnableConfigurationPropertiesRegistrar的getTypes方法从注解信息中获取需要注册的type类型,此处获取到的type类型为MybatisProperties,随后调用ConfigurationPropertiesBeanRegistrar的register方法进行注册;
首先根据ConfigurationProperties构造一个注解对象,然后调用register方法进行注册。至此由MybatisAutoConfiguration自动装配类注册的BeanDefinition就注册完毕了。
class ConfigurationClassBeanDefinitionReader {
private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
registrars.forEach((registrar, metadata) ->
registrar.registerBeanDefinitions(metadata, this.registry, this.importBeanNameGenerator));
}
}
ImportBeanDefinitionRegistrar
public interface ImportBeanDefinitionRegistrar {
default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry,
BeanNameGenerator importBeanNameGenerator) {
registerBeanDefinitions(importingClassMetadata, registry);
}
default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
}
}
EnableConfigurationPropertiesRegistrar注册器注册BeanDefinition
class EnableConfigurationPropertiesRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
registerInfrastructureBeans(registry);
registerMethodValidationExcludeFilter(registry);
ConfigurationPropertiesBeanRegistrar beanRegistrar = new ConfigurationPropertiesBeanRegistrar(registry);
getTypes(metadata).forEach(beanRegistrar::register);
}
private Set<Class<?>> getTypes(AnnotationMetadata metadata) {
return metadata.getAnnotations().stream(EnableConfigurationProperties.class)
.flatMap((annotation) -> Arrays.stream(annotation.getClassArray(MergedAnnotation.VALUE)))
.filter((type) -> void.class != type).collect(Collectors.toSet());
}
}
ConfigurationPropertiesBeanRegistrar
final class ConfigurationPropertiesBeanRegistrar {
ConfigurationPropertiesBeanRegistrar(BeanDefinitionRegistry registry) {
this.registry = registry;
this.beanFactory = (BeanFactory) this.registry;
}
void register(Class<?> type) {
MergedAnnotation<ConfigurationProperties> annotation = MergedAnnotations
.from(type, SearchStrategy.TYPE_HIERARCHY).get(ConfigurationProperties.class);
register(type, annotation);
}
}
MyBatis加载BeanDefinition的实例化
经过了自动装配的加载机制,有关MyBatis启动的相关BeanDefinition已加载完毕,现在我们将程序运行到finishBeanFactoryInitialization处,看一下相关BeanDefinition的实例化,见下一篇