Java 我们可以有一个工厂类作为Springbean,并有一个工厂方法根据条件返回多个Springbean吗?
我想根据factory类中的条件返回多个Springbean 这是一种好的做法吗 有没有更好的方法来编写下面的代码?。 还有其他适合这里的设计模式吗 下面是代码片段:Java 我们可以有一个工厂类作为Springbean,并有一个工厂方法根据条件返回多个Springbean吗?,java,spring,design-patterns,factory,Java,Spring,Design Patterns,Factory,我想根据factory类中的条件返回多个Springbean 这是一种好的做法吗 有没有更好的方法来编写下面的代码?。 还有其他适合这里的设计模式吗 下面是代码片段: package com.test; import org.springframework.stereotype.Component; import javax.annotation.Resource; @Component public class InstanceFactory { @Resource(name
package com.test;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component
public class InstanceFactory {
@Resource(name = "instance1")
private Instance instance1;
@Resource(name = "instance2")
private Instance instance2;
public Instance getService(Condition condition) {
if (condition.one() && condition.two()) {
return instance2;
} else {
return instance1;
}
}
}
这取决于你想要实现什么。工厂模式是用来创建对象的,但在本例中,您返回的是已经在其他地方创建的对象。如果要创建将由Spring管理的bean,有几种方法: @ConditionalYourConditionalImplementation.class:在@Configuration注释类的方法上添加的此注释将允许您在给定条件已满时创建bean。示例如下: 您还可以使用BeanFactory将bean DefinitionBean的定义注入到容器中。示例如下:
现在,如果您想要一个对象来确定Instance类型的对象更适合某些需要,那么您的方法是可以的,但从技术上讲它不是一个工厂:它取决于您想要实现什么。工厂模式是用来创建对象的,但在本例中,您返回的是已经在其他地方创建的对象。如果要创建将由Spring管理的bean,有几种方法: @ConditionalYourConditionalImplementation.class:在@Configuration注释类的方法上添加的此注释将允许您在给定条件已满时创建bean。示例如下: 您还可以使用BeanFactory将bean DefinitionBean的定义注入到容器中。示例如下:
现在,如果您想要一个对象来确定哪种类型的对象实例更适合某些需要,那么您的方法是可以的,但从技术上讲,它不是一个工厂:在设计类似的东西时,我将面临考虑两种设计模式的解决方案: 策略模式:为了在每次需要评估更多实例时替换重复的if-else。 装饰模式:尝试使每个条件尽可能可配置。它们可以由一个或多个谓词组成。 考虑到这两种模式,您可能会实现以下目标:
public class InstanceFactory {
@Autowire
private final EnumMap<InstanceType, Instance> instancesMap;
public void getInstance(Condition condition) {
instancesMap.get(getInstanceType(condition)).doSomething();
}
private InstanceType getInstanceType(Condition condition) {
return Arrays.stream(InstancesType.values())
.filter(evaluator -> evaluator.evaluate(condition))
.findFirst().orElseThrow(() -> new RuntimeException("Instance type not found"));
}
}
首先,定义哪些条件将标识给定实例:
public enum InstanceType {
INSTANCE_TYPE_1(Condition::isOne, Condition::isTwo),
INSTANCE_TYPE_2(Condition::isOne, Condition::isThree),
...;
private List<Predicate<Condition>> evaluators;
@SafeVarargs
InstanceType(final Predicate<Condition>... evaluators) {
this.evaluators = Arrays.asList(evaluators);
}
public boolean evaluate(final Condition condition) {
return evaluators.stream().allMatch(it -> it.test(condition));
}
}
最后,一个要配置的类,其中将类型和实例之间的关系定义为EnumMap
@Configuration
public class InstanceFactoryConfig {
@Autowired
private List<Instance> instances;
@Bean
public EnumMap<InstanceType, Instance> instancesMap() {
EnumMap<InstanceType, Instance> instanceEnumMap = new EnumMap<>(InstanceType.class);
instances.forEach(i -> instanceEnumMap.put(i.getType(), i));
return instanceEnumMap;
}
}
因此,可以将InstanceFactory替换为以下内容:
public class InstanceFactory {
@Autowire
private final EnumMap<InstanceType, Instance> instancesMap;
public void getInstance(Condition condition) {
instancesMap.get(getInstanceType(condition)).doSomething();
}
private InstanceType getInstanceType(Condition condition) {
return Arrays.stream(InstancesType.values())
.filter(evaluator -> evaluator.evaluate(condition))
.findFirst().orElseThrow(() -> new RuntimeException("Instance type not found"));
}
}
如您所见,InstanceFactory不太容易被修改。这意味着,每次需要添加新实例实现时,只需修改InstanceType枚举。希望这对你有帮助 在设计这样的东西时,我会考虑两种设计模式: 策略模式:为了在每次需要评估更多实例时替换重复的if-else。 装饰模式:尝试使每个条件尽可能可配置。它们可以由一个或多个谓词组成。 考虑到这两种模式,您可能会实现以下目标:
public class InstanceFactory {
@Autowire
private final EnumMap<InstanceType, Instance> instancesMap;
public void getInstance(Condition condition) {
instancesMap.get(getInstanceType(condition)).doSomething();
}
private InstanceType getInstanceType(Condition condition) {
return Arrays.stream(InstancesType.values())
.filter(evaluator -> evaluator.evaluate(condition))
.findFirst().orElseThrow(() -> new RuntimeException("Instance type not found"));
}
}
首先,定义哪些条件将标识给定实例:
public enum InstanceType {
INSTANCE_TYPE_1(Condition::isOne, Condition::isTwo),
INSTANCE_TYPE_2(Condition::isOne, Condition::isThree),
...;
private List<Predicate<Condition>> evaluators;
@SafeVarargs
InstanceType(final Predicate<Condition>... evaluators) {
this.evaluators = Arrays.asList(evaluators);
}
public boolean evaluate(final Condition condition) {
return evaluators.stream().allMatch(it -> it.test(condition));
}
}
最后,一个要配置的类,其中将类型和实例之间的关系定义为EnumMap
@Configuration
public class InstanceFactoryConfig {
@Autowired
private List<Instance> instances;
@Bean
public EnumMap<InstanceType, Instance> instancesMap() {
EnumMap<InstanceType, Instance> instanceEnumMap = new EnumMap<>(InstanceType.class);
instances.forEach(i -> instanceEnumMap.put(i.getType(), i));
return instanceEnumMap;
}
}
因此,可以将InstanceFactory替换为以下内容:
public class InstanceFactory {
@Autowire
private final EnumMap<InstanceType, Instance> instancesMap;
public void getInstance(Condition condition) {
instancesMap.get(getInstanceType(condition)).doSomething();
}
private InstanceType getInstanceType(Condition condition) {
return Arrays.stream(InstancesType.values())
.filter(evaluator -> evaluator.evaluate(condition))
.findFirst().orElseThrow(() -> new RuntimeException("Instance type not found"));
}
}
如您所见,InstanceFactory不太容易被修改。这意味着,每次需要添加新实例实现时,只需修改InstanceType枚举。希望这对你有帮助 见:
活动概要文件由属性设置,并基于您分配给概要文件的值,Spring将为同一接口加载不同的bean。
因此,它可能正是您所需要的。请参阅:
活动概要文件由属性设置,并基于您分配给概要文件的值,Spring将为同一接口加载不同的bean。
所以它可能正是您所需要的。您可以使用spring现有的FactoryBean接口并实现您自己的逻辑 这是在spring框架中创建bean的最佳方法之一 以下是与示例的链接:
您可以使用spring现有的FactoryBean接口并实现您自己的逻辑 这是在spring框架中创建bean的最佳方法之一 以下是与示例的链接:
我觉得很好。虽然这可能取决于你的实际情况。这看起来像是一个问题,你知道FactoryBeans吗?或者根据情况,配置文件可能会有用。要有一个明确的答案,应该有更多的细节。谢谢@biziclop和Nathan Hughes。我会去看看工厂的。我觉得很好。虽然这可能取决于你的实际情况。这看起来像是一个问题,你知道FactoryBeans吗?或根据情况,选择mig
这可能有用。要有一个明确的答案,应该有更多的细节。谢谢@biziclop和Nathan Hughes。我将研究FactoryBean,它不建议使用@ConditionMissingBean不在spring boot自动配置库中。根据spring文档,建议使用@ConditionMissingBean。不管怎么说,没有人说过关于春靴的事。目前只有spring和@conditional具有自定义条件类。不建议使用@ConditionMissingBean不在spring引导自动配置库中。根据spring文档,建议使用etcIt。不管怎么说,没有人说过关于春靴的事。目前,只有spring和@conditional具有自定义条件类。