Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 我们可以有一个工厂类作为Springbean,并有一个工厂方法根据条件返回多个Springbean吗?_Java_Spring_Design Patterns_Factory - Fatal编程技术网

Java 我们可以有一个工厂类作为Springbean,并有一个工厂方法根据条件返回多个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

我想根据factory类中的条件返回多个Springbean

这是一种好的做法吗

有没有更好的方法来编写下面的代码?。 还有其他适合这里的设计模式吗

下面是代码片段:

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具有自定义条件类。