Spring Frameworkのdefault scope

2014-11-03T00:00:00+00:00 Java Spring Framework

っていう事でやってみた

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スコープに動的に書き換える事で諸問題が発生してきそうな気もするけど、勉強になったのでメモ

POIでExcelを生成する Javaで同時リクエストをテストする方法