【问题标题】:How to call custom data loader on Spring application start如何在 Spring 应用程序启动时调用自定义数据加载器
【发布时间】:2012-11-08 05:32:16
【问题描述】:

我正在尝试在应用程序启动时将一些数据加载到我的数据库中。我为此目的定义了一个 bean

applicationContext.xml

<bean class="com.project.loader.DataLoader" 
id="DataLoader" 
depends-on="entityManagerFactory" 
scope="singleton"/>

类:

@RooJavaBean
@RooConfigurable
public class DataLoader implements InitializingBean

它正在执行,但是在调用第一个 persist() 方法时,Spring 向我抛出以下错误:

Caused by: java.lang.IllegalStateException: Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)
at com.project.lib.model.extensions.i18n.Locale_Roo_Jpa_ActiveRecord.entityManager_aroundBody0(Locale_Roo_Jpa_ActiveRecord.aj:19)
at com.project.lib.model.extensions.i18n.Locale_Roo_Jpa_ActiveRecord.ajc$interMethod$com_project_lib_model_extensions_i18n_Locale_Roo_Jpa_ActiveRecord$com_project_lib_model_extensions_i18n_Locale$entityManager(Locale_Roo_Jpa_ActiveRecord.aj:1)
at com.project.lib.model.extensions.i18n.Locale.entityManager(Locale.java:1)

以前当我以下列方式定义 DataLoader 时它正在工作:

@Component
@Configurable
public class DataLoader implements ApplicationListener

但使用原始类型不是一个好习惯,所以我想切换

我怎样才能让它工作?

春季版:3.1

【问题讨论】:

  • 你认为删除@Component 重要吗?
  • 在我当前的实现(最上面一个)中,组件被移除,bean 被定义在 applicationContext 中。它正在使用@Component 和 IoC 扫描,但是问题在于使用原始类型 ApplicationListener 接口的不良做法。我认为 Bean 方法被调用得太早了......
  • 如果您只担心原始类型,为什么不直接使用ApplicationListener&lt;ContextRefreshedEvent&gt; 或类似的东西?
  • ...最重要的是我想要一些我可以控制执行顺序的东西。对其他 bean 的依赖对我有用,但是在这种情况下,对 entityManagerFactory 的依赖是不够的。

标签: java spring web-applications spring-roo


【解决方案1】:

我过去通过将组件扫描定义移动到应用程序上下文的末尾解决了这个问题,正如 here 建议的那样

【讨论】:

  • 这不是我想要的。您使用 ApplicationListener 这使得类被调用几次。如果没有找到更好的解决方案,我会坚持这一点。谢谢。
【解决方案2】:

我使用spring SmartLifecycle: http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/context/SmartLifecycle.html

我创建了一个可以很好地做到这一点的类,只需扩展和覆盖 run 方法:

public abstract class StartupService implements SmartLifecycle {
/** Logger for this class and subclasses */
protected static final Logger logger = LoggerFactory.getLogger(StartupService.class);

protected boolean running=false;

////////////////////// Lifecycle Methods \\\\\\\\\\\\\\\\\\
@Override
public void start() {
    try {
        logger.info("starting {}", this.getClass().getSimpleName());
        run();
    } catch (Exception e) {
        logger.error("failed to run importer", e);
    }
}

@Override
public void stop() {
    running=false;
}

@Override
public boolean isRunning() {
    return running;
}

////////////////////// SmartLifecycle Methods \\\\\\\\\\\\\\\\\\
@Override
public boolean isAutoStartup() {
    return true;
}

@Override
public void stop(Runnable callback) {
    stop();
    callback.run();
}

@Override
public int getPhase() {
    return 0;
}

public abstract void run() throws Exception;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-29
    • 1970-01-01
    • 1970-01-01
    • 2011-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多