gpt4 book ai didi

spring - 动态 Spring bean 创建

转载 作者:行者123 更新时间:2023-12-04 02:35:39 31 4
gpt4 key购买 nike

我正在使用一个 API,它以 XXXLocalServiceUtil 类的形式公开服务,这些类是单例对象的静态包装器。我不想使用静态 XXXLocalServiceUtil 方法,而是想自己注入(inject) XXXLocalService 对象以直接在我的代码中使用它们,例如:

@Named
public class MyMailingService {
@Inject UserLocalService userService;

public String mailUser(String email) {
User user = userService.getUser(email);
emailUser(user);
}
}

然后像这样配置我的 applicationContext.xml:

<beans ...>
<bean class="x.y.z.UserLocalServiceUtil" factory-method="getService"/>
<bean class="x.y.z.CompanyLocalServiceUtil" factory-method="getService"/>
...
</beans>

这非常有效。现在,我正在谈论的这个 API 有大约 100 个这样的 XXXLocalServiceUtil 类,每个类都有自己的静态 getService 方法,该方法返回实际的服务。我不想在我的 applicationContext.xml 中列出所有这些服务,我想让 Spring 为我注入(inject)的每个 XXXLocalService 找到正确的 XXXLocalServiceUtil 类。所以我需要某种动态 bean 工厂,它可以为我完成工作,当然是在延迟加载的基础上。

有人知道如何轻松实现吗?

最佳答案

您可以使用 GenericApplicationContext 将 bean 与在 xml 中声明的其余 spring bean 一起动态加载到 applicationContext。这是一个使用 Reflections library 实现的示例...

private static final Pattern SERVICE_UTIL_PATTERN = Pattern.compile(".*LocalServiceUtil.*");

public static void main(String[] args) {
ConfigurationBuilder builder = new ConfigurationBuilder().addUrls(
ClasspathHelper.forPackage("x.y.z"))
.setScanners(new SubTypesScanner(false));
Reflections reflections = new Reflections(builder);
GenericApplicationContext applicationContext = new GenericApplicationContext();
Set<Class<? extends Object>> classes = reflections.getSubTypesOf(Object.class);

for (Class<? extends Object> serviceUtilClass : classes) {
String className = serviceUtilClass.getName();

if (SERVICE_UTIL_PATTERN.matcher(className).matches()) {
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClassName(className);
beanDefinition.setFactoryMethodName("getService");
beanDefinition.setLazyInit(true);

String beanName = StringUtils.uncapitalize(serviceClass.getSimpleName().replace("Util", ""));
applicationContext.registerBeanDefinition(beanName, beanDefinition);
}
}

XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(applicationContext);
reader.loadBeanDefinitions("classpath:/applicationContext.xml");
applicationContext.refresh();
}

更新:要在 Web 应用程序中使用它,您可以简单地扩展 Spring 的 XmlWebApplicationContext 并覆盖 initBeanDefinitionReader 方法,如下所示...

private static final Pattern SERVICE_UTIL_PATTERN = Pattern.compile(".*LocalServiceUtil.*");

@Override
protected void initBeanDefinitionReader(
XmlBeanDefinitionReader beanDefinitionReader) {
ConfigurationBuilder builder = new ConfigurationBuilder().addUrls(
ClasspathHelper.forPackage("x.y.z"))
.setScanners(new SubTypesScanner(false));
Reflections reflections = new Reflections(builder);
Set<Class<? extends Object>> classes = reflections.getSubTypesOf(Object.class);
BeanDefinitionRegistry registry = beanDefinitionReader.getRegistry();

for (Class<? extends Object> serviceClass : classes) {
String className = serviceClass.getName();

if (SERVICE_UTIL_PATTERN.matcher(className).matches()) {
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClassName(className);
beanDefinition.setFactoryMethodName("getService");
beanDefinition.setLazyInit(true);
String beanName = StringUtils.uncapitalize(serviceClass
.getSimpleName().replace("Util", ""));
registry.registerBeanDefinition(beanName, beanDefinition);
}
}
}

}

并将以下 context-param 添加到您的 web.xml...

<context-param>
<param-name>contextClass</param-name>
<param-value>x.y.z.MyXmlWebApplicationContext</param-value>
</context-param>

关于spring - 动态 Spring bean 创建,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10804885/

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