文章目录
mybatis小demo
spring整合mybatis
mybatis配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<typeAlias type="org.example.jdbc.User" alias="User"/>
</typeAliases>
<mappers>
<mapper resource="mybatis/UserMappper.xml" />
</mappers>
</configuration>
spring配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql:///test?serverTimezone=UTC"></property>
<!--<property name="url" value="jdbc:mysql://localhost:3306/test?serverTimezone=UTC"></property>-->
<property name="username" value="root"></property>
<property name="password" value="root"></property>
<property name="initialSize" value="1"></property>
<property name="maxIdle" value="2"></property>
<property name="minIdle" value="1"></property>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:spring-mybatis/SqlMapconfig.xml"/>
</bean>
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="org.example.mybatis.UserMapper"></property>
<property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
</bean>
</beans>
查看入口类继承层次
主要继承了InitializingBean,FactoryBean还有EventListener
InitializingBean:bean初始化bean后会调用afterPropertiesSet用于对bean属性做一些操作,和配置文件自定义init-method一样,只不过执行顺序比init早
FactoryBean:通过getObject获取bean
EventListener:用于事件监听
查看SqlSessionFactoryBean初始化前做了啥
public void afterPropertiesSet() throws Exception {
notNull(dataSource, "Property 'dataSource' is required");
notNull(sqlSessionFactoryBuilder, "Property 'sqlSessionFactoryBuilder' is required");
state((configuration == null && configLocation == null) || !(configuration != null && configLocation != null),
"Property 'configuration' and 'configLocation' can not specified with together");
this.sqlSessionFactory = buildSqlSessionFactory();
}
/*
主要对mybatis配置的一些别名,配置文件路径的支持,可以直接省略mybatis配置文件
*/
protected SqlSessionFactory buildSqlSessionFactory() throws Exception {
final Configuration targetConfiguration;
XMLConfigBuilder xmlConfigBuilder = null;
if (this.configuration != null) {
targetConfiguration = this.configuration;
if (targetConfiguration.getVariables() == null) {
targetConfiguration.setVariables(this.configurationProperties);
} else if (this.configurationProperties != null) {
targetConfiguration.getVariables().putAll(this.configurationProperties);
}
}
//设置mybatis配置文件路径
else if (this.configLocation != null) {
//使用mybatis构造config属性信息
xmlConfigBuilder = new XMLConfigBuilder(this.configLocation.getInputStream(), null, this.configurationProperties);
targetConfiguration = xmlConfigBuilder.getConfiguration();
} else {
LOGGER.debug(
() -> "Property 'configuration' or 'configLocation' not specified, using default MyBatis Configuration");
targetConfiguration = new Configuration();
Optional.ofNullable(this.configurationProperties).ifPresent(targetConfiguration::setVariables);
}
Optional.ofNullable(this.objectFactory).ifPresent(targetConfiguration::setObjectFactory);
Optional.ofNullable(this.objectWrapperFactory).ifPresent(targetConfiguration::setObjectWrapperFactory);
Optional.ofNullable(this.vfs).ifPresent(targetConfiguration::setVfsImpl);
//mybatis配置别名支持
if (hasLength(this.typeAliasesPackage)) {
scanClasses(this.typeAliasesPackage, this.typeAliasesSuperType).stream()
.filter(clazz -> !clazz.isAnonymousClass()).filter(clazz -> !clazz.isInterface())
.filter(clazz -> !clazz.isMemberClass()).forEach(targetConfiguration.getTypeAliasRegistry()::registerAlias);
}
if (!isEmpty(this.typeAliases)) {
Stream.of(this.typeAliases).forEach(typeAlias -> {
targetConfiguration.getTypeAliasRegistry().registerAlias(typeAlias);
LOGGER.debug(() -> "Registered type alias: '" + typeAlias + "'");
});
}
if (!isEmpty(this.plugins)) {
Stream.of(this.plugins).forEach(plugin -> {
targetConfiguration.addInterceptor(plugin);
LOGGER.debug(() -> "Registered plugin: '" + plugin + "'");
});
}
if (hasLength(this.typeHandlersPackage)) {
scanClasses(this.typeHandlersPackage, TypeHandler.class).stream().filter(clazz -> !clazz.isAnonymousClass())
.filter(clazz -> !clazz.isInterface()).filter(clazz -> !Modifier.isAbstract(clazz.getModifiers()))
.forEach(targetConfiguration.getTypeHandlerRegistry()::register);
}
if (!isEmpty(this.typeHandlers)) {
Stream.of(this.typeHandlers).forEach(typeHandler -> {
targetConfiguration.getTypeHandlerRegistry().register(typeHandler);
LOGGER.debug(() -> "Registered type handler: '" + typeHandler + "'");
});
}
if (!isEmpty(this.scriptingLanguageDrivers)) {
Stream.of(this.scriptingLanguageDrivers).forEach(languageDriver -> {
targetConfiguration.getLanguageRegistry().register(languageDriver);
LOGGER.debug(() -> "Registered scripting language driver: '" + languageDriver + "'");
});
}
Optional.ofNullable(this.defaultScriptingLanguageDriver)
.ifPresent(targetConfiguration::setDefaultScriptingLanguage);
if (this.databaseIdProvider != null) {// fix #64 set databaseId before parse mapper xmls
try {
targetConfiguration.setDatabaseId(this.databaseIdProvider.getDatabaseId(this.dataSource));
} catch (SQLException e) {
throw new NestedIOException("Failed getting a databaseId", e);
}
}
Optional.ofNullable(this.cache).ifPresent(targetConfiguration::addCache);
if (xmlConfigBuilder != null) {
try {
xmlConfigBuilder.parse();
LOGGER.debug(() -> "Parsed configuration file: '" + this.configLocation + "'");
} catch (Exception ex) {
throw new NestedIOException("Failed to parse config resource: " + this.configLocation, ex);
} finally {
ErrorContext.instance().reset();
}
}
targetConfiguration.setEnvironment(new Environment(this.environment,
this.transactionFactory == null ? new SpringManagedTransactionFactory() : this.transactionFactory,
this.dataSource));
if (this.mapperLocations != null) {
if (this.mapperLocations.length == 0) {
LOGGER.warn(() -> "Property 'mapperLocations' was specified but matching resources are not found.");
} else {
for (Resource mapperLocation : this.mapperLocations) {
if (mapperLocation == null) {
continue;
}
try {
XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(mapperLocation.getInputStream(),
targetConfiguration, mapperLocation.toString(), targetConfiguration.getSqlFragments());
xmlMapperBuilder.parse();
} catch (Exception e) {
throw new NestedIOException("Failed to parse mapping resource: '" + mapperLocation + "'", e);
} finally {
ErrorContext.instance().reset();
}
LOGGER.debug(() -> "Parsed mapper file: '" + mapperLocation + "'");
}
}
} else {
LOGGER.debug(() -> "Property 'mapperLocations' was not specified.");
}
return this.sqlSessionFactoryBuilder.build(targetConfiguration);
}
工厂方法加载
@Override
public SqlSessionFactory getObject() throws Exception {
if (this.sqlSessionFactory == null) {
afterPropertiesSet();
}
return this.sqlSessionFactory;
}
整合前获取对象
...
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
...
现在获取对象
ApplicationContext bf = new ClassPathXmlApplicationContext("spring-mybatis/spring-mybatis.xml");
UserMapper userService = (UserMapper) bf.getBean("userMapper");
MapperFactoryBean的加载
现在获取对象是直接spring获取,没有经过session,对于我们来说是直接加入spirng容器了,使我们忽略了对session的感知.也就是说spring封装了获取对象的过程,直接加入spring容器管理,其中逻辑主要MapperFactoryBean实现
分析层次可知主要主要实现了FactoryBean和InitializingBean.
afterPropertiesSet实现初始化
/*
dao校验以及初始化
*/
public final void afterPropertiesSet() throws IllegalArgumentException, BeanInitializationException {
// Let abstract subclasses check their configuration.
//模板设计模式,主要子类实现
checkDaoConfig();
// Let concrete implementations initialize themselves.
try {
//对dao初始化
initDao();
}
catch (Exception ex) {
throw new BeanInitializationException("Initialization of DAO failed", ex);
}
}
/*
分别对sqlSessionFactory映射接口,接口对应文件存在性校验
*/
protected void checkDaoConfig() {
//对sqlSessionTemplate非空判断,也就是注入的sqlSessionFactory
super.checkDaoConfig();
//映射接口判断,也就是需要代理的mapper
notNull(this.mapperInterface, "Property 'mapperInterface' is required");
Configuration configuration = getSqlSession().getConfiguration();
//映射文件存在性校验
//是否注入了此接口,一般扫描mapper.xml的时候就加入了此接口
if (this.addToConfig && !configuration.hasMapper(this.mapperInterface)) {
try {
//映射类型注册,内部做了xml配置文件的映射
configuration.addMapper(this.mapperInterface);
} catch (Exception e) {
logger.error("Error while adding the mapper '" + this.mapperInterface + "' to configuration.", e);
throw new IllegalArgumentException(e);
} finally {
ErrorContext.instance().reset();
}
}
}
FactoryBean的获取对象方法,可以看到基本跟原生mybatis获取对象方式一致
@Override
public T getObject() throws Exception {
return getSqlSession().getMapper(this.mapperInterface);
}
使用自动扫描生成mapper代理
注入自动
**spring配置文件**
```java
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql:///test?serverTimezone=UTC"></property>
<!--<property name="url" value="jdbc:mysql://localhost:3306/test?serverTimezone=UTC"></property>-->
<property name="username" value="root"></property>
<property name="password" value="root"></property>
<property name="initialSize" value="1"></property>
<property name="maxIdle" value="2"></property>
<property name="minIdle" value="1"></property>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:spring-mybatis/SqlMapconfig.xml"/>
</bean>
<!--使用扫描解决-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="org.example.mybatis"></property>
</bean>
</beans>
分析MapperScannerConfigurer接口继承层次
主要继承了InitializingBean和BeanFactoryPostProcessor接口
首先查看InitializingBean实现
发现只是对basePackage进行断言
@Override
public void afterPropertiesSet() throws Exception {
notNull(this.basePackage, "Property 'basePackage' is required");
}
查看BeanFactoryPostProcessor实现
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// left intentionally blank
}
查看BeanFactoryPostProcessor的子类BeanDefinitionRegistryPostProcessor
/*
对BeanDefinitionRegistry类型的处理
遍历所有硬编码注册的beanFactoryPostProcessors
当为BeanDefinitionRegistryPostProcessor类型
则执行postProcessBeanDefinitionRegistry
并添加注册处理器集合
不符合直接添加常规后置处理器
遍历配置文件注入的BeanDefinitionRegistryPostProcessor
保存继承PriorityOrdered排序接口的对象
按照PriorityOrdered排序当前处理器
添加所有的当前注册处理器到注册处理器中
当前处理器执行执行postProcessBeanDefinitionRegistry方法
清空当前注册处理器
遍历配置文件注入的BeanDefinitionRegistryPostProcessor
保存继承Ordered排序接口的对象
按照Ordered排序当前处理器
添加所有的当前注册处理器到注册处理器中
当前处理器执行执行postProcessBeanDefinitionRegistry方法
清空当前注册处理器
循环遍历以及调用postProcessBeanDefinitionRegistry方法
...
调用所有的继承了BeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法
调用传来的postProcessBeanFactory的postProcessBeanFactory方法
获取所有继承了BeanFactoryPostProcessor的接口,并分别排序,和无序调用
清除缓存的合并bean定义
*/
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<>();
//对BeanDefinitionRegistry类型的处理
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
//记录通过硬编码方式注册的BeanFactoryPostProcessor
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
//记录通过硬编码方式注册的BeanDefinitionRegistryPostProcessor
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
//对于BeanDefinitionRegistryPostProcessor类型,在beanFactoryPostProcessor的基础上还有自己定义的方法,需要先调用
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
//执行postProcessBeanDefinitionRegistry方法
//mybatis整合spring的时候,注解扫描使用
registryProcessor.postProcessBeanDefinitionRegistry(registry);
//...
}
/*
对占位符配置属性的支持
设置注入的值
生成对应过滤器控制扫描结果
完成扫描
*/
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
//对占位符配置属性的支持
/*
postProcessBeanDefinitionRegistry执行的时候会早于BeanFactoryPostProcessor
这就导致PropertyResourceConfigurer没被执行,也就没加载所有属性文件
像{var}子类的变量无法解析
*/
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));
}
/*
分别采用加载配置类或者环境变量类替换占位符值
*/
private void processPropertyPlaceHolders() {
//找到所有PropertyResourceConfigurer类型的bean
Map<String, PropertyResourceConfigurer> prcs = applicationContext.getBeansOfType(PropertyResourceConfigurer.class);
if (!prcs.isEmpty() && applicationContext instanceof ConfigurableApplicationContext) {
//继承了BeanNameAware,所以在setName注入了类名
BeanDefinition mapperScannerBean = ((ConfigurableApplicationContext) applicationContext).getBeanFactory()
.getBeanDefinition(beanName);
// PropertyResourceConfigurer does not expose any methods to explicitly perform
// property placeholder substitution. Instead, create a BeanFactory that just
// contains this mapper scanner and post process the factory.
//模拟spring容器加载处理器
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
//注册registerBeanDefinition
factory.registerBeanDefinition(beanName, mapperScannerBean);
//执行后置处理器
for (PropertyResourceConfigurer prc : prcs.values()) {
prc.postProcessBeanFactory(factory);
}
//如果有{var}子类的变量,则被替换
PropertyValues values = mapperScannerBean.getPropertyValues();
this.basePackage = updatePropertyValue("basePackage", values);
this.sqlSessionFactoryBeanName = updatePropertyValue("sqlSessionFactoryBeanName", values);
this.sqlSessionTemplateBeanName = updatePropertyValue("sqlSessionTemplateBeanName", values);
this.lazyInitialization = updatePropertyValue("lazyInitialization", values);
}
//环境变量解析占位符
this.basePackage = Optional.ofNullable(this.basePackage).map(getEnvironment()::resolvePlaceholders).orElse(null);
this.sqlSessionFactoryBeanName = Optional.ofNullable(this.sqlSessionFactoryBeanName)
.map(getEnvironment()::resolvePlaceholders).orElse(null);
this.sqlSessionTemplateBeanName = Optional.ofNullable(this.sqlSessionTemplateBeanName)
.map(getEnvironment()::resolvePlaceholders).orElse(null);
this.lazyInitialization = Optional.ofNullable(this.lazyInitialization).map(getEnvironment()::resolvePlaceholders)
.orElse(null);
}
/*
设置扫描类的规则
*/
public void registerFilters() {
boolean acceptAllInterfaces = true;
// if specified, use the given annotation and / or marker interface
//对annotationClass属性处理
if (this.annotationClass != null) {
//AnnotationTypeFilter保证在扫描对应java文件的时只接受标记有注解为annotationClass的接口
addIncludeFilter(new AnnotationTypeFilter(this.annotationClass));
acceptAllInterfaces = false;
}
// override AssignableTypeFilter to ignore matches on the actual marker interface
//对markerInterface属性处理
if (this.markerInterface != null) {
//AssignableTypeFilter保证在扫描对应java文件的时只接受实现markerInterface的接口
addIncludeFilter(new AssignableTypeFilter(this.markerInterface) {
@Override
protected boolean matchClassName(String className) {
return false;
}
});
acceptAllInterfaces = false;
}
//接受所有接口文件
if (acceptAllInterfaces) {
// default include filter that accepts all classes
addIncludeFilter((metadataReader, metadataReaderFactory) -> true);
}
// exclude package-info.java
//不扫描package-info.java
addExcludeFilter((metadataReader, metadataReaderFactory) -> {
String className = metadataReader.getClassMetadata().getClassName();
return className.endsWith("package-info");
});
}
//扫描包并注册注解配置处理器
public int scan(String... basePackages) {
int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
doScan(basePackages);
// Register annotation config processors, if necessary.
//如果配置了includeAnnotationConfig,则注册对应注解的处理器以保证注解功能的正常使用
if (this.includeAnnotationConfig) {
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
//返回扫描条件的BeanDefinition个数
return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
}
扫描包名
/*
调用父类扫描路径生成BeanDefinitionHolder
利用MapperFactoryBean对每个beanDefinitions生成mapper
*/
public Set<BeanDefinitionHolder> doScan(String... basePackages) {
Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);
if (beanDefinitions.isEmpty()) {
LOGGER.warn(() -> "No MyBatis mapper was found in '" + Arrays.toString(basePackages)
+ "' package. Please check your configuration.");
} else {
//利用MapperFactoryBean对每个beanDefinitions生成mapper
processBeanDefinitions(beanDefinitions);
}
return beanDefinitions;
}
/*
扫描包,生成BeanDefinition
对注解bean的处理
注册bean
*/
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
for (String basePackage : basePackages) {
//扫描包下basePackage路径下java文件
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
//解析scope
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
//构造名字,通常类名首字母小写
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
//如果是AnnotatedBeanDefinition类型的Bean
if (candidate instanceof AnnotatedBeanDefinition) {
// 检测常用注解,如primary,Lazy,DependsOn,Role等
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
//检测当前bean是否注册
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
//如果当前bean使用来生成代理的bean,进行下一步处理
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
//注册BeanDefinition,以及别名
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
}
else {
//执行扫描
return scanCandidateComponents(basePackage);
}
}
/*
拼接路径扫描所有类,根据之前配置的过滤器过滤掉class
*/
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
Set<BeanDefinition> candidates = new LinkedHashSet<>();
try {//classpath*: /**/*.class
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + '/' + this.resourcePattern;
//获取包下解析的class
Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
boolean traceEnabled = logger.isTraceEnabled();
boolean debugEnabled = logger.isDebugEnabled();
for (Resource resource : resources) {
if (traceEnabled) {
logger.trace("Scanning " + resource);
}
//是否可读
if (resource.isReadable()) {
try {
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
//扫描当前文件是否符合要求
if (isCandidateComponent(metadataReader)) {
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setResource(resource);
sbd.setSource(resource);
if (isCandidateComponent(sbd)) {
if (debugEnabled) {
logger.debug("Identified candidate component class: " + resource);
}
candidates.add(sbd);
}
else {
if (debugEnabled) {
logger.debug("Ignored because not a concrete top-level class: " + resource);
}
}
}
else {
if (traceEnabled) {
logger.trace("Ignored because not matching any filter: " + resource);
}
}
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to read candidate component class: " + resource, ex);
}
}
else {
if (traceEnabled) {
logger.trace("Ignored because not readable: " + resource);
}
}
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
}
return candidates;
}
/*
使用registerFilters配置的过滤器过滤
*/
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
//org.mybatis.spring.mapper.ClassPathMapperScanner.registerFilters设置了是否包含某个文件的逻辑
//对exclued的处理
for (TypeFilter tf : this.excludeFilters) {
if (tf.match(metadataReader, getMetadataReaderFactory())) {
return false;
}
}
//对include的处理
for (TypeFilter tf : this.includeFilters) {
if (tf.match(metadataReader, getMetadataReaderFactory())) {
return isConditionMatch(metadataReader);
}
}
return false;
}
利用MapperFactoryBean对每个beanDefinitions生成mapper
/*
利用MapperFactoryBean对每个beanDefinitions生成mapper
*/
private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {
GenericBeanDefinition definition;
for (BeanDefinitionHolder holder : beanDefinitions) {
definition = (GenericBeanDefinition) holder.getBeanDefinition();
String beanClassName = definition.getBeanClassName();
LOGGER.debug(() -> "Creating MapperFactoryBean with name '" + holder.getBeanName() + "' and '" + beanClassName
+ "' mapperInterface");
// the mapper interface is the original class of the bean
// but, the actual class of the bean is MapperFactoryBean
//构造注入mapperInterface
definition.getConstructorArgumentValues().addGenericArgumentValue(beanClassName); // issue #59
//设置MapperFactoryBean
definition.setBeanClass(this.mapperFactoryBeanClass);
definition.getPropertyValues().add("addToConfig", this.addToConfig);
boolean explicitFactoryUsed = false;
if (StringUtils.hasText(this.sqlSessionFactoryBeanName)) {
definition.getPropertyValues().add("sqlSessionFactory",
new RuntimeBeanReference(this.sqlSessionFactoryBeanName));
explicitFactoryUsed = true;
} else if (this.sqlSessionFactory != null) {
definition.getPropertyValues().add("sqlSessionFactory", this.sqlSessionFactory);
explicitFactoryUsed = true;
}
if (StringUtils.hasText(this.sqlSessionTemplateBeanName)) {
if (explicitFactoryUsed) {
LOGGER.warn(
() -> "Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored.");
}
definition.getPropertyValues().add("sqlSessionTemplate",
new RuntimeBeanReference(this.sqlSessionTemplateBeanName));
explicitFactoryUsed = true;
} else if (this.sqlSessionTemplate != null) {
if (explicitFactoryUsed) {
LOGGER.warn(
() -> "Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored.");
}
definition.getPropertyValues().add("sqlSessionTemplate", this.sqlSessionTemplate);
explicitFactoryUsed = true;
}
if (!explicitFactoryUsed) {
LOGGER.debug(() -> "Enabling autowire by type for MapperFactoryBean with name '" + holder.getBeanName() + "'.");
//设置自动注入根据类型,就是在这里会根据类型自动注入sqlSessionFactory
definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
}
//是否应延迟初始化此bean。
definition.setLazyInit(lazyInitialization);
}
}
注入sqlSessionFactory
不知道大家有没有发现这里没有注入非常重要的元素*sqlSessionFactory***
配置文件里面配置了2个参数注入,然后生成mapper,这里少了sqlSessionFactory
<property name="mapperInterface" value="org.example.mybatis.UserMapper"></property>
<property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
sqlSessionFactory的注入过程实际上是根据这个函数注入的
//设置自动注入根据类型,就是在这里会根据类型自动注入sqlSessionFactory
definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
当执行到这步的时候,会根据类型注入所有的set方法,其中sqlSessionFactory就设置了set方法
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean
/*
填充属性判断
执行InstantiationAwareBeanPostProcessor
根据注入类型选择不同处理
根据名称自动注入
根据类型自动注入
执行InstantiationAwareBeanPostProcessor
依赖检查
应用属性
*/
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
...
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
//根据名称自动注入
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
//根据类型自动注入,注入所有set方法的属性
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
...
会在如下部,自动注入
/*
查询需要依赖注入的属性
遍历注入属性
获取指定属性set方法
解析指定beanName的属性所匹配的值,并存储参数
注册依赖
*/
protected void autowireByType(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
//存储所有依赖的bean
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
//寻找bw中需要依赖注入的属性
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
try {
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
// Don't try autowiring by type for type Object: never makes sense,
// even if it technically is a unsatisfied, non-simple property.
if (Object.class != pd.getPropertyType()) {
//探测指定属性set方法
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
// Do not allow eager init for type matching in case of a prioritized post-processor.
boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
//解析指定beanName的属性所匹配的值,并把解析到的属性名称存储在autowiredArgument中
//当属性存在多个封装bean时如:
///@Autowired private List<A>aList;将会找到所有匹配A类型的bean并将其注入
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
if (autowiredArgument != null) {
pvs.add(propertyName, autowiredArgument);
}
for (String autowiredBeanName : autowiredBeanNames) {
//注册依赖
registerDependentBean(autowiredBeanName, beanName);
if (logger.isTraceEnabled()) {
logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" +
propertyName + "' to bean named '" + autowiredBeanName + "'");
}
}
autowiredBeanNames.clear();
}
} catch (BeansException ex) {
throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
}
}
}