Spring:在加载持久化上下文之前运行代码

时间:2014-09-19 15:35:23

标签: java database spring dao applicationcontext

我有基于弹簧的多模块应用程序。在我的DAO模块中,DB(嵌入式derby)由实现ApplicationListener的类启动和创建。

问题是在日志中有来自Spring的巨大堆栈跟踪,它表示没有数据库(无法连接)。

仍然,我的应用程序没有任何问题。此堆栈跟踪在调用ApplicationListener并创建db之前出现。实际上,只有当我第一次在机器上启动应用程序时才会看到它,因为db只创建了这个时间,而不是刚才使用的。

所以我的问题是如何在日志中避免这种异常?也许在应用程序上下文完全加载之前有spring或hibenate设置没有连接到db?或者调用由其他侦听器创建db的代码?

2 个答案:

答案 0 :(得分:0)

我想你是从正在创建的spring bean中获取数据库中的一些数据。也许是通过@PostConstruct或其他方式。请记住,在Spring上下文完全加载之前,一些bean可以注入未初始化的bean。

所以不要使用DB,不要调用任何DAO 直到你确定弹簧上下文已完全初始化。

要对DAO进行这样的初始调用,请尝试保证弹簧上下文完整性的模式:

@Component
public class SpringContextMonitor implements ApplicationListener<ApplicationEvent> {

  @Autowired
  private SomeDao dao;

  ...

  @Override
    public void onApplicationEvent(ApplicationEvent event) {
        if (event instanceof ContextRefreshedEvent) {
            onStart((ContextRefreshedEvent) event);
        }
    }

  private void onStart(ContextRefreshedEvent event) {

    // do your initialization here
    dao.getSomething();
    dao2.getSomething();
    ...

  }

  ...
}

上例中的onStart方法是您确定所有bean都已完全初始化的地方

答案 1 :(得分:0)

这就是我的方式:ROOT上下文包含数据源,dao,服务和事务管理器。在XML配置中,数据库的声明是:

<bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"
      p:url="jdbc:derby:/path/to/database;create=TRUE" 
      p:username="user" p:password="pwd"
      p:driverClassName="org.apache.derby.jdbc.EmbeddedDriver"/>

然后可以使用它来声明hibernate和相关DAO的会话工厂:

<bean class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"
      id="sessionFactory" p:dataSource-ref="datasource">
    <!-- hibernate config -->
    ...
</bean>
<bean class="org.springframework.orm.hibernate4.HibernateTransactionManager"
      name="transactionManager" p:sessionFactory-ref="sessionFactory"/>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="myDao" class="... .myDaoImpl" p:sessionFactory-ref="sessionFactory" .../>

这样所有都是由spring创建的,这可以确保创建顺序正确。当然,在Java配置中也可以使用相同的逻辑。