mybatis(A component required a bean of type 'org.apache.ibatis.session.Configuration' that could not be found.)原因、日志问题,兼容默认mybatis配置
mybatis(A component required a bean of type 'org.apache.ibatis.session.Configuration' that could not be found.)原因、日志问题,兼容默认mybatis配置
这个问题一般是需要自定义SqlSessionFactory需要使用到org.apache.ibatis.session.Configuration默认配置,但是新版本mybatis已经不会将Configuration作为bean注入到spring中管理,因此需要自己来创建并兼容mybatis默认配置项
获取到MybatisProperties(mybatis配置)的信息,去创建一个org.apache.ibatis.session.Configuration,然后去添加自定义的操作
复制
@Bean
public SqlSessionFactoryBean sqlSessionFactoryBean(
DynamicDataSource dynamicDataSource,
List<ConfigurationCustomizer> configurationCustomizers
) {
org.apache.ibatis.session.Configuration configuration = null;
MybatisProperties.CoreConfiguration coreConfiguration = mybatisProperties.getConfiguration();
if (Objects.nonNull(coreConfiguration) || !StringUtils.hasText(mybatisProperties.getConfigLocation())) {
configuration = new org.apache.ibatis.session.Configuration();
}
if (Objects.nonNull(configuration) && Objects.nonNull(coreConfiguration)) {
coreConfiguration.applyTo(configuration);
}
if (Objects.nonNull(configuration) && !CollectionUtils.isEmpty(configurationCustomizers)) {
for (ConfigurationCustomizer customizer : configurationCustomizers) {
customizer.customize(configuration);
}
}
// 设置日志输出
configuration.setLogImpl(mybatisProperties.getConfiguration().getLogImpl());
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setTransactionFactory(new MultiDataSourceTransactionFactory(dataSourceProperties.getDefaultDataSourceName()));
sqlSessionFactoryBean.setDataSource(dynamicDataSource);
// 添加插件
List<Interceptor> interceptors = new ArrayList<>(configuration.getInterceptors());
// interceptors.add(new DemoPlugin());
sqlSessionFactoryBean.addPlugins(interceptors.toArray(new Interceptor[]{}));
// 设置xml文件路径
List<String> mapperLocations = List.of(mybatisProperties.getMapperLocations());
if (mapperLocations.isEmpty()) {
log.warn("未设置mapper-locations");
}
List<org.springframework.core.io.Resource> resources = new ArrayList<>();
mapperLocations.forEach(item -> {
try {
resources.addAll(List.of(new PathMatchingResourcePatternResolver().getResources(item)));
} catch (IOException e) {
log.warn("mapper-location读取异常,异常路径是: {}", item);
}
});
sqlSessionFactoryBean.setMapperLocations(resources.toArray(new org.springframework.core.io.Resource[]{}));
sqlSessionFactoryBean.setConfiguration(configuration);
return sqlSessionFactoryBean;
}
这里提一下,常用的log-impl配置项org.apache.ibatis.logging.stdout.StdOutImpl,没有做日志级别管理,这里直接看源码。可以看到isDebugEnabled方法直接返回为true的,所以在应用启动时会打印很多:Parsed mapper file: xxxx
StdOutImpl
复制
package org.apache.ibatis.logging.stdout;
import org.apache.ibatis.logging.Log;
/**
* @author Clinton Begin
*/
public class StdOutImpl implements Log {
public StdOutImpl(String clazz) {
// Do Nothing
}
@Override
public boolean isDebugEnabled() {
return true;
}
@Override
public boolean isTraceEnabled() {
return true;
}
@Override
public void error(String s, Throwable e) {
System.err.println(s);
e.printStackTrace(System.err);
}
@Override
public void error(String s) {
System.err.println(s);
}
@Override
public void debug(String s) {
System.out.println(s);
}
@Override
public void trace(String s) {
System.out.println(s);
}
@Override
public void warn(String s) {
System.out.println(s);
}
}
这里还有常见的这个信息:Logging initialized using xxx
LogFactory
复制
private static void setImplementation(Class<? extends Log> implClass) {
try {
Constructor<? extends Log> candidate = implClass.getConstructor(String.class);
Log log = candidate.newInstance(LogFactory.class.getName());
if (log.isDebugEnabled()) {
log.debug("Logging initialized using '" + implClass + "' adapter.");
}
logConstructor = candidate;
} catch (Throwable t) {
throw new LogException("Error setting Log implementation. Cause: " + t, t);
}
}
SqlSessionFactoryBean
复制
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 IOException("Failed to parse mapping resource: '" + mapperLocation + "'", e);
} finally {
ErrorContext.instance().reset();
}
// 这里的LOGGER是通过mybatis的LoggerFactory.getLogger(SqlSessionFactoryBean.class)获取到的,最终会调用org.apache.ibatis.logging.LogFactory方法去获取当前所使用的日志
// 而org.mybatis.logging.Logger中的debug方法会调用org.apache.ibatis.logging.Log接口的isDebugEnabled方法,获取日志级别
// StdOutImpl、Slf4jImpl等都是实现org.apache.ibatis.logging.Log接口的
LOGGER.debug(() -> "Parsed mapper file: '" + mapperLocation + "'");
}
作者:https://blog.xn--rpv331d.com/望舒
链接:https://blog.xn--rpv331d.com/望舒/blog/20
转载注意保留文章出处...
1
0
51
No data