gpt4 book ai didi

java - 使用 BeanFactoryPostProcessor 创建 bean

转载 作者:搜寻专家 更新时间:2023-11-01 02:10:31 26 4
gpt4 key购买 nike

Spring BeanFactoryPostProcessor问题

我想创建一个 Spring BeanFactoryPostProcessor,将 bean 添加到当前的 ApplicationContext。

我的 spring-ws-config.xml 中有很多 Web 服务定义,我想尽可能地减少。

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 来自动创建 beans,所以我这样写:

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);
}
}

但是,这不行!,我写了一个简单的测试,你可以看看here

我看到 IOC 不使用带有注释的类,这是因为方法:BeanFactory#getBeansWithAnnotation 不初始化它,将其标记为已创建,并且不注入(inject)任何东西。

解决方法

我做了一个解决方法:按名称获取所有 beans,获取相应的类并使用 #bf.getBeansOfType(Class),(此方法不初始化它!)。

我的问题:

  • 这是一个有效的解决方法?
  • 如何使用 #getBeansWithAnnotation() 方法而不初始化 bean?

最佳答案

问题是BeanFactoryPostProcessor不能和实例一起工作,而#getBeansWithAnnotation()返回实例,所以不推荐,这里相关Javadoc :

BeanFactoryPostProcessor 可以与 bean 定义交互并修改 bean 定义,但不能与 bean 实例交互。这样做可能会导致 bean 过早实例化,违反容器并导致意外的副作用。如果需要 bean 实例交互,请考虑改为实现 BeanPostProcessor。

所以我的解决方案是这样的:

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory bf)
throws BeansException {

String[] beans = bf.getBeanDefinitionNames();
for (String s : beans) {
Class<?> beanType = bf.getType(s);
WebService ws = AnnotationUtils.findAnnotation(beanType,
WebService.class);
if (ws != null) {
String name = getName(s);
DefaultWsdl11Definition newWS = createWebService(name,
ws.xsds());

bf.registerSingleton(name, newWS);
}
}

}

关于java - 使用 BeanFactoryPostProcessor 创建 bean,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19458152/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com