回答:
「アプリケーションの起動」が「アプリケーションコンテキストの起動」を意味する場合、そうです。これを行う方法はたくさんあります。最も簡単な方法は(とにかくシングルトンBeanの場合)、でメソッドに注釈を付けることです@PostConstruct
。リンクを見て他のオプションを確認しますが、要約すると次のとおりです。
@PostConstruct
afterPropertiesSet()
InitializingBean
コールバックインターフェイスで定義されているとおり技術的には、これらはコンテキストライフサイクルではなくBeanライフサイクルへのフックですが、99%の場合、2つは同等です。
特にコンテキストの起動/シャットダウンにフックする必要がある場合は、Lifecycle
代わりにインターフェースを実装できますが、それはおそらく不要です。
Access restriction: The type PostConstruct is not accessible due to restriction on required library /Library/Java/JavaVirtualMachines/jdk1.8.0_05.jdk/Contents/Home/jre/lib/rt.jar
@PostConstruct
メソッドが呼び出されましたが、間接的に依存しているJMSインフラストラクチャはまだ完全に接続されていません(そして、すべてが静かに失敗しただけです)。機能する@EventListener(ApplicationReadyEvent.class)
すべてのものに切り替える際に(ApplicationReadyEvent
バニラスプリングに固有のスプリングブートについては、Stefanの回答を参照してください)。
これはで簡単に行えApplicationListener
ます。私はこれをSpring'sを聞いて動作させるようにしましたContextRefreshedEvent
:
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
@Component
public class StartupHousekeeper implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(final ContextRefreshedEvent event) {
// do whatever you need here
}
}
アプリケーションリスナーは、Springで同期的に実行されます。コードが1度だけ実行されるようにしたい場合は、コンポーネントの状態を維持してください。
更新
Spring 4.2以降では、@EventListener
アノテーションを使用してContextRefreshedEvent
(これを指摘してくれた@bphilipnycに感謝)を観察することもできます。
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
@Component
public class StartupHousekeeper {
@EventListener(ContextRefreshedEvent.class)
public void contextRefreshedEvent() {
// do whatever you need here
}
}
ContextStartedEvent
代わりに使用したい人のために注意してください、イベントが発生する前にリスナーを追加することは困難です。
Spring 4.2以降では、次の操作を簡単に実行できます。
@Component
class StartupHousekeeper {
@EventListener(ContextRefreshedEvent.class)
public void contextRefreshedEvent() {
//do whatever
}
}
スプリングブートを使用している場合、これが最良の答えです。
@PostConstruct
と他のさまざまなライフサイクル間投詞はラウンドアラウンド方法だと思います。これらは、ランタイムの問題に直接つながるか、予期しないBean /コンテキストライフサイクルイベントが原因で、明らかではない欠陥を引き起こす可能性があります。単純なJavaを使用してBeanを直接呼び出すだけではどうですか。それでも、Beanを「春の方法」で呼び出します(例:春のAoPプロキシを介して)。そして何よりも、それはプレーンJavaであり、それよりも簡単なものはありません。コンテキストリスナーや奇妙なスケジューラーは必要ありません。
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
ConfigurableApplicationContext app = SpringApplication.run(DemoApplication.class, args);
MyBean myBean = (MyBean)app.getBean("myBean");
myBean.invokeMyEntryPoint();
}
}
main()
アプリケーションフレームワーク(JavaServer Facesなど)を使用する場合など、まったくないシナリオもあります。
@PostConstructアノテーションを参照しようとすると警告が表示されるJava 1.8ユーザーの場合は、代わりに、@ Scheduledアノテーションをピギーバックして、fixedRateまたはfixedDelayの@Scheduledジョブがある場合に実行できるようにしました。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@EnableScheduling
@Component
public class ScheduledTasks {
private static final Logger LOGGER = LoggerFactory.getLogger(ScheduledTasks.class);
private static boolean needToRunStartupMethod = true;
@Scheduled(fixedRate = 3600000)
public void keepAlive() {
//log "alive" every hour for sanity checks
LOGGER.debug("alive");
if (needToRunStartupMethod) {
runOnceOnlyOnStartup();
needToRunStartupMethod = false;
}
}
public void runOnceOnlyOnStartup() {
LOGGER.debug("running startup job");
}
}
私たちが行ったことはorg.springframework.web.context.ContextLoaderListener
、コンテキストの開始時に何かを印刷するように拡張することでした。
public class ContextLoaderListener extends org.springframework.web.context.ContextLoaderListener
{
private static final Logger logger = LoggerFactory.getLogger( ContextLoaderListener.class );
public ContextLoaderListener()
{
logger.info( "Starting application..." );
}
}
次にサブクラスを構成しweb.xml
ます。
<listener>
<listener-class>
com.mycomp.myapp.web.context.ContextLoaderListener
</listener-class>
</listener>
注意が必要なのは、
runOnceOnStartup
メソッドが完全に初期化されたSpringコンテキストに依存している場合のみです。例:トランザクション境界でdaoを呼び出したい
また、fixedDelayを非常に高く設定して、スケジュールされたメソッドを使用することもできます。
@Scheduled(fixedDelay = Long.MAX_VALUE)
public void runOnceOnStartup() {
dosomething();
}
これには、アプリケーション全体が結び付けられているという利点があります(トランザクション、Daoなど)。
@PostConstruct
か?
WebApplicationInitializerを実装する別のソリューションを投稿し、誰かがその使用例を持っている場合に備えて、Spring Beanがインスタンス化される前に呼び出されます
AppStartListener implements ApplicationListener {
@Override
public void onApplicationEvent(ApplicationEvent event) {
if(event instanceof ApplicationReadyEvent){
System.out.print("ciao");
}
}
}
@EventListener
サーバーでの起動とすべてのBeanの初期化後に呼び出されるコンポーネントで使用できます。
@EventListener
public void onApplicationEvent(ContextClosedEvent event) {
}
StartupHousekeeper.java
パッケージにあるファイルの場合com.app.startup
、
これを行うStartupHousekeeper.java
:
@Component
public class StartupHousekeeper {
@EventListener(ContextRefreshedEvent.class)
public void keepHouse() {
System.out.println("This prints at startup.");
}
}
そしてこれを行うmyDispatcher-servlet.java
:
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<mvc:annotation-driven />
<context:component-scan base-package="com.app.startup" />
</beans>