Spring BeanFactoryPostProcessor の問題
現在の ApplicationContext に Bean を追加する Spring BeanFactoryPostProcessor を作成したいと考えています。
社内に多数の Web サービス定義があり、spring-ws-config.xml
できるだけ削減したいと考えています。
XML 構成
構成は次のようになります。
<bean id="menu"
class="org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition"
lazy-init="true">
<property name="schemaCollection">
<bean
class="org.springframework.xml.xsd.commons.CommonsXsdSchemaCollection">
<property name="inline" value="true" />
<property name="xsds">
<list>
<value>classpath:xsd.xsd</value>
</list>
</property>
</bean>
</property>
<property name="portTypeName" value="portType" />
<property name="serviceName" value="serviceName" />
<property name="locationUri" value="/endpoints" />
</bean>
Java 構成
そこで、次の Bean 定義を使用して @Configuration クラスを作成します。
@Bean
@Lazy
public DefaultWsdl11Definition webService() throws IOException {
logger.info("Creating Web Service");
DefaultWsdl11Definition toRet = new DefaultWsdl11Definition();
toRet.setPortTypeName("portType");
toRet.setServiceName("serviceName");
CommonsXsdSchemaCollection collection = new CommonsXsdSchemaCollection();
collection.setInline(true);
collection.setXsds(new Resource[] { new ClassPathResource("path1") });
collection.afterPropertiesSet();
toRet.setSchemaCollection(collection);
toRet.setLocationUri("/endpoints");
return toRet;
}
これでだいぶマシになりました! でももっと減らしたいので @WebServiceDefinition というアノテーションをつけて BeanFactoryPostProcessor をつけて bean を自動生成したいのでこう書きました。
BeanFactoryPostProcessor
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory bf)
throws BeansException {
Map<String, Object> beans = bf.getBeansWithAnnotation(WebService.class);
for (Entry<String, Object> entry : beans.entrySet()) {
Object bean = entry.getValue();
WebService ws = bean.getClass().getAnnotation(WebService.class);
String name = getName(entry.getKey());
DefaultWsdl11Definition newWS = createWebService(name, ws.xsds());
bf.registerSingleton(name, newWS);
}
}
しかし、これはうまくいきません!簡単なテストを書きました。ここで見ることができます
IOC が注釈付きのクラスで機能しないことがわかります。これは、メソッド BeanFactory#getBeansWithAnnotation が初期化せず、作成済みとしてマークし、何も注入しないためです。
回避策
名前ですべての Bean を取得し、対応するクラスを取得して、#bf.getBeansOfType(Class) を使用します (このメソッドは初期化しません!)。
私の質問:
- これは有効な回避策ですか?
- メソッド #getBeansWithAnnotation() を使用して、Bean を初期化しないようにするにはどうすればよいですか?