回目录 《spring boot 源码解析》
# keyword:
BeanDefinition配置信息
=》BeanDefinitionReader=>BeanDefinition
=>BeanFactoryPostProcessor
=>BeanFactory:反射实例化 Construction ctor=Class.getConstruction(); TestObj obj=ctor.newInstance();
=>BeanPostProcessor
=>初始化 设置属性,解决依赖
org.springframework.beans.factory.support.DefaultListableBeanFactory
/** Map of bean definition objects, keyed by bean name */ private final Map<String, BeanDefinition> beanDefinitionMap
/** Map from dependency type to corresponding autowired value */
resolvableDependencies
容器:
GenericApplicationContext extends AbstractApplicationContext
getEnvironment 环境参数 配置文件信息 getBeanFactory beansMap
工厂:
DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory(<<DefaultSingletonBeanRegistry)
implements ConfigurableListableBeanFactory
整理思路:
初始化上下文和工厂,
读取配置文件信息,放入
读取bean信息,实例化bean,初始化bean,设置bean属性包括其依赖的自动装配;
starter
@SpringBootApplication(scanBasePackages = { "com.lyhistory.mybatis.springboot.mybatis_starter"})
public class StarterMain {
public static void main(String[] args) {
SpringApplication.run(StarterMain.class, args);
}
}
# 调用SpringApp构造方法
PrimarySource: StarterMain.class
public SpringApplication(Class<?>... primarySources) {
this(null, primarySources);
}
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
# spring.fatories=>ApplicationContextInitializer
首先重要的一步是加载配置信息: org.springframework.context.ApplicationContextInitializer
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
层层调用
Set<String> names = new LinkedHashSet<>(
SpringFactoriesLoader.loadFactoryNames(type, classLoader));
这个SpringFactoriesLoader.loadFactoryNames方法很重要,后面还会出现,都是从META-INF/spring.factories里面加载信息!
比如后面AutoConfigurationImportSelector就会读取EnableAutoConfiguration
# deduceMainApplicationClass
通过main方法判断主程序
# 调用run方法
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(
SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}
两个东西比较重要ConfigurableApplicationContext和 SpringApplicationRunListeners
# prepareEnvironment
发布事件publish EVENT: ApplicationEnvironmentPreparedEvent
EnvironmentPostProcessor
接收事件org.springframework.boot.context.config.ConfigFileApplicationListener: onApplicationEvent
for (EnvironmentPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessEnvironment(event.getEnvironment(),
event.getSpringApplication());
}
调用所有实现了org.springframework.boot.env.EnvironmentPostProcessor接口的postProcessEnvironment方法
主要是往env.getPropertySources()塞数据
后面还有个地方会往enve的这个propertySources塞数据,就是ConfigurationClassParser.doProcessConfigurationClass的“第一步”
# createApplicationContext
(ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass)
contextClass是org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext
最终调用org.springframework.boot.web.servlet.context.AnnotationConfigUtils的registerAnnotationConfigProcessors方法,注册一堆初始的beanDefinition到this.beanFactory.registerBeanDefinition
CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME=org.springframework.context.annotation.internalConfigurationAnnotationProcessor
AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME=org.springframework.context.annotation.internalAutowiredAnnotationProcessor
REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME=org.springframework.context.annotation.internalRequiredAnnotationProcessor
COMMON_ANNOTATION_PROCESSOR_BEAN_NAME=org.springframework.context.annotation.internalCommonAnnotationProcessor
EVENT_LISTENER_PROCESSOR_BEAN_NAME=org.springframework.context.event.internalEventListenerProcessor
EVENT_LISTENER_FACTORY_BEAN_NAME=org.springframework.context.event.internalEventListenerFactory
# prepareContext
将入口主类注册到beanFactory的beanDefinitionMap
// Load the sources
load(context, sources.toArray(new Object[0]));
org.springframework.boot.BeanDefinitionLoader
if (source instanceof Class<?>) {
return load((Class<?>) source);
}
=>
if (isComponent(source)) {
this.annotatedReader.register(source);
return 1;
}
org.springframework.context.annotation.AnnotatedBeanDefinitionReader:
register=>registerBean=>doRegisterBean
=>beanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
=> org.springframework.context.support.AnnotationConfigServletWebServerApplicationContext(GenericApplicationContext):
registerBeanDefinition=>this.beanFactory.registerBeanDefinition 跟前面一样!
到此为止将主类StarterMain加载到容器,可以在beanDefinitionMap中看到
# refreshContext 进入spring之refresh十三步
private void refreshContext(ConfigurableApplicationContext context) {
refresh(context);
if (this.registerShutdownHook) {
try {
context.registerShutdownHook();
}
catch (AccessControlException ex) {
// Not allowed in some environments.
}
}
}
protected void refresh(ApplicationContext applicationContext) {
Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
((AbstractApplicationContext) applicationContext).refresh();
}
关键:((AbstractApplicationContext) applicationContext).refresh(); 注意下面调用super:从springboot进入到spring!!!
=>org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext extends GenericWebApplicationContext implements ConfigurableWebServerApplicationContext
@Override
public final void refresh() throws BeansException, IllegalStateException {
try {
super.refresh();
}
catch (RuntimeException ex) {
stopAndReleaseWebServer();
throw ex;
}
}
进入了:
org.springframework.context.support.AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
# 第三步 prepareBeanFactory
将环境Environment和system相关的信息放入工厂的manualSingletonNames(local beans)
# 第四步 postProcessBeanFactory
此时可以看一下现在beanFactory里面的beanDefinitionMap有什么
除了几个internal的Processor处理程序的bean和一个EventListener工厂的bean外,我们的主程序也作为bean存储其中;
看类型很明显,我们的主程序是Generic Bean类型,其他的都是Root Bean类型
beanDefinitionMap::
{org.springframework.context.annotation.internalConfigurationAnnotationProcessor=Root bean: class [org.springframework.context.annotation.ConfigurationClassPostProcessor];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.context.event.internalEventListenerFactory=Root bean: class [org.springframework.context.event.DefaultEventListenerFactory];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.context.event.internalEventListenerProcessor=Root bean: class [org.springframework.context.event.EventListenerMethodProcessor];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.context.annotation.internalAutowiredAnnotationProcessor=Root bean: class [org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.context.annotation.internalCommonAnnotationProcessor=Root bean: class [org.springframework.context.annotation.CommonAnnotationBeanPostProcessor];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, starterMain=Generic bean: class [com.lyhistory.mybatis.springboot.mybatis_starter.StarterMain];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null}
在进入下一步之前我们猜测,现在beanDefinitionMap还只有我们定义的一个主程序bean,接下来的思路应该是由主程序入手,递归出主程序扫描范围内的所有bean,如@Config,@Bean,@Controller,@Service,@Component等等,但是其他引入的starter中的bean呢,比如Mybatis的@Mapper,接下来我们看springboot读取这些bean信息的思路;
# 第五步:invokeBeanFactoryPostProcessors:
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
org.springframework.context.support.PostProcessorRegistrationDelegate
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
参数beanFactoryPostProcessors
[org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer$ConfigurationWarningsPostProcessor, org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer$CachingMetadataReaderFactoryPostProcessor, org.springframework.boot.context.config.ConfigFileApplicationListener$PropertySourceOrderingPostProcessor]
# 首先registryProcessor.postProcessBeanDefinitionRegistry:
org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory
不重要
# First: invokeBeanDefinitionRegistryPostProcessors
然后重要的来了:
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
返回:[org.springframework.context.annotation.internalConfigurationAnnotationProcessor],这就是前面prepare的
CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME=org.springframework.context.annotation.internalConfigurationAnnotationProcessor,参考AnnotationConfigUtils
接着就是根据这个internalConfigurationAnnotationProcessor从beanFactory中根据这个所谓的post processor name取出一个BeanDefinitionRegistryPostProcessor的实例,添加到当前的currentRegistryProcessors里面
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
//根据前面更新的currentRegistryProcessors,里面包含一个BeanDefinitionRegistryPostProcessor实例,调用该post processor
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
//清空当前的currentRegistryProcessors
currentRegistryProcessors.clear();
下面开始分析 invokeBeanDefinitionRegistryPostProcessors调用过程
=>org.springframework.context.annotation.ConfigurationClassPostProcessor(这个名字比较明显Configuration相关):
postProcessBeanDefinitionRegistry=>processConfigBeanDefinitions
/**
* Build and validate a configuration model based on the registry of
* {@link Configuration} classes.
*/
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
// Parse each @Configuration class
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
parser.parse(candidates);
parser.validate();
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
// Read the model and create bean definitions based on its content
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
candidates.clear();
if (registry.getBeanDefinitionCount() > candidateNames.length) {
String[] newCandidateNames = registry.getBeanDefinitionNames();
Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
Set<String> alreadyParsedClasses = new HashSet<>();
for (ConfigurationClass configurationClass : alreadyParsed) {
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
for (String candidateName : newCandidateNames) {
if (!oldCandidateNames.contains(candidateName)) {
BeanDefinition bd = registry.getBeanDefinition(candidateName);
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
!alreadyParsedClasses.contains(bd.getBeanClassName())) {
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
candidateNames = newCandidateNames;
}
}
while (!candidates.isEmpty());
// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
// Clear cache in externally provided MetadataReaderFactory; this is a no-op
// for a shared cache since it'll be cleared by the ApplicationContext.
((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
}
}
# 1.首先是parser.parse过程
=>org.springframework.context.annotation.ConfigurationClassParser:
注意这个类有个很重要的成员变量:
private final Map<ConfigurationClass, ConfigurationClass> configurationClasses = new LinkedHashMap<>();
后面所有解析出来的Bean的beanname和完整包名都会放里面
parse()
public void parse(Set<BeanDefinitionHolder> configCandidates) {
this.deferredImportSelectors = new LinkedList<>();
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {
if (bd instanceof AnnotatedBeanDefinition) {
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
}
else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
}
else {
parse(bd.getBeanClassName(), holder.getBeanName());
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
}
}
processDeferredImportSelectors();
}
上面方法分为两大步:
# 第一步 parse 解析AnnotatedBeanDefinition
调用到doProcessConfigurationClass这里是重点:
从主类开始递归!
// Process any @PropertySource annotations
前面说了prepareEnvironment可以往env.propertySource加载配置信息,这里也有一个修改点!(但是我暂时不知道怎么用的)
// Process any @ComponentScan annotations
=>org.springframework.context.annotation.ComponentScanAnnotationParser: parse
=>org.springframework.context.annotation.ClassPathBeanDefinitionScanner:
doScan=>registerBeanDefinition=>BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry);=>org.springframework.beans.factory.support.DefaultListableBeanFactory: registerBeanDefinition
if(hasBeanCreationStarted()){
this.beanDefinitionMap.put(beanName, beanDefinition);
}
// Process any @Import annotations
// Process any @ImportResource annotations
// Process individual @Bean methods
上面的各个步骤里都会调用processConfigurationClass这个方法,这个方法最终是将bean的信息写入到前面说的重要的成员变量configurationClasses
这一步做完之后,正常推理configurationClasses应该扫描到了根据主类获取的各个自定义bean,验证一下
{ConfigurationClass: beanName 'myBatisConfiguration', class path resource [com/lyhistory/mybatis/springboot/mybatis_starter/MyBatisConfiguration.class]=ConfigurationClass: beanName 'myBatisConfiguration', class path resource [com/lyhistory/mybatis/springboot/mybatis_starter/MyBatisConfiguration.class],
ConfigurationClass: beanName 'myBatisMapperScannerConfig', class path resource [com/lyhistory/mybatis/springboot/mybatis_starter/MyBatisMapperScannerConfig.class]=ConfigurationClass: beanName 'myBatisMapperScannerConfig', class path resource [com/lyhistory/mybatis/springboot/mybatis_starter/MyBatisMapperScannerConfig.class],
ConfigurationClass: beanName 'testController', class path resource [com/lyhistory/mybatis/springboot/mybatis_starter/TestController.class]=ConfigurationClass: beanName 'testController', class path resource [com/lyhistory/mybatis/springboot/mybatis_starter/TestController.class],
ConfigurationClass: beanName 'testService', class path resource [com/lyhistory/mybatis/springboot/mybatis_starter/TestService.class]=ConfigurationClass: beanName 'testService', class path resource [com/lyhistory/mybatis/springboot/mybatis_starter/TestService.class],
ConfigurationClass: beanName 'starterMain', com.lyhistory.mybatis.springboot.mybatis_starter.StarterMain=ConfigurationClass: beanName 'starterMain', com.lyhistory.mybatis.springboot.mybatis_starter.StarterMain}
# 第二步 processDeferredImportSelectors
for (DeferredImportSelectorGrouping grouping : groupings.values()) {
grouping.getImports().forEach(entry -> {
ConfigurationClass configurationClass = configurationClasses.get(entry.getMetadata());
try {
processImports(configurationClass, asSourceClass(configurationClass),
asSourceClasses(entry.getImportClassName()), false);
}
此处groupings只有一个:
{class org.springframework.boot.autoconfigure.AutoConfigurationImportSelector$AutoConfigurationGroup
=
org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorGrouping@22ebccb9}
所以通过grouping.getImports()
/**
* Return the imports defined by the group.
* @return each import with its associated configuration class
*/
public Iterable<Group.Entry> getImports() {
for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {
this.group.process(deferredImport.getConfigurationClass().getMetadata(),
deferredImport.getImportSelector());
}
return this.group.selectImports();
}
org.springframework.boot.autoconfigure.AutoConfigurationImportSelector:
process=>selectImports (这个是2.0旧版本,新版本2.1.4是 getAutoConfigurationEntry 不同版本)
先看下这个方法的最终返回值
[org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration
, org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration
, org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration
, org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration
, org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration
, org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration
, org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration
, org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration
, org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration
, org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration
, org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
, org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration
, org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration
, org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration
, org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration
, org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration
, org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration
, org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration
, org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration
, org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration
, org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration
, org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration
, org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration
, org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration
, org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration
, org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration
, org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration
, org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration
, org.mybatis.spring.boot.autoconfigure.MybatisLanguageDriverAutoConfiguration
, org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration]
=>总之都是会调用getCandidateConfigurations
/**
* Return the auto-configuration class names that should be considered. By default
* this method will load candidates using {@link SpringFactoriesLoader} with
* {@link #getSpringFactoriesLoaderFactoryClass()}.
* @param metadata the source metadata
* @param attributes the {@link #getAttributes(AnnotationMetadata) annotation
* attributes}
* @return a list of candidate configurations
*/
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
Assert.notEmpty(configurations,
"No auto configuration classes found in META-INF/spring.factories. If you "
+ "are using a custom packaging, make sure that file is correct.");
return configurations;
}
protected Class<?> getSpringFactoriesLoaderFactoryClass() {
return EnableAutoConfiguration.class;
}
终于藏不住了,看到了熟悉的SpringFactoriesLoader.loadFactoryNames,这里去加载所有META-INF/spring.factories里面的EnableAutoConfiguration
加载结果会排除重复和无效的以及排序后,如图:
可以看到顺序已经重排了!
到这里,grouping.getImports()就完成了,接下来就是foreach处理了
grouping.getImports().forEach(entry -> {
ConfigurationClass configurationClass = configurationClasses.get(entry.getMetadata());
try {
processImports(configurationClass, asSourceClass(configurationClass),
asSourceClasses(entry.getImportClassName()), false);
}
下面拿Mybatis的例子来解析
=>processImports
else {
// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
// process it as an @Configuration class
this.importStack.registerImport(
currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
processConfigurationClass(candidate.asConfigClass(configClass));
}
processConfigurationClass
=>shouldSkip:检查其依赖条件是否满足,比如mybatis DataSource依赖于两个条件
@ConditionalOnProperty( /* / prefix = "spring.datasource", / / name = {"is-dynamic-datasource"}, / / havingValue = "true", / / matchIfMissing = false / / ) / */ @Conditional({cn.hutool.db.sql.Condition.class})
condition.matches(this.context, metadata)
=>org.springframework.boot.autoconfigure.condition.SpringBootCondition:matches
ConditionOutcome outcome = getMatchOutcome(context, metadata);
因为是两个条件,所以两个循环,第一次是
org.springframework.boot.autoconfigure.condition.OnPropertyCondition: getMatchOutcome
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) {
List<AnnotationAttributes> allAnnotationAttributes = annotationAttributesFromMultiValueMap(
metadata.getAllAnnotationAttributes(
ConditionalOnProperty.class.getName()));
List<ConditionMessage> noMatch = new ArrayList<>();
List<ConditionMessage> match = new ArrayList<>();
for (AnnotationAttributes annotationAttributes : allAnnotationAttributes) {
ConditionOutcome outcome = determineOutcome(annotationAttributes,
context.getEnvironment());
(outcome.isMatch() ? match : noMatch).add(outcome.getConditionMessage());
}
if (!noMatch.isEmpty()) {
return ConditionOutcome.noMatch(ConditionMessage.of(noMatch));
}
return ConditionOutcome.match(ConditionMessage.of(match));
}
核心就是context.getEnvironment(),很清楚的从前面准备好的env propertySources中获取相关属性值,看是否有设置;
然后第二个cn.hutool.db.sql.Condition有点神奇,没有搞懂,直接是new ConditionOutcome(true, “启动动态数据源”),满足返回;
总之,条件检测成功!
检查完后神奇的调用doProcessConfigurationClass,注意我们说第一步的parse就会调到这里,这次是解析EnableAutoConfiguration
,当然这里也没有什么好解析的
注意,我们前面说了doProcessConfigurationClass的各个步骤会调用rocessConfigurationClass这个方法,这个方法最终是将bean的信息写入到前面说的重要的成员变量configurationClasses
这步结束,再来看下configurationClasses的值,debug技巧就是在在parser.validate上面打断点,等parser.parse也就是上面的第一步和第二步全部结束
parser.parse(candidates); parser.validate();
可以看到第一步和第二步的所有bean都已经在里面了
可以看到configClasses里面放满了
第一步从主类注解扫描到的所有@Controller @Service @Bean等以及springboot自带的一些内部bean,
第二步从每个springboot starter的META-INF/spring.fatories中加载的类信息,详细内容:
{ConfigurationClass: beanName 'myBatisConfiguration', class path resource [com/lyhistory/mybatis/springboot/mybatis_starter/MyBatisConfiguration.class]=ConfigurationClass: beanName 'myBatisConfiguration', class path resource [com/lyhistory/mybatis/springboot/mybatis_starter/MyBatisConfiguration.class]
, ConfigurationClass: beanName 'myBatisMapperScannerConfig', class path resource [com/lyhistory/mybatis/springboot/mybatis_starter/MyBatisMapperScannerConfig.class]=ConfigurationClass: beanName 'myBatisMapperScannerConfig', class path resource [com/lyhistory/mybatis/springboot/mybatis_starter/MyBatisMapperScannerConfig.class]
, ConfigurationClass: beanName 'testController', class path resource [com/lyhistory/mybatis/springboot/mybatis_starter/TestController.class]=ConfigurationClass: beanName 'testController', class path resource [com/lyhistory/mybatis/springboot/mybatis_starter/TestController.class]
, ConfigurationClass: beanName 'testService', class path resource [com/lyhistory/mybatis/springboot/mybatis_starter/TestService.class]=ConfigurationClass: beanName 'testService', class path resource [com/lyhistory/mybatis/springboot/mybatis_starter/TestService.class]
, ConfigurationClass: beanName 'starterMain', com.lyhistory.mybatis.springboot.mybatis_starter.StarterMain=ConfigurationClass: beanName 'starterMain', com.lyhistory.mybatis.springboot.mybatis_starter.StarterMain
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/context/PropertyPlaceholderAutoConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/context/PropertyPlaceholderAutoConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/websocket/servlet/WebSocketServletAutoConfiguration$TomcatWebSocketConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/websocket/servlet/WebSocketServletAutoConfiguration$TomcatWebSocketConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/websocket/servlet/WebSocketServletAutoConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/websocket/servlet/WebSocketServletAutoConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryConfiguration$EmbeddedTomcat.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryConfiguration$EmbeddedTomcat.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryAutoConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryAutoConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/web/servlet/DispatcherServletAutoConfiguration$DispatcherServletConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/web/servlet/DispatcherServletAutoConfiguration$DispatcherServletConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/web/servlet/DispatcherServletAutoConfiguration$DispatcherServletRegistrationConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/web/servlet/DispatcherServletAutoConfiguration$DispatcherServletRegistrationConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/web/servlet/DispatcherServletAutoConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/web/servlet/DispatcherServletAutoConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/task/TaskExecutionAutoConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/task/TaskExecutionAutoConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/validation/ValidationAutoConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/validation/ValidationAutoConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/web/servlet/error/ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/web/servlet/error/ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/web/servlet/error/ErrorMvcAutoConfiguration$DefaultErrorViewResolverConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/web/servlet/error/ErrorMvcAutoConfiguration$DefaultErrorViewResolverConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/web/servlet/error/ErrorMvcAutoConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/web/servlet/error/ErrorMvcAutoConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter$FaviconConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter$FaviconConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceJmxConfiguration$Hikari.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceJmxConfiguration$Hikari.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceJmxConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceJmxConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration$PooledDataSourceConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration$PooledDataSourceConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/jdbc/metadata/DataSourcePoolMetadataProvidersConfiguration$HikariPoolDataSourceMetadataProviderConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/jdbc/metadata/DataSourcePoolMetadataProvidersConfiguration$HikariPoolDataSourceMetadataProviderConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/jdbc/metadata/DataSourcePoolMetadataProvidersConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/jdbc/metadata/DataSourcePoolMetadataProvidersConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceInitializerInvoker.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceInitializerInvoker.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceInitializationConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceInitializationConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/mybatis/spring/boot/autoconfigure/MybatisLanguageDriverAutoConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/mybatis/spring/boot/autoconfigure/MybatisLanguageDriverAutoConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/mybatis/spring/boot/autoconfigure/MybatisAutoConfiguration$MapperScannerRegistrarNotFoundConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/mybatis/spring/boot/autoconfigure/MybatisAutoConfiguration$MapperScannerRegistrarNotFoundConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/mybatis/spring/boot/autoconfigure/MybatisAutoConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/mybatis/spring/boot/autoconfigure/MybatisAutoConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/jmx/JmxAutoConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/jmx/JmxAutoConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/admin/SpringApplicationAdminJmxAutoConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/admin/SpringApplicationAdminJmxAutoConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/cache/GenericCacheConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/cache/GenericCacheConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/cache/SimpleCacheConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/cache/SimpleCacheConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/cache/NoOpCacheConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/cache/NoOpCacheConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/cache/CacheAutoConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/cache/CacheAutoConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/context/ConfigurationPropertiesAutoConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/context/ConfigurationPropertiesAutoConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/dao/PersistenceExceptionTranslationAutoConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/dao/PersistenceExceptionTranslationAutoConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration$Jackson2ObjectMapperBuilderCustomizerConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration$Jackson2ObjectMapperBuilderCustomizerConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration$JacksonObjectMapperBuilderConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration$JacksonObjectMapperBuilderConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration$ParameterNamesModuleConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration$ParameterNamesModuleConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration$JacksonObjectMapperConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration$JacksonObjectMapperConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/http/HttpMessageConvertersAutoConfiguration$StringHttpMessageConverterConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/http/HttpMessageConvertersAutoConfiguration$StringHttpMessageConverterConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/http/JacksonHttpMessageConvertersConfiguration$MappingJackson2HttpMessageConverterConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/http/JacksonHttpMessageConvertersConfiguration$MappingJackson2HttpMessageConverterConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/http/JacksonHttpMessageConvertersConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/http/JacksonHttpMessageConvertersConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/http/HttpMessageConvertersAutoConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/http/HttpMessageConvertersAutoConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/http/codec/CodecsAutoConfiguration$LoggingCodecConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/http/codec/CodecsAutoConfiguration$LoggingCodecConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/http/codec/CodecsAutoConfiguration$JacksonCodecConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/http/codec/CodecsAutoConfiguration$JacksonCodecConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/http/codec/CodecsAutoConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/http/codec/CodecsAutoConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/info/ProjectInfoAutoConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/info/ProjectInfoAutoConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/jdbc/JdbcTemplateAutoConfiguration$JdbcTemplateConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/jdbc/JdbcTemplateAutoConfiguration$JdbcTemplateConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/jdbc/JdbcTemplateAutoConfiguration$NamedParameterJdbcTemplateConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/jdbc/JdbcTemplateAutoConfiguration$NamedParameterJdbcTemplateConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/jdbc/JdbcTemplateAutoConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/jdbc/JdbcTemplateAutoConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/task/TaskSchedulingAutoConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/task/TaskSchedulingAutoConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceTransactionManagerAutoConfiguration$DataSourceTransactionManagerConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceTransactionManagerAutoConfiguration$DataSourceTransactionManagerConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceTransactionManagerAutoConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceTransactionManagerAutoConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/transaction/annotation/ProxyTransactionManagementConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/transaction/annotation/ProxyTransactionManagementConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/transaction/TransactionAutoConfiguration$EnableTransactionManagementConfiguration$CglibAutoProxyConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/transaction/TransactionAutoConfiguration$EnableTransactionManagementConfiguration$CglibAutoProxyConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/transaction/TransactionAutoConfiguration$EnableTransactionManagementConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/transaction/TransactionAutoConfiguration$EnableTransactionManagementConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/transaction/TransactionAutoConfiguration$TransactionTemplateConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/transaction/TransactionAutoConfiguration$TransactionTemplateConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/transaction/TransactionAutoConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/transaction/TransactionAutoConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/web/client/RestTemplateAutoConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/web/client/RestTemplateAutoConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/web/embedded/EmbeddedWebServerFactoryCustomizerAutoConfiguration$TomcatWebServerFactoryCustomizerConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/web/embedded/EmbeddedWebServerFactoryCustomizerAutoConfiguration$TomcatWebServerFactoryCustomizerConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/web/embedded/EmbeddedWebServerFactoryCustomizerAutoConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/web/embedded/EmbeddedWebServerFactoryCustomizerAutoConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/web/servlet/HttpEncodingAutoConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/web/servlet/HttpEncodingAutoConfiguration.class]
, ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/web/servlet/MultipartAutoConfiguration.class]=ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/web/servlet/MultipartAutoConfiguration.class]}
到此处,再看看beanDefinitionMap,不出所料,依然不会变,因为前面只是初步解析准备工作,还没有开始读取beanDefinition
从主程序读取的bean Controller Service都已经在里面了,但是上面第二步拿到的那些Starter的AutoEnableConfiguration还没有进来,还需要继续
{myBatisMapperScannerConfig=Generic bean: class [com.lyhistory.mybatis.springboot.mybatis_starter.MyBatisMapperScannerConfig];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in file [C:\Workspace\Repository\learn_coding\java\Components\mybatis-demo\hello-mybatis\target\classes\com\lyhistory\mybatis\springboot\mybatis_starter\MyBatisMapperScannerConfig.class], org.springframework.context.annotation.internalConfigurationAnnotationProcessor=Root bean: class [org.springframework.context.annotation.ConfigurationClassPostProcessor];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.context.event.internalEventListenerFactory=Root bean: class [org.springframework.context.event.DefaultEventListenerFactory];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.context.event.internalEventListenerProcessor=Root bean: class [org.springframework.context.event.EventListenerMethodProcessor];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, testController=Generic bean: class [com.lyhistory.mybatis.springboot.mybatis_starter.TestController];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in file [C:\Workspace\Repository\learn_coding\java\Components\mybatis-demo\hello-mybatis\target\classes\com\lyhistory\mybatis\springboot\mybatis_starter\TestController.class], org.springframework.context.annotation.internalAutowiredAnnotationProcessor=Root bean: class [org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory=Generic bean: class [org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer$SharedMetadataReaderFactoryBean];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.context.annotation.internalCommonAnnotationProcessor=Root bean: class [org.springframework.context.annotation.CommonAnnotationBeanPostProcessor];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, testService=Generic bean: class [com.lyhistory.mybatis.springboot.mybatis_starter.TestService];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in file [C:\Workspace\Repository\learn_coding\java\Components\mybatis-demo\hello-mybatis\target\classes\com\lyhistory\mybatis\springboot\mybatis_starter\TestService.class], starterMain=Generic bean: class [com.lyhistory.mybatis.springboot.mybatis_starter.StarterMain];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, myBatisConfiguration=Generic bean: class [com.lyhistory.mybatis.springboot.mybatis_starter.MyBatisConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in file [C:\Workspace\Repository\learn_coding\java\Components\mybatis-demo\hello-mybatis\target\classes\com\lyhistory\mybatis\springboot\mybatis_starter\MyBatisConfiguration.class]}
# 2.继续加载Starter的BeanDefinition
org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader: loadBeanDefinitions
public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
for (ConfigurationClass configClass : configurationModel) {
loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
}
}
这个地方有点意思,我们拿Mybatis举例,有两种不同的方式:
# Mybatis 用法一,自定义@Bean(name = "MapperScannerConfigurer")
package com.lyhistory.mybatis.springboot.mybatis_starter;
@Configuration
@AutoConfigureAfter(MyBatisConfiguration.class)
public class MyBatisMapperScannerConfig {
@Bean(name = "MapperScannerConfigurer")
public MapperScannerConfigurer mapperScannerConfigurer() {
MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
mapperScannerConfigurer.setBasePackage("com.lyhistory.mybatis.springboot.mybatis_starter");
return mapperScannerConfigurer;
}
}
循环开始,前面的是主程序扫的bean,比如我自定义的com/lyhistory/mybatis/springboot/mybatis_starter/MyBatisConfiguration.class和com/lyhistory/mybatis/springboot/mybatis_starter/MyBatisMapperScannerConfig.class等等
MyBatisConfiguration的这些方法的@bean都加到beanDefinitionMap
loadBeanDefinitionsForBeanMethod(beanMethod);
package com.lyhistory.mybatis.springboot.mybatis_starter;
@Configuration
public class MyBatisConfiguration {
@Value("${spring.datasource.driverClassName}")
private String jdbcDriverClassName;
@Value("${spring.datasource.url}")
private String jdbcUrl;
@Value("${spring.datasource.username}")
private String jdbcUsername;
@Value("${spring.datasource.password}")
private String jdbcPassword;
@Bean(name = "dataSource",destroyMethod = "close")
public DataSource dataSource() {
DruidDataSource datasource = new DruidDataSource();
datasource.setDriverClassName(jdbcDriverClassName);
datasource.setUrl(jdbcUrl);
datasource.setUsername(jdbcUsername);
datasource.setPassword(jdbcPassword);
datasource.setMaxActive(20);
datasource.setMinIdle(5);
return datasource;
}
@Bean(name = {"sqlSessionFactory"})
@ConditionalOnMissingBean(name = {"sqlSessionFactory"})
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
sqlSessionFactoryBean.setTypeAliasesPackage("com.lyhistory.mybatis.table");
sqlSessionFactoryBean.setConfigLocation(new ClassPathResource("mybatis/config/mybatis-config.xml"));
sqlSessionFactoryBean.setMapperLocations(
(new PathMatchingResourcePatternResolver()).getResources("classpath*:mybatis/mapping/*_starter.xml"));
return sqlSessionFactoryBean.getObject();
}
}
继续循环,还会处理一个比较特殊的bean,就是主程序!!
om.lyhistory.mybatis.springboot.mybatis_starter.StarterMain
注意,它会触发这个方法
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
configClass.getImportBeanDefinitionRegistrars():获取到
key=org.springframework.boot.autoconfigure.AutoConfigurationPackages$Registrar@10b9db7b
values=org.springframework.core.type.StandardAnnotationMetadata@2b62442c
private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
registrars.forEach((registrar, metadata) ->
registrar.registerBeanDefinitions(metadata, this.registry));
}
这个registrar就是org.springframework.boot.autoconfigure.AutoConfigurationPackages,进入到其静态内部类Registrar的registerBeanDefinitions方法,最终往beanFactory里面的beanDefinitionMap注册org.springframework.boot.autoconfigure.AutoConfigurationPackages
。。。。
继续循环其他的starter注册的EnableAutoConfiguration的配置bean, 比如org/mybatis/spring/boot/autoconfigure/MybatisAutoConfiguration.class
beanName=org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
if (configClass.isImported()) {
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
是经过前面parse的第二步从META-INF/spring.factories import进来的,还不在beanDefinitionMap中,所以需要往beanFactory注册一下,当然跟前面一样,其class内部的方法bean也需要注册,略过,重点说后面一步
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
configClass.getImportBeanDefinitionRegistrars():获取到:
key1:org.springframework.boot.context.properties.EnableConfigurationPropertiesImportSelector$ConfigurationPropertiesBeanRegistrar@1e63ec0b
value1:org.springframework.core.type.classreading.AnnotationMetadataReadingVisitor@160ac7fb, className=org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
key2:org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessorRegistrar@3b956878
value2:org.springframework.core.type.classreading.AnnotationMetadataReadingVisitor@160ac7fb
org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
这种方式到这里不会发生什么
# Mybatis 用法二:不自定义MapperScannerConfigurer
configClass.getImportBeanDefinitionRegistrars():获取到:
key=org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration$AutoConfiguredMapperScannerRegistrar@2b4d4327
values=org.springframework.core.type.classreading.AnnotationMetadataReadingVisitor@49232c6f
className=org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration$MapperScannerRegistrarNotFoundConfiguration
可以看到这里有个MapperScannerRegistrarNotFoundConfiguration,这里没有自定义@Bean(name = "MapperScannerConfigurer"),所以就会用这个MapperScannerRegistrarNotFoundConfiguration来触发Mybatis的扫描工作 ,而前面第一种方式相当于将这里的Mybatis Auto Scanner覆写了,所以也很容易理解
至于为什么,可以研究一下前面第二步递归解析的时候调用的org.springframework.context.annotation.ConfigurationClass
初步猜测,springboot有地方可以让mybatis去检查是否主类或者其他包下定义了MapperScannerConfigurer这个bean,如果没有则启用MapperScannerRegistrarNotFoundConfiguration
public void addImportBeanDefinitionRegistrar(ImportBeanDefinitionRegistrar registrar, AnnotationMetadata importingClassMetadata) {
this.importBeanDefinitionRegistrars.put(registrar, importingClassMetadata);
}
接着说
private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
registrars.forEach((registrar, metadata) ->
registrar.registerBeanDefinitions(metadata, this.registry));
}
此处rigistrar就是加了@Configuration标注的org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
进入到MyBatis!可以看到Mybatis开始扫描Mapper
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
logger.debug("Searching for mappers annotated with @Mapper");
ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
try {
if (this.resourceLoader != null) {
scanner.setResourceLoader(this.resourceLoader);
}
List<String> packages = AutoConfigurationPackages.get(this.beanFactory);
if (logger.isDebugEnabled()) {
for (String pkg : packages) {
logger.debug("Using auto-configuration base package '{}'", pkg);
}
}
scanner.setAnnotationClass(Mapper.class);
scanner.registerFilters();
scanner.doScan(StringUtils.toStringArray(packages));
} catch (IllegalStateException ex) {
logger.debug("Could not determine auto-configuration package, automatic mapper scanning disabled.", ex);
}
}
上面很明显,这种方式@Mapper会被立即扫描进来,
但是上面第一种方式结束后@Mapper不会被扫描进来,(第一种方式还需要后面的Finally那一步操作才可以扫描到!)
我这里只放了第一种方式的截图:
beanDefinitionMap,org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration也进来了
{defaultServletHandlerMapping=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration; factoryMethodName=defaultServletHandlerMapping; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class], org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter$FaviconConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter$FaviconConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, applicationTaskExecutor=Root bean: class [null];
scope=; abstract=false; lazyInit=true; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration; factoryMethodName=applicationTaskExecutor; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/task/TaskExecutionAutoConfiguration.class], persistenceExceptionTranslationPostProcessor=Root bean: class [org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=persistenceExceptionTranslationPostProcessor; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/dao/PersistenceExceptionTranslationAutoConfiguration.class], characterEncodingFilter=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration; factoryMethodName=characterEncodingFilter; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/HttpEncodingAutoConfiguration.class], myBatisMapperScannerConfig=Generic bean: class [com.lyhistory.mybatis.springboot.mybatis_starter.MyBatisMapperScannerConfig];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in file [C:\Workspace\Repository\learn_coding\java\Components\mybatis-demo\hello-mybatis\target\classes\com\lyhistory\mybatis\springboot\mybatis_starter\MyBatisMapperScannerConfig.class], org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration$DispatcherServletRegistrationConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration$DispatcherServletRegistrationConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, sqlSessionFactory=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=myBatisConfiguration; factoryMethodName=sqlSessionFactory; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [com/lyhistory/mybatis/springboot/mybatis_starter/MyBatisConfiguration.class], preserveErrorControllerTargetClassPostProcessor=Root bean: class [org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=preserveErrorControllerTargetClassPostProcessor; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/error/ErrorMvcAutoConfiguration.class], org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$JacksonObjectMapperBuilderConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$JacksonObjectMapperBuilderConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, jdbcTemplate=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=true; factoryBeanName=org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration$JdbcTemplateConfiguration; factoryMethodName=jdbcTemplate; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/jdbc/JdbcTemplateAutoConfiguration$JdbcTemplateConfiguration.class], org.springframework.context.annotation.internalConfigurationAnnotationProcessor=Root bean: class [org.springframework.context.annotation.ConfigurationClassPostProcessor];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, propertySourcesPlaceholderConfigurer=Root bean: class [org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=propertySourcesPlaceholderConfigurer; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/context/PropertyPlaceholderAutoConfiguration.class], org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration$EnableTransactionManagementConfiguration$CglibAutoProxyConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration$EnableTransactionManagementConfiguration$CglibAutoProxyConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, faviconRequestHandler=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter$FaviconConfiguration; factoryMethodName=faviconRequestHandler; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter$FaviconConfiguration.class], beanNameViewResolver=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration; factoryMethodName=beanNameViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/error/ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration.class], loggingCodecCustomizer=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration$LoggingCodecConfiguration; factoryMethodName=loggingCodecCustomizer; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/http/codec/CodecsAutoConfiguration$LoggingCodecConfiguration.class], viewResolver=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter; factoryMethodName=viewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter.class], methodValidationPostProcessor=Root bean: class [org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=methodValidationPostProcessor; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/validation/ValidationAutoConfiguration.class], stringHttpMessageConverter=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration$StringHttpMessageConverterConfiguration; factoryMethodName=stringHttpMessageConverter; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/http/HttpMessageConvertersAutoConfiguration$StringHttpMessageConverterConfiguration.class], org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration$TomcatWebServerFactoryCustomizerConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration$TomcatWebServerFactoryCustomizerConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, tomcatServletWebServerFactoryCustomizer=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; factoryMethodName=tomcatServletWebServerFactoryCustomizer; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryAutoConfiguration.class], org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, server-org.springframework.boot.autoconfigure.web.ServerProperties=Generic bean: class [org.springframework.boot.autoconfigure.web.ServerProperties];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, messageConverters=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration; factoryMethodName=messageConverters; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/http/HttpMessageConvertersAutoConfiguration.class], jsonComponentModule=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; factoryMethodName=jsonComponentModule; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration.class], dataSourceInitializerPostProcessor=Generic bean: class [org.springframework.boot.autoconfigure.jdbc.DataSourceInitializerPostProcessor];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, websocketServletWebServerCustomizer=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration$TomcatWebSocketConfiguration; factoryMethodName=websocketServletWebServerCustomizer; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/websocket/servlet/WebSocketServletAutoConfiguration$TomcatWebSocketConfiguration.class], org.springframework.context.event.internalEventListenerFactory=Root bean: class [org.springframework.context.event.DefaultEventListenerFactory];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, mappingJackson2HttpMessageConverter=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.http.JacksonHttpMessageConvertersConfiguration$MappingJackson2HttpMessageConverterConfiguration; factoryMethodName=mappingJackson2HttpMessageConverter; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/http/JacksonHttpMessageConvertersConfiguration$MappingJackson2HttpMessageConverterConfiguration.class], mbeanExporter=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=true; factoryBeanName=org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration; factoryMethodName=mbeanExporter; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/jmx/JmxAutoConfiguration.class], mbeanServer=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration; factoryMethodName=mbeanServer; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/jmx/JmxAutoConfiguration.class], servletWebServerFactoryCustomizer=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; factoryMethodName=servletWebServerFactoryCustomizer; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryAutoConfiguration.class], mvcUrlPathHelper=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration; factoryMethodName=mvcUrlPathHelper; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class], transactionTemplate=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration$TransactionTemplateConfiguration; factoryMethodName=transactionTemplate; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/transaction/TransactionAutoConfiguration$TransactionTemplateConfiguration.class], webServerFactoryCustomizerBeanPostProcessor=Root bean: class [org.springframework.boot.web.server.WebServerFactoryCustomizerBeanPostProcessor];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration=Generic bean: class [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, mybatis-org.mybatis.spring.boot.autoconfigure.MybatisProperties=Generic bean: class [org.mybatis.spring.boot.autoconfigure.MybatisProperties];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$Jackson2ObjectMapperBuilderCustomizerConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$Jackson2ObjectMapperBuilderCustomizerConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration$StringHttpMessageConverterConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration$StringHttpMessageConverterConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, standardJacksonObjectMapperBuilderCustomizer=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$Jackson2ObjectMapperBuilderCustomizerConfiguration; factoryMethodName=standardJacksonObjectMapperBuilderCustomizer; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration$Jackson2ObjectMapperBuilderCustomizerConfiguration.class], taskSchedulerBuilder=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration; factoryMethodName=taskSchedulerBuilder; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/task/TaskSchedulingAutoConfiguration.class], org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, transactionInterceptor=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration; factoryMethodName=transactionInterceptor; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/transaction/annotation/ProxyTransactionManagementConfiguration.class], org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, jacksonCodecCustomizer=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration$JacksonCodecConfiguration; factoryMethodName=jacksonCodecCustomizer; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/http/codec/CodecsAutoConfiguration$JacksonCodecConfiguration.class], conventionErrorViewResolver=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration$DefaultErrorViewResolverConfiguration; factoryMethodName=conventionErrorViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/error/ErrorMvcAutoConfiguration$DefaultErrorViewResolverConfiguration.class], org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.boot.autoconfigure.jdbc.metadata.DataSourcePoolMetadataProvidersConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.jdbc.metadata.DataSourcePoolMetadataProvidersConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.context.event.internalEventListenerProcessor=Root bean: class [org.springframework.context.event.EventListenerMethodProcessor];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, spring.mvc-org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties=Generic bean: class [org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, localeCharsetMappingsCustomizer=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration; factoryMethodName=localeCharsetMappingsCustomizer; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/HttpEncodingAutoConfiguration.class], formContentFilter=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration; factoryMethodName=formContentFilter; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.class], multipartConfigElement=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration; factoryMethodName=multipartConfigElement; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/MultipartAutoConfiguration.class], MapperScannerConfigurer=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=myBatisMapperScannerConfig; factoryMethodName=mapperScannerConfigurer; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [com/lyhistory/mybatis/springboot/mybatis_starter/MyBatisMapperScannerConfig.class], requestContextFilter=Root bean: class [org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=requestContextFilter; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter.class], testController=Generic bean: class [com.lyhistory.mybatis.springboot.mybatis_starter.TestController];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in file [C:\Workspace\Repository\learn_coding\java\Components\mybatis-demo\hello-mybatis\target\classes\com\lyhistory\mybatis\springboot\mybatis_starter\TestController.class], defaultViewResolver=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter; factoryMethodName=defaultViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter.class], org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration$EnableTransactionManagementConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration$EnableTransactionManagementConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, jacksonObjectMapperBuilder=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$JacksonObjectMapperBuilderConfiguration; factoryMethodName=jacksonObjectMapperBuilder; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration$JacksonObjectMapperBuilderConfiguration.class], spring.task.scheduling-org.springframework.boot.autoconfigure.task.TaskSchedulingProperties=Generic bean: class [org.springframework.boot.autoconfigure.task.TaskSchedulingProperties];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration$LoggingCodecConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration$LoggingCodecConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, restTemplateBuilder=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration; factoryMethodName=restTemplateBuilder; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/client/RestTemplateAutoConfiguration.class], multipartResolver=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration; factoryMethodName=multipartResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/MultipartAutoConfiguration.class], requestMappingHandlerMapping=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=true; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration; factoryMethodName=requestMappingHandlerMapping; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class], org.springframework.aop.config.internalAutoProxyCreator=Root bean: class [org.springframework.aop.framework.autoproxy.InfrastructureAdvisorAutoProxyCreator];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration$JdbcTemplateConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration$JdbcTemplateConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, requestMappingHandlerAdapter=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration; factoryMethodName=requestMappingHandlerAdapter; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class], spring.transaction-org.springframework.boot.autoconfigure.transaction.TransactionProperties=Generic bean: class [org.springframework.boot.autoconfigure.transaction.TransactionProperties];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, mvcHandlerMappingIntrospector=Root bean: class [null];
scope=; abstract=false; lazyInit=true; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration; factoryMethodName=mvcHandlerMappingIntrospector; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class], springApplicationAdminRegistrar=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration; factoryMethodName=springApplicationAdminRegistrar; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/admin/SpringApplicationAdminJmxAutoConfiguration.class], org.springframework.boot.autoconfigure.condition.BeanTypeRegistry=Generic bean: class [org.springframework.boot.autoconfigure.condition.BeanTypeRegistry];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, spring.info-org.springframework.boot.autoconfigure.info.ProjectInfoProperties=Generic bean: class [org.springframework.boot.autoconfigure.info.ProjectInfoProperties];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.context.annotation.internalAutowiredAnnotationProcessor=Root bean: class [org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, spring.resources-org.springframework.boot.autoconfigure.web.ResourceProperties=Generic bean: class [org.springframework.boot.autoconfigure.web.ResourceProperties];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.boot.context.properties.ConfigurationBeanFactoryMetadata=Generic bean: class [org.springframework.boot.context.properties.ConfigurationBeanFactoryMetadata];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory=Generic bean: class [org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer$SharedMetadataReaderFactoryBean];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$ParameterNamesModuleConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$ParameterNamesModuleConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, mvcContentNegotiationManager=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration; factoryMethodName=mvcContentNegotiationManager; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class], objectNamingStrategy=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration; factoryMethodName=objectNamingStrategy; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/jmx/JmxAutoConfiguration.class], org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, errorAttributes=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration; factoryMethodName=errorAttributes; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/error/ErrorMvcAutoConfiguration.class], httpRequestHandlerAdapter=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration; factoryMethodName=httpRequestHandlerAdapter; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class], beanNameHandlerMapping=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration; factoryMethodName=beanNameHandlerMapping; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class], spring.servlet.multipart-org.springframework.boot.autoconfigure.web.servlet.MultipartProperties=Generic bean: class [org.springframework.boot.autoconfigure.web.servlet.MultipartProperties];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.context.annotation.internalCommonAnnotationProcessor=Root bean: class [org.springframework.context.annotation.CommonAnnotationBeanPostProcessor];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryConfiguration$EmbeddedTomcat=Generic bean: class [org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryConfiguration$EmbeddedTomcat];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, resourceHandlerMapping=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration; factoryMethodName=resourceHandlerMapping; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class], simpleControllerHandlerAdapter=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration; factoryMethodName=simpleControllerHandlerAdapter; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class], spring.http-org.springframework.boot.autoconfigure.http.HttpProperties=Generic bean: class [org.springframework.boot.autoconfigure.http.HttpProperties];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.mybatis.spring.boot.autoconfigure.MybatisLanguageDriverAutoConfiguration=Generic bean: class [org.mybatis.spring.boot.autoconfigure.MybatisLanguageDriverAutoConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, testService=Generic bean: class [com.lyhistory.mybatis.springboot.mybatis_starter.TestService];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in file [C:\Workspace\Repository\learn_coding\java\Components\mybatis-demo\hello-mybatis\target\classes\com\lyhistory\mybatis\springboot\mybatis_starter\TestService.class], org.springframework.transaction.config.internalTransactionAdvisor=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration; factoryMethodName=transactionAdvisor; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/transaction/annotation/ProxyTransactionManagementConfiguration.class], parameterNamesModule=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$ParameterNamesModuleConfiguration; factoryMethodName=parameterNamesModule; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration$ParameterNamesModuleConfiguration.class], org.springframework.boot.autoconfigure.jdbc.DataSourceInitializationConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.jdbc.DataSourceInitializationConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.boot.autoconfigure.jdbc.DataSourceInitializerInvoker=Generic bean: class [org.springframework.boot.autoconfigure.jdbc.DataSourceInitializerInvoker];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, hiddenHttpMethodFilter=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration; factoryMethodName=hiddenHttpMethodFilter; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.class], org.springframework.transaction.config.internalTransactionalEventListenerFactory=Root bean: class [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=transactionalEventListenerFactory; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/transaction/annotation/ProxyTransactionManagementConfiguration.class], org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, mvcValidator=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration; factoryMethodName=mvcValidator; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class], org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration$TomcatWebSocketConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration$TomcatWebSocketConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, mvcResourceUrlProvider=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration; factoryMethodName=mvcResourceUrlProvider; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class], spring.task.execution-org.springframework.boot.autoconfigure.task.TaskExecutionProperties=Generic bean: class [org.springframework.boot.autoconfigure.task.TaskExecutionProperties];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, viewControllerHandlerMapping=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration; factoryMethodName=viewControllerHandlerMapping; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class], org.springframework.boot.autoconfigure.jdbc.metadata.DataSourcePoolMetadataProvidersConfiguration$HikariPoolDataSourceMetadataProviderConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.jdbc.metadata.DataSourcePoolMetadataProvidersConfiguration$HikariPoolDataSourceMetadataProviderConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, dispatcherServlet=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration$DispatcherServletConfiguration; factoryMethodName=dispatcherServlet; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/DispatcherServletAutoConfiguration$DispatcherServletConfiguration.class], org.springframework.boot.autoconfigure.AutoConfigurationPackages=Generic bean: class [org.springframework.boot.autoconfigure.AutoConfigurationPackages$BasePackages];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor=Generic bean: class [org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, hikariPoolDataSourceMetadataProvider=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.jdbc.metadata.DataSourcePoolMetadataProvidersConfiguration$HikariPoolDataSourceMetadataProviderConfiguration; factoryMethodName=hikariPoolDataSourceMetadataProvider; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/jdbc/metadata/DataSourcePoolMetadataProvidersConfiguration$HikariPoolDataSourceMetadataProviderConfiguration.class], spring.jdbc-org.springframework.boot.autoconfigure.jdbc.JdbcProperties=Generic bean: class [org.springframework.boot.autoconfigure.jdbc.JdbcProperties];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, transactionAttributeSource=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration; factoryMethodName=transactionAttributeSource; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/transaction/annotation/ProxyTransactionManagementConfiguration.class], org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter=Generic bean: class [org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration$DataSourceTransactionManagerConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration$DataSourceTransactionManagerConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, transactionManager=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration$DataSourceTransactionManagerConfiguration; factoryMethodName=transactionManager; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceTransactionManagerAutoConfiguration$DataSourceTransactionManagerConfiguration.class], errorPageRegistrarBeanPostProcessor=Root bean: class [org.springframework.boot.web.server.ErrorPageRegistrarBeanPostProcessor];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, errorPageCustomizer=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration; factoryMethodName=errorPageCustomizer; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/error/ErrorMvcAutoConfiguration.class], mvcConversionService=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration; factoryMethodName=mvcConversionService; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class], org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration$DefaultErrorViewResolverConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration$DefaultErrorViewResolverConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, starterMain=Generic bean: class [com.lyhistory.mybatis.springboot.mybatis_starter.StarterMain];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, tomcatWebServerFactoryCustomizer=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration$TomcatWebServerFactoryCustomizerConfiguration; factoryMethodName=tomcatWebServerFactoryCustomizer; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/embedded/EmbeddedWebServerFactoryCustomizerAutoConfiguration$TomcatWebServerFactoryCustomizerConfiguration.class], faviconHandlerMapping=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter$FaviconConfiguration; factoryMethodName=faviconHandlerMapping; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter$FaviconConfiguration.class], org.springframework.boot.autoconfigure.http.JacksonHttpMessageConvertersConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.http.JacksonHttpMessageConvertersConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, mvcPathMatcher=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration; factoryMethodName=mvcPathMatcher; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class], handlerExceptionResolver=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration; factoryMethodName=handlerExceptionResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class], basicErrorController=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration; factoryMethodName=basicErrorController; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/error/ErrorMvcAutoConfiguration.class], org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, dispatcherServletRegistration=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration$DispatcherServletRegistrationConfiguration; factoryMethodName=dispatcherServletRegistration; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/DispatcherServletAutoConfiguration$DispatcherServletRegistrationConfiguration.class], dataSource=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=myBatisConfiguration; factoryMethodName=dataSource; initMethodName=null; destroyMethodName=close; defined in class path resource [com/lyhistory/mybatis/springboot/mybatis_starter/MyBatisConfiguration.class], org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration$JacksonCodecConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration$JacksonCodecConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, tomcatServletWebServerFactory=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryConfiguration$EmbeddedTomcat; factoryMethodName=tomcatServletWebServerFactory; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryConfiguration$EmbeddedTomcat.class], org.springframework.boot.autoconfigure.http.JacksonHttpMessageConvertersConfiguration$MappingJackson2HttpMessageConverterConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.http.JacksonHttpMessageConvertersConfiguration$MappingJackson2HttpMessageConverterConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, spring.jackson-org.springframework.boot.autoconfigure.jackson.JacksonProperties=Generic bean: class [org.springframework.boot.autoconfigure.jackson.JacksonProperties];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, error=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration; factoryMethodName=defaultErrorView; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/error/ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration.class], org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, spring.datasource-org.springframework.boot.autoconfigure.jdbc.DataSourceProperties=Generic bean: class [org.springframework.boot.autoconfigure.jdbc.DataSourceProperties];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$JacksonObjectMapperConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$JacksonObjectMapperConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, namedParameterJdbcTemplate=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=true; factoryBeanName=org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration$NamedParameterJdbcTemplateConfiguration; factoryMethodName=namedParameterJdbcTemplate; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/jdbc/JdbcTemplateAutoConfiguration$NamedParameterJdbcTemplateConfiguration.class], org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration$DispatcherServletConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration$DispatcherServletConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration$TransactionTemplateConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration$TransactionTemplateConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, mvcViewResolver=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration; factoryMethodName=mvcViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class], defaultValidator=Root bean: class [org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=true; factoryBeanName=null; factoryMethodName=defaultValidator; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/validation/ValidationAutoConfiguration.class], welcomePageHandlerMapping=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter; factoryMethodName=welcomePageHandlerMapping; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter.class], mvcUriComponentsContributor=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration; factoryMethodName=mvcUriComponentsContributor; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class], org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration=Generic bean: class [org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, jacksonObjectMapper=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=true; factoryBeanName=org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$JacksonObjectMapperConfiguration; factoryMethodName=jacksonObjectMapper; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration$JacksonObjectMapperConfiguration.class], org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration$NamedParameterJdbcTemplateConfiguration=Generic bean: class [org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration$NamedParameterJdbcTemplateConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, myBatisConfiguration=Generic bean: class [com.lyhistory.mybatis.springboot.mybatis_starter.MyBatisConfiguration];
scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in file [C:\Workspace\Repository\learn_coding\java\Components\mybatis-demo\hello-mybatis\target\classes\com\lyhistory\mybatis\springboot\mybatis_starter\MyBatisConfiguration.class], taskExecutorBuilder=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration; factoryMethodName=taskExecutorBuilder; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/task/TaskExecutionAutoConfiguration.class], platformTransactionManagerCustomizers=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration; factoryMethodName=platformTransactionManagerCustomizers; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/transaction/TransactionAutoConfiguration.class], sqlSessionTemplate=Root bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration; factoryMethodName=sqlSessionTemplate; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/mybatis/spring/boot/autoconfigure/MybatisAutoConfiguration.class]}
# Next:
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
此时,postProcessor有两个,多了一个MapperScannerConfigurer
[org.springframework.context.annotation.internalConfigurationAnnotationProcessor, MapperScannerConfigurer]
上面的if判断不会通过,因为internalConfigurationAnnotationProcessor已经在上面一步处理过了,所以包含在processedBeans里面,而MapperScannerConfigurer虽然没有处理过,但不是类型不符合Ordered
# Finally
// 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);
currentRegistryProcessors.clear();
}
通过if判断,终于轮到MapperScannerConfigurer起作用了,首先beanFactory.getBean实例化MapperScannerConfigurer
开始invoke,
org.mybatis.spring.mapper.MapperScannerConfigurer mplements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
if (this.processPropertyPlaceHolders) {
processPropertyPlaceHolders();
}
ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
scanner.setAddToConfig(this.addToConfig);
scanner.setAnnotationClass(this.annotationClass);
scanner.setMarkerInterface(this.markerInterface);
scanner.setSqlSessionFactory(this.sqlSessionFactory);
scanner.setSqlSessionTemplate(this.sqlSessionTemplate);
scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName);
scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName);
scanner.setResourceLoader(this.applicationContext);
scanner.setBeanNameGenerator(this.nameGenerator);
scanner.setMapperFactoryBeanClass(this.mapperFactoryBeanClass);
if (StringUtils.hasText(lazyInitialization)) {
scanner.setLazyInitialization(Boolean.valueOf(lazyInitialization));
}
scanner.registerFilters();
scanner.scan(
StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS));
}
终于将我们自定义的mybatis的@Mapper加载进来了
TODO:
#Next Last
实例化
org.springframework.beans.factory.support.AbstractBeanFactory
doGetBean
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
createBean
doCreateBean
populateBean() 开始找autowired dependencies
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
postProcessPropertyValues
metadata.inject(bean, beanName, pvs);
org.springframework.beans.factory.annotation.InjectionMetadata
inject
element.inject(target, beanName, pvs);
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
inject
beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
org.springframework.beans.factory.support.DefaultListableBeanFactory
resolveDependency
doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter)
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
postProcessPropertyValues
inject
# 第六步 registerBeanPostProcessors
# 第十一步 finishBeanFactoryInitialization
# 第十二步 finishRefresh
# 第十三步 resetCommonCaches
BeanFactory (固定模板)
VS
FactoryBean 生产唯一固定的复杂对象 (参考OpenFeign实现接口getobject getobjecttype isSingleton)
# More example
类似前面分析的mybatis,redis connector也有类似的,通过下面代码的注释,可以看到,类似mybatis的RegistrarNotFound,当我们没有自定义RedisConnectionFactory的时候,spring 会帮我们注册一个默认的即下面的LettuceConnectionFactory,严格说其实不是spring帮我们,而是 spring boot starter --- spring-boot-starter-data-redis,其制定的标准接口,默认选用Lettuce实现
@Configuration
@ComponentScan("com.lyhistory.redis")
//@EnableRedisRepositories(basePackages = "com.lyhistory.redis.repo")
@PropertySource("classpath:application.properties")
public class RedisConfig {
@Autowired
private ClusterConfigurationProperties clusterProperties;
@Bean
RedisClusterConfiguration redisConfiguration() {
RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration(clusterProperties.getNodes());
redisClusterConfiguration.setMaxRedirects(clusterProperties.getMaxRedirects());
return redisClusterConfiguration;
}
/*
@Bean
JedisConnectionFactory jedisConnectionFactory() {
return new JedisConnectionFactory();
}
*/
@Bean
LettuceConnectionFactory redisConnectionFactory(RedisClusterConfiguration redisConfiguration) {
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
poolConfig.setMaxIdle(-1);
poolConfig.setMinIdle(10);
poolConfig.setMaxWaitMillis(3000);
poolConfig.setMaxTotal(200);
LettucePoolingClientConfiguration lettucePoolingClientConfiguration = LettucePoolingClientConfiguration.builder()
.commandTimeout(Duration.ofSeconds(10))
.shutdownTimeout(Duration.ZERO)
.poolConfig(poolConfig)
.build();
return new LettuceConnectionFactory(redisConfiguration, lettucePoolingClientConfiguration);
}
// 我对spring boot的启动过程run方法进行了debug
// 执行完 AbstractApplicationContext.refresh() => finishBeanFactoryInitialization(beanFactory);
// 查看 beanFactory.beanDefinitionMap,会看到
// redisConnectionFactory=Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=redisConfig; factoryMethodName=redisConnectionFactory; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [com/lyhistory/redis/RedisConfig.class
// 可以明确的看到这个redisConnectionFactory也就是子类LettuceConnectionFactory 就是上面定义的bean,路径是我们自定义的该类 [com/lyhistory/redis/RedisConfig.class]
//
// 如果将前面的bean注释掉,再debug
// 会看到
// redisConnectionFactory=Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.data.redis.LettuceConnectionConfiguration; factoryMethodName=redisConnectionFactory; initMethodName=null; destroyMethodName=(inferred);
// 路径变成了 [org/springframework/boot/autoconfigure/data/redis/LettuceConnectionConfiguration.class],
@Bean
public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory connectionFactory){//(RedisConnectionFactory connectionFactory) {// LettuceConnectionFactory implements RedisConnectionFactory
final RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
template.setConnectionFactory(connectionFactory);
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class);
template.setValueSerializer(fastJsonRedisSerializer);
//template.setValueSerializer(new GenericToStringSerializer<Object>(Object.class));
return template;
}
}
前面想复杂了,实际比较简单
在 spring-boot-autoconfigure的 org.springframework.boot.autoconfigure.data.redis; 看到很简单的 ConditionalOnMissingBean,
就是说当没有找到用户自定义的这些connectionFactory就会默认创建,可见,用户自定义的优先级肯定是比较高的,应该是在前面的程序启动过程中加载bean的时候优先加载的,而后才是加载第三方定义的这些默认的bean
@Configuration
@ConditionalOnClass(RedisClient.class)
class LettuceConnectionConfiguration extends RedisConnectionConfiguration {
。。。。。。。。。。。。。
@Bean
@ConditionalOnMissingBean(RedisConnectionFactory.class)
public LettuceConnectionFactory redisConnectionFactory(
ClientResources clientResources) throws UnknownHostException {
LettuceClientConfiguration clientConfig = getLettuceClientConfiguration(
clientResources, this.properties.getLettuce().getPool());
return createLettuceConnectionFactory(clientConfig);
}
private LettuceConnectionFactory createLettuceConnectionFactory(
LettuceClientConfiguration clientConfiguration) {
if (getSentinelConfig() != null) {
return new LettuceConnectionFactory(getSentinelConfig(), clientConfiguration);
}
if (getClusterConfiguration() != null) {
return new LettuceConnectionFactory(getClusterConfiguration(),
clientConfiguration);
}
return new LettuceConnectionFactory(getStandaloneConfig(), clientConfiguration);
}
。。。。。。。。。。。。。
# performance
7min到40s:SpringBoot启动优化实践 https://juejin.cn/post/7181342523728592955
refer: 具体解析可以参考 https://www.javatt.com/p/19819