首页 > 代码库 > spring+mybati java config配置引起的bean相互引用日志报警告问题
spring+mybati java config配置引起的bean相互引用日志报警告问题
摘要: Error creating bean with name ‘XXX‘: Requested bean is currently in creation: Is there an unresolvable circular reference?; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException:
如果把MapperScan单独配置,就不会有警告
报循环引用警告的配置
/** * 数据源配置 * 数据源配置个人觉得还是xml好些。用xml配置改动增加配置只需重启 * * @author doctor * * @time 2015年3月3日 下午2:57:10 */@Configurationpublic class DataSourceConfig { @Bean public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { return new PropertySourcesPlaceholderConfigurer(); } @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface DbH2 { } /** * H2 数据原配置 * 不用import ,原因文档见:{@code Configuration}文档中的With nested Configuration classes部分 * spring源码如何处理见: * {@link org.springframework.context.annotation.ConfigurationClassParser#processMemberClasses(ConfigurationClass, SourceClass) } * * @author doctor * * @time 2015年3月3日 下午3:26:15 */ @Configuration @MapperScan(basePackages = { "com.doctor.spring4.common.mapper" }, annotationClass = DbH2.class, sqlSessionFactoryRef = "dbH2SqlSessionFactory") @PropertySource("classpath:/spring4_2015Pro/jdbc-H2.properties") static class MybatisH2Config { @Value("${jdbc.H2.url}") private String url; @Value("${jdbc.H2.user}") private String user; @Value("${jdbc.H2.password}") private String password; @Value("${jdbc.H2.driverClassName}") private String driverClassName; @Value("${jdbc.H2.initialSize}") private int initialSize; @Value("${jdbc.H2.minIdle}") private int minIdle; @Value("${jdbc.H2.maxActive}") private int maxActive; @Value("${jdbc.H2.maxWait}") private long maxWait; @Value("${jdbc.H2.minEvictableIdleTimeMillis}") private long minEvictableIdleTimeMillis; @Value("${jdbc.H2.timeBetweenEvictionRunsMillis}") private long timeBetweenEvictionRunsMillis; @Value("${jdbc.H2.validationQuery}") private String validationQuery; @Value("${jdbc.H2.testWhileIdle}") private boolean testWhileIdle; @Value("${jdbc.H2.testOnBorrow}") private boolean testOnBorrow; @Value("${jdbc.H2.testOnReturn}") private boolean testOnReturn; @Value("${jdbc.H2.poolPreparedStatements}") private boolean poolPreparedStatements; @Value("${jdbc.H2.maxPoolPreparedStatementPerConnectionSize}") private int maxPoolPreparedStatementPerConnectionSize; @Bean(name = "dbH2DataSource", initMethod = "init", destroyMethod = "close") public DataSource dbH2DataSource() { DruidDataSource druidDataSource = new DruidDataSource(); druidDataSource.setUrl(url); druidDataSource.setUsername(user); druidDataSource.setPassword(password); druidDataSource.setDriverClassName(driverClassName); druidDataSource.setInitialSize(initialSize); druidDataSource.setMinIdle(minIdle); druidDataSource.setMaxActive(maxActive); druidDataSource.setMaxWait(maxWait); druidDataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); druidDataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); druidDataSource.setValidationQuery(validationQuery); druidDataSource.setTestWhileIdle(testWhileIdle); druidDataSource.setTestOnBorrow(testOnBorrow); druidDataSource.setTestOnReturn(testOnReturn); druidDataSource.setPoolPreparedStatements(poolPreparedStatements); druidDataSource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize); return druidDataSource; } @Bean(name = "dbH2SqlSessionFactory") @Resource(name = "dbH2DataSource") public SqlSessionFactory DbH2SqlSessionFactory(DataSource dataSource) throws Exception { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(dataSource); sqlSessionFactoryBean.setTypeHandlersPackage(""); sqlSessionFactoryBean.setConfigLocation(new ClassPathResource("/spring4_2015Config/mybatis-db-config.xml")); return sqlSessionFactoryBean.getObject(); } }}
dbH2DataSource,dbH2SqlSessionFactory,MapperScan有依赖关系.
如果把MapperScan单独配置,就不会有警告,例如:
/** * 数据源配置 * 数据源配置个人觉得还是xml好些。用xml配置改动增加配置只需重启 * * @author doctor * * @time 2015年3月3日 下午2:57:10 */@Configurationpublic class DataSourceConfig { @Bean public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { return new PropertySourcesPlaceholderConfigurer(); } @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface DbH2 { } /** * H2 数据原配置 * 不用import ,原因文档见:{@code Configuration}文档中的With nested Configuration classes部分 * spring源码如何处理见: * {@link org.springframework.context.annotation.ConfigurationClassParser#processMemberClasses(ConfigurationClass, SourceClass) } * * @author doctor * * @time 2015年3月3日 下午3:26:15 */ @Configuration @PropertySource("classpath:/spring4_2015Pro/jdbc-H2.properties") static class MybatisH2Config { @Value("${jdbc.H2.url}") private String url; @Value("${jdbc.H2.user}") private String user; @Value("${jdbc.H2.password}") private String password; @Value("${jdbc.H2.driverClassName}") private String driverClassName; @Value("${jdbc.H2.initialSize}") private int initialSize; @Value("${jdbc.H2.minIdle}") private int minIdle; @Value("${jdbc.H2.maxActive}") private int maxActive; @Value("${jdbc.H2.maxWait}") private long maxWait; @Value("${jdbc.H2.minEvictableIdleTimeMillis}") private long minEvictableIdleTimeMillis; @Value("${jdbc.H2.timeBetweenEvictionRunsMillis}") private long timeBetweenEvictionRunsMillis; @Value("${jdbc.H2.validationQuery}") private String validationQuery; @Value("${jdbc.H2.testWhileIdle}") private boolean testWhileIdle; @Value("${jdbc.H2.testOnBorrow}") private boolean testOnBorrow; @Value("${jdbc.H2.testOnReturn}") private boolean testOnReturn; @Value("${jdbc.H2.poolPreparedStatements}") private boolean poolPreparedStatements; @Value("${jdbc.H2.maxPoolPreparedStatementPerConnectionSize}") private int maxPoolPreparedStatementPerConnectionSize; @Bean(name = "dbH2DataSource", initMethod = "init", destroyMethod = "close") public DataSource dbH2DataSource() { DruidDataSource druidDataSource = new DruidDataSource(); druidDataSource.setUrl(url); druidDataSource.setUsername(user); druidDataSource.setPassword(password); druidDataSource.setDriverClassName(driverClassName); druidDataSource.setInitialSize(initialSize); druidDataSource.setMinIdle(minIdle); druidDataSource.setMaxActive(maxActive); druidDataSource.setMaxWait(maxWait); druidDataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); druidDataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); druidDataSource.setValidationQuery(validationQuery); druidDataSource.setTestWhileIdle(testWhileIdle); druidDataSource.setTestOnBorrow(testOnBorrow); druidDataSource.setTestOnReturn(testOnReturn); druidDataSource.setPoolPreparedStatements(poolPreparedStatements); druidDataSource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize); return druidDataSource; } @Bean(name = "dbH2SqlSessionFactory") @Resource(name = "dbH2DataSource") public SqlSessionFactory DbH2SqlSessionFactory(DataSource dataSource) throws Exception { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(dataSource); sqlSessionFactoryBean.setTypeHandlersPackage(""); sqlSessionFactoryBean.setConfigLocation(new ClassPathResource("/spring4_2015Config/mybatis-db-config.xml")); return sqlSessionFactoryBean.getObject(); } } @Configuration @MapperScan(basePackages = { "com.doctor.spring4.common.mapper" }, annotationClass = DbH2.class, sqlSessionFactoryRef = "dbH2SqlSessionFactory") static class MyBatisMapperConfig { // MapperScan注解不要和数据源定义的配置写在一起,(如MybatisH2Config配置上), // 否此会导致循环引用初始化bean问题. // 看来xml配置还是有优势的 // 03-11 17:01:50.010 main WARN o.s.b.f.s.DefaultListableBeanFactory - Bean creation // exception on FactoryBean type check: // org.springframework.beans.factory.BeanCreationException: Error creating bean with name // ‘userMapper‘ defined in file // [/home/cui/workspace/spring4-2015/target/classes/com/doctor/spring4/common/mapper/UserMapper.class]: // Cannot resolve reference to bean ‘dbH2SqlSessionFactory‘ while setting bean property // ‘sqlSessionFactory‘; nested exception is // org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean // with name ‘dbH2SqlSessionFactory‘: Requested bean is currently in creation: Is there an // unresolvable circular reference? }}
但是最好的配置还是如下:
/** * 数据源配置 * 数据源配置个人觉得还是xml好些。用xml配置改动增加配置只需重启 * * 注意:MybatisH2Config 类中两个有依赖关系的bean注入方法,不要用set方法形式注入, * 有可能导致注入循环引用问题.(@MapperScan 注解在MybatisH2Config,而且注解依赖里面的bean定义). * @author doctor * * @time 2015年3月3日 下午2:57:10 */@Configurationpublic class DataSourceConfig { @Bean public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { return new PropertySourcesPlaceholderConfigurer(); } @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface DbH2 { } /** * H2 数据原配置 * 不用import ,原因文档见:{@code Configuration}文档中的With nested Configuration classes部分 * spring源码如何处理见: * {@link org.springframework.context.annotation.ConfigurationClassParser#processMemberClasses(ConfigurationClass, SourceClass) } * * @author doctor * * @time 2015年3月3日 下午3:26:15 */ @Configuration @MapperScan(basePackages = { "com.doctor.spring4.common.mapper" }, annotationClass = DbH2.class, sqlSessionFactoryRef = "dbH2SqlSessionFactory") @PropertySource("classpath:/spring4_2015Pro/jdbc-H2.properties") static class MybatisH2Config { @Value("${jdbc.H2.url}") private String url; @Value("${jdbc.H2.user}") private String user; @Value("${jdbc.H2.password}") private String password; @Value("${jdbc.H2.driverClassName}") private String driverClassName; @Value("${jdbc.H2.initialSize}") private int initialSize; @Value("${jdbc.H2.minIdle}") private int minIdle; @Value("${jdbc.H2.maxActive}") private int maxActive; @Value("${jdbc.H2.maxWait}") private long maxWait; @Value("${jdbc.H2.minEvictableIdleTimeMillis}") private long minEvictableIdleTimeMillis; @Value("${jdbc.H2.timeBetweenEvictionRunsMillis}") private long timeBetweenEvictionRunsMillis; @Value("${jdbc.H2.validationQuery}") private String validationQuery; @Value("${jdbc.H2.testWhileIdle}") private boolean testWhileIdle; @Value("${jdbc.H2.testOnBorrow}") private boolean testOnBorrow; @Value("${jdbc.H2.testOnReturn}") private boolean testOnReturn; @Value("${jdbc.H2.poolPreparedStatements}") private boolean poolPreparedStatements; @Value("${jdbc.H2.maxPoolPreparedStatementPerConnectionSize}") private int maxPoolPreparedStatementPerConnectionSize; @Bean(name = "dbH2DataSource", initMethod = "init", destroyMethod = "close") public DataSource dbH2DataSource() { DruidDataSource druidDataSource = new DruidDataSource(); druidDataSource.setUrl(url); druidDataSource.setUsername(user); druidDataSource.setPassword(password); druidDataSource.setDriverClassName(driverClassName); druidDataSource.setInitialSize(initialSize); druidDataSource.setMinIdle(minIdle); druidDataSource.setMaxActive(maxActive); druidDataSource.setMaxWait(maxWait); druidDataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); druidDataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); druidDataSource.setValidationQuery(validationQuery); druidDataSource.setTestWhileIdle(testWhileIdle); druidDataSource.setTestOnBorrow(testOnBorrow); druidDataSource.setTestOnReturn(testOnReturn); druidDataSource.setPoolPreparedStatements(poolPreparedStatements); druidDataSource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize); return druidDataSource; } @Bean(name = "dbH2SqlSessionFactory") public SqlSessionFactory DbH2SqlSessionFactory() throws Exception { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(dbH2DataSource()); sqlSessionFactoryBean.setTypeHandlersPackage(""); sqlSessionFactoryBean.setConfigLocation(new ClassPathResource("/spring4_2015Config/mybatis-db-config.xml")); return sqlSessionFactoryBean.getObject(); } }}
https://my.oschina.net/doctor2014/blog/386431
Requested bean is currently in creation: Is there an unresolvable circular reference?
getBean的时候由于bean之间存在循环依赖出现类似的错误,先做一个简单实验模拟一下这个异常出现的原因:
bean.xml配置如下:
<?xml version="1.0" encoding="GBK"?>
<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"
default-autowire="byName">
<bean id="a" class="BeanA" scope="prototype"/>
<bean id="b" class="BeanB" scope="prototype"/>
</beans>
BeanA类如下:
public class BeanA
{
private BeanB b;
public BeanB getB() {
return b;
}
public void setB(BeanB b) {
this.b = b;
}
}
BeanB类如下:
public class BeanB
{
private BeanA a;
public BeanA getA() {
return a;
}
public void setA(BeanA a) {
this.a = a;
}
}
程序执行的堆栈信息:
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
会抛出一个异常:Requested bean is currently in creation: Is there an unresolvable circular reference,然后scope是singlton或者其他的时候bean的创建过程不一样,不会有一个这样子的判断,因而不会抛出这样子的错误。
因为scope=prototype,所以每次请求对应不同的bean,所以在创建的时候有一个依赖的先后顺序,而如果bean配置成singleton,则属性间初始化的顺序可以无所谓了,所有的bean都只有一份,所以在bean是singleton时候不会报unresolvable circular reference的错误。
spring+mybati java config配置引起的bean相互引用日志报警告问题
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。