码迷,mamicode.com
首页 > 编程语言 > 详细

spring+mybati java config配置引起的bean相互引用日志报警告问题

时间:2016-11-15 23:50:49      阅读:1237      评论:0      收藏:0      [点我收藏+]

标签:sql   map   .class   schema   member   cannot   引用   ssi   ret   

摘要: 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
 */
@Configuration
public 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
 */
@Configuration
public 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
 */
@Configuration
public 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;
}
}
程序执行的堆栈信息:
技术分享
 
bean在初始化的同时会初始化相应的属性(byName),a在初始化的时候会创建a.b,a.b在初始化的时候会创建a.b.a,形成了一个环,所以在AbstractBeanFactory.doGetBean(这里会出现递归调用) 时候 ,走到:
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相互引用日志报警告问题

标签:sql   map   .class   schema   member   cannot   引用   ssi   ret   

原文地址:http://www.cnblogs.com/softidea/p/6067593.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!