java 如何确保使用 Spring @Configuration 注释初始化依赖配置?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3261082/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I ensure dependent configurations are initialized with Spring @Configuration annotation?
提问by jhericks
I am trying to use @Configuration annotations to wire up my application but I keep getting a NullPointerException in one of the initializers because the bean it refers to is not yet initialized (I think). I have tried specifying in the web.xml just the 'root' config class and also tried doing a package scan and neither seem to work.
我正在尝试使用 @Configuration 注释来连接我的应用程序,但我一直在其中一个初始化程序中收到 NullPointerException,因为它引用的 bean 尚未初始化(我认为)。我尝试在 web.xml 中仅指定“root”配置类,并尝试进行包扫描,但似乎都不起作用。
Sorry about the big code dump. I tried to produce a much simpler set of classes to reproduce the issue, but of course, when I did that, everything worked fine.Here are my classes (imports elided):
对大代码转储感到抱歉。 我试图生成一组更简单的类来重现该问题,但是当然,当我这样做时,一切正常。这是我的课程(省略了导入):
DataSourceConfig.java:
数据源配置.java:
@Configuration
public class DataSourceConfig {
public DataSourceConfig() {
System.err.println("DataSourceConfig constructed...");
}
@Bean
public DataSource dataSource() {
BasicDataSource bean = new BasicDataSource();
bean.setDriverClassName("com.mysql.jdbc.Driver");
bean.setUrl("jdbc:mysql://localhost:3306/observation");
bean.setUsername("observation");
bean.setPassword("*******");
bean.setInitialSize(1);
bean.setMaxActive(5);
bean.setTestOnBorrow(true);
System.err.println("dataSource bean initialized: " + bean.toString());
return bean;
}
}
HibernateConfig.java
休眠配置文件
@Configuration
@Import(DataSourceConfig.class)
public class HibernateConfig {
public HibernateConfig() {
System.err.println("HibernateConfig constructing...");
}
@Autowired
private DataSourceConfig dataSourceConfig;
@Bean
protected NamingStrategy namingStrategy() {
return new ImprovedNamingStrategy();
}
private AnnotationSessionFactoryBean sessionFactoryBean = null;
@Bean
@DependsOn("dataSourceConfig")
public AnnotationSessionFactoryBean sessionFactory() {
if (sessionFactoryBean == null) {
sessionFactoryBean = new AnnotationSessionFactoryBean();
NPE Here--> sessionFactoryBean.setDataSource(dataSourceConfig.dataSource());
sessionFactoryBean.setSchemaUpdate(true);
sessionFactoryBean.setNamingStrategy(namingStrategy());
sessionFactoryBean.setPackagesToScan(new String[] {
"com.newco.observations.domain",
"com.newco.observations.domain.*" });
Properties props = new Properties();
props.setProperty("hibernate.default_schema", "observation");
props.setProperty("hibernate.dialect",
"org.hibernate.dialect.MySQLDialect");
props.setProperty("hibernate.show_sql", "true");
sessionFactoryBean.setHibernateProperties(props);
System.err.println("sessionFactory initialized");
}
return sessionFactoryBean;
}
@Bean
@DependsOn("dataSourceConfig")
public JdbcTemplate jdbcTemplate() {
return new JdbcTemplate(dataSourceConfig.dataSource());
}
@Bean
@DependsOn("sessionFactory")
public ResourceTransactionManager txManager() {
HibernateTransactionManager bean = new HibernateTransactionManager();
bean.setSessionFactory((SessionFactory) sessionFactory().getObject());
return bean;
}
@Bean
@DependsOn("sessionFactory")
public HibernateTemplate hibernateTemplate() {
return new HibernateTemplate((SessionFactory) sessionFactory()
.getObject());
}
}
DaoConfig.java:
DaoConfig.java:
@Configuration
@Import(HibernateConfig.class)
public class DaoConfig {
public DaoConfig()
{
System.err.println("DaoConfig constructing...");
}
private @Autowired HibernateConfig hibernateConfig;
@Bean
@DependsOn("hibernateTemplate")
public PhenomenonGroupDao phenomenonGroupDao()
{
PhenomenonGroupDaoImpl bean = new PhenomenonGroupDaoImpl();
bean.setHibernateTemplate(hibernateConfig.hibernateTemplate());
return bean;
}
@Bean
@DependsOn("hibernateTemplate")
public PhenomenonDao phenomenonDao()
{
PhenomenonDaoImpl bean = new PhenomenonDaoImpl();
bean.setHibernateTemplate(hibernateConfig.hibernateTemplate());
return bean;
}
@Bean
@DependsOn("hibernateTemplate")
public DiscretePhenomenonDao discretePhenomenonDao()
{
DiscretePhenomenonDaoImpl bean = new DiscretePhenomenonDaoImpl();
bean.setHibernateTemplate(hibernateConfig.hibernateTemplate());
return bean;
}
}
You can see from the System.err.println's and the @DependsOn annotations a kind of flailing about that I'm doing.
您可以从 System.err.println 和 @DependsOn 注释中看到我正在做的事情。
I can provide the full log if it's useful, but here is what I think are the relevant lines (with a little formatting to make it more readable (maybe)):
如果有用,我可以提供完整的日志,但这是我认为的相关行(带有一些格式以使其更具可读性(可能)):
- 208 [Thread-0] INFO org.springframework.context.annotation.ConfigurationClassEnhancer
- Successfully enhanced com.bjk.observation.server.config.DaoConfig; enhanced class name is: com.bjk.observation.server.config.DaoConfig$$EnhancerByCGLIB$$96e1956
- 229 [Thread-0] INFO org.springframework.beans.factory.support.DefaultListableBeanFactory
- Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@185572a: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor, org.springframework.context.annotation.internalAutowiredAnnotationProcessor, org.springframework.context.annotation.internalRequiredAnnotationProcessor, org.springframework.context.annotation.internalCommonAnnotationProcessor, org.springframework.context.annotation.internalPersistenceAnnotationProcessor, daoConfig,com.bjk.observation.server.config.DataSourceConfig#0, dataSource, com.bjk.observation.server.config.HibernateConfig#0, namingStrategy, sessionFactory, jdbcTemplate, txManager, hibernateTemplate, phenomenonGroupDao, phenomenonDao, discretePhenomenonDao]; root of factory hierarchy DaoConfig constructing...
- 252 [Thread-0] INFO org.springframework.beans.factory.support.DefaultListableBeanFactory
- Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@185572a: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor, org.springframework.context.annotation.internalAutowiredAnnotationProcessor, org.springframework.context.annotation.internalRequiredAnnotationProcessor, org.springframework.context.annotation.internalCommonAnnotationProcessor, org.springframework.context.annotation.internalPersistenceAnnotationProcessor, daoConfig, com.bjk.observation.server.config.DataSourceConfig#0, dataSource, com.bjk.observation.server.config.HibernateConfig#0, namingStrategy, sessionFactory, jdbcTemplate, txManager, hibernateTemplate, phenomenonGroupDao, phenomenonDao, discretePhenomenonDao]; root of factory hierarchy
- 253 [Thread-0] ERROR org.springframework.web.context.ContextLoader
- Context initialization failed org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'daoConfig': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.bjk.observation.server.config.HibernateConfig com.bjk.observation.server.config.DaoConfig.hibernateConfig; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.bjk.observation.server.config.HibernateConfig#0': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.bjk.observation.server.config.HibernateConfig]: Constructor threw exception; nested exception is java.lang.NullPointerException
- 208 [Thread-0] INFO org.springframework.context.annotation.ConfigurationClassEnhancer
- 成功增强com.bjk.observation.server.config.DaoConfig;增强类名称为:com.bjk.observation.server.config.DaoConfig$$EnhancerByCGLIB$$96e1956
- 229 [Thread-0] INFO org.springframework.beans.factory.support.DefaultListableBeanFactory
- 在 org.springframework.beans.factory.support.DefaultListableBeanFactory@185572a 中预实例化单例:定义 beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor, org.springframework.context.annotation.internalAutowiredAnnotationProcessor, orgtext.springframework.context.annotation.internalConfigurationAnnotationProcessor, internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,daoConfig,com.bjk.observation.server.config.DataSourceConfig#0,数据源,com.bjk.config.observation HibernateConfig#0、namingStrategy、sessionFactory、jdbcTemplate、txManager、hibernateTemplate、现象组道、现象道、离散现象道];工厂层次结构的根 DaoConfig 构造...
- 252 [线程-0] 信息 org.springframework.beans.factory.support.DefaultListableBeanFactory
- 销毁 org.springframework.beans.factory.support.DefaultListableBeanFactory@185572a 中的单例:定义 bean [org.springframework.context.annotation.internalConfigurationAnnotationProcessor, org.springframework.context.annotation.internalAutowiredAnnotationProcessor, org.springframework.intext.annotation.internalConfigurationAnnotationProcessor, org.springframework.context.annotation.internalConfigurationAnnotationProcessor, org.springframework.context.annotation.internalConfigurationAnnotationProcessor org.springframework.context.annotation.internalCommonAnnotationProcessor, org.springframework.context.annotation.internalPersistenceAnnotationProcessor, daoConfig, com.bjk.observation.server.config.DataSourceConfig#0, dataSource, com.bjk.observation.Configserver.config.Hibernate 0、namingStrategy、sessionFactory、jdbcTemplate、txManager、hibernateTemplate、现象GroupDao、现象Dao、discretePhenomenonDao];工厂层次结构的根
- 253 [Thread-0] 错误 org.springframework.web.context.ContextLoader
- 上下文初始化失败 org.springframework.beans.factory.BeanCreationException:创建名为“daoConfig”的 bean 时出错:自动装配依赖项的注入失败;嵌套异常是 org.springframework.beans.factory.BeanCreationException:无法自动装配字段:private com.bjk.observation.server.config.HibernateConfig com.bjk.observation.server.config.DaoConfig.hibernateConfig; 嵌套异常是 org.springframework.beans.factory.BeanCreationException:创建名为 'com.bjk.observation.server.config.HibernateConfig#0' 的 bean 时出错:bean 实例化失败;嵌套异常是 org.springframework.beans.BeanInstantiationException:无法实例化 bean 类 [com.bjk.observation.server.config.HibernateConfig]:构造函数抛出异常;嵌套异常是 java.lang.NullPointerException
回答by skaffman
The problem, I believe is here:
问题,我相信是在这里:
@Autowired
private DataSourceConfig dataSourceConfig;
You're not supposed to explicitly wire yourself with other @Configuration-annotated classes, but rather the beans that they produce. Spring will sort out the plumbing for you.
您不应该将自己与其他带@Configuration注释的类显式连接起来,而应该使用它们生成的 bean。春天会为你整理水管。
So replace the above field with the simpler:
所以用更简单的替换上面的字段:
@Autowired
private DataSource dataSource;
Spring will fetch the DataSourcefrom DataSourceConfigand transparently inject it into the field.
Spring 将获取DataSourcefromDataSourceConfig并将其透明地注入到字段中。
Similarly, replace
同样,替换
@Autowired
private HibernateConfig hibernateConfig;
with
和
@Autowired
private HibernateTemplate hibernateTemplate;
You'll notice that the @Configurationstyle doesn't feel as nice when working with factory beans like AnnotationSessionFactoryBean, since you often have to call getObject()on it yourself. Sometimes, it's more natural to use XML config, and mix it with the java config style.
您会注意到,在@Configuration使用工厂 bean 时,这种风格感觉不太好AnnotationSessionFactoryBean,因为您经常需要自己调用getObject()它。有时,使用 XML 配置更自然,并将其与 java 配置样式混合使用。

