Spring Frameworkのdefault scope
ほう > A Java geek » Changing default Spring bean scope http://t.co/mTCShFYH2y
— kinjouj (@kinjou_j) 2014, 11月 3
っていう事でやってみた
SampleService.java
package sample;
import org.springframework.stereotype.Service;
@Service
public class SampleService {
}
通常だとこういうクラスを依存性注入するような事をした場合にはデフォルトではsingletonインスタンススコープになっている
SampleTest.java
package sample;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.junit.Assert.*;
import static org.hamcrest.Matchers.*;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({ "classpath:applicationContext.xml" })
public class SampleTest {
@Autowired
private SampleService service1;
@Autowired
private SampleService service2;
@Test public void test() {
assertThat(service1, not(sameInstance(service2)));
}
}
上記で書いたように依存性注入されるインスタンススコープはsingletonなのでservice1とservice2のインスタンスは同一のになる。よってこのテストは成功しない
で上記参考によるとBeanFactoryPostProcessorを実装して動的にprototypeインスタンス方式になるようにスコープを書き換える事で可能らしい
CustomBeanFactoryPostProcessor.java
package sample;
import org.springframework.beans.BeansException;
@Component
public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanDefinitionName);
String className = beanDefinition.getBeanClassName();
if (className.startsWith("sample") && "singleton".equals(beanDefinition.getScope())) {
beanDefinition.setScope("prototype");
}
}
}
}
ってな感じで作っておいて、再度テストを実行すると今度はテストが成功する。動的にscopeをprototypeにする事で依存性注入される際にインスタンススコープがprototypeになる為にテストの要件である「インスタンスが異なる」部分が問題なくテストされてる
んまぁ物によっちゃsingletonスコープをprottypeスコープに動的に書き換える事で諸問題が発生してきそうな気もするけど、勉強になったのでメモ