2011年10月15日土曜日

@PostConstructと@PreDestroyの悩み

アノテーションの使い方を前回で書いたのはいいんだけども。

ちょっと気になったので試したら悩みができた。。。
@Autowiredとか@Resourceとかで設定した場合でprototype指定されていたら、
ApplicationContextを直接持ってないとこでdestroyって呼べなくね?みたいな。
ApplicationContext持ち回せばいいのかな。。。。

試しに以下のようなコードを書いたが確かにdestroyは呼ばれない。(前回試してるから当たり前なんだが)
クラスを2重にするのがめんどくさかったのでJUnitで。。。。

対象Bean
package com.zomu.t.example;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component("testComponent")
@Scope("prototype")
public class TestComponent {

 @PostConstruct
 public void init() {
  System.out.println("init.");
 }

 public void outputMsg() {
  System.out.println("msg....");
 }

 @PreDestroy
 public void destroy() {
  System.out.println("destroy.");
 }

}


実行クラス
package com.zomu.t.example;

import javax.annotation.Resource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:ApplicationContext.xml" })
public class TestInitDestroy2 {

 @Resource(name = "testComponent")
 TestComponent tc = null;

 @Test
 public void main() {
  tc.outputMsg();
 }
}


んーどうすりゃいいんだ。
思いつくのはこれしかない。

実行クラス
package com.zomu.t.example;

import javax.annotation.Resource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:StoreManager-Common-ApplicationContext.xml" })
public class TestInitDestroy2 {

 @Resource(name = "testComponent")
 TestComponent tc = null;

 @Autowired
 ConfigurableApplicationContext appContext = null;

 @Test
 public void main() {
  tc.outputMsg();

  appContext.getBeanFactory().destroyBean("testComponent", tc);
 }
}
やってることは、前回と変わりはない。ApplicationContextと手を握り合って「バルス」って唱えただけ。

これだと当たり前にdestroyも呼ばれるんだが。
他にいい方法ってないの?

0 件のコメント:

コメントを投稿