简体   繁体   English

如何让用户决定在Spring中用于接口的实现?

[英]How to let user to decide which implementation to use for interface in Spring?

I'm developing an SDK, which will be used to create additional applications for batch processing. 我正在开发一个SDK,该SDK将用于创建用于批处理的其他应用程序。 There is core-a-api module, which holds interface Client core-a-api模块,其中包含接口Client

public interface Client {
    void send();

} }

and core-a-impl which holds couple implementations for Client interface - HttpClient and TcpClient . 还有core-a-impl ,它包含客户端接口HttpClientTcpClient的几个实现。
Also, there is one more core module core-b-impl , which uses a particular instance of Client interface. 另外,还有一个核心模块core-b-impl ,它使用Client接口的特定实例。

public class SendingTasklet implements Tasklet {
    @Autowired
    private Client client

    public void process() {
        client.send();
    } 

} }
What instance should be created ( HttpClient or SftpClient ) should be decided by the user, who creates an application using SDK. 应该创建哪个实例( HttpClientSftpClient )应该由用户决定,该用户使用SDK创建应用程序。 He also needs to have an ability to create its own implementation for Client and use it in SendingTasklet . 他还需要具有为Client创建自己的实现并在SendingTasklet中使用它的能力 A user from core dependencies can see only interfaces from -api modules. 具有核心依赖性的用户只能看到-api模块的接口。 For dependency injection, I'm using Spring. 对于依赖项注入,我使用的是Spring。 All beans for particular modules are created in each module separately. 特定模块的所有bean分别在每个模块中创建。 The user created beans are created in user's configuration class 用户创建的bean是在用户的配置类中创建的

@Configuration
public class UsersApplicationConf {

    @Bean
    public Client client {
        return new UsersClient();
    } 

} }

The issue is, that somehow without exposing -impl module details for user application, he should be able to decide what Client implementation can be used from the core provided implementations or he should be able to pass one of its own. 问题是,在某种程度上不公开用户应用程序的-impl模块详细信息,他应该能够从提供的实现中决定可以使用哪种Client实现,或者他应该能够传递自己的实现。

The first thought was to use qualifiers when injecting into SendingTasklet , but then you need to create a separate instance variable for each implementation in SendingTasklet and this is not very good because if there would be more implementations for Client interface it would be required to change SendingTasklet as well. 首先想到的是在注入SendingTasklet时使用限定符,但随后您需要为SendingTasklet中的每个实现创建一个单独的实例变量,这不是很好,因为如果Client接口有更多实现,则需要更改SendingTasklet也一样 And also the problem, that user should somehow decide wich implementation to use persists. 还有一个问题,就是用户应该以某种方式决定要使用哪种实现仍然存在。

What I did, I exposed core-a-impl for client's application. 我所做的是,我为客户的应用程序提供了core-a-impl So in his configuration, he can decide what instance to create for Client interface. 因此,在他的配置中,他可以决定为Client接口创建哪个实例。

@Configuration
public class UsersApplicationConf {

    @Bean
    public Client client {
        return new HttpClient();
    } 

} }

But this is not very smart as well and I'm thinking is there any other way how to solve this issue? 但这也不是很聪明,我在想还有其他方法可以解决这个问题吗?

You can use strategy or factory pattern as mentioned here but personally I would go with JSR 330 that you can find an example here , below code block for spring example: 您可以使用此处提到的策略或工厂模式,但就我个人而言,我会使用JSR 330,您可以在此处的spring示例代码块下面找到一个示例:

package spring;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import static spring.Spring.Platform;

@Configuration
@ComponentScan
public class Spring {

    public static void main(String[] args) {
        new AnnotationConfigApplicationContext(Spring.class);
    }

    @Autowired
    @Platform(Platform.OperatingSystems.ANDROID)
    private MarketPlace android;

    @Autowired
    @Platform(Platform.OperatingSystems.IOS)
    private MarketPlace ios;

    @PostConstruct
    public void qualifyTheTweets() {
        System.out.println("ios:" + this.ios);
        System.out.println("android:" + this.android);
    }

    // the type has to be public!
    @Target({ElementType.FIELD,
            ElementType.METHOD,
            ElementType.TYPE,
            ElementType.PARAMETER})
    @Retention(RetentionPolicy.RUNTIME)
    @Qualifier
    public static @interface Platform {

        OperatingSystems value();

        public static enum OperatingSystems {
            IOS,
            ANDROID
        }
    }
}

interface MarketPlace {
}

@Component
@Platform(Platform.OperatingSystems.IOS)
class AppleMarketPlace implements MarketPlace {

    @Override
    public String toString() {
        return "apple";
    }
}

@Component
@Platform(Platform.OperatingSystems.ANDROID)
class GoogleMarketPlace implements MarketPlace {

    @Override
    public String toString() {
        return "android";
    }
}

Edit: I didnt test the code but I have used javax.inject.Qualifier with CDI if this code doesnt work let me know I will update with correct combination and imports 编辑:我没有测试代码,但我使用javax.inject.Qualifier与CDI如果此代码不起作用,请通知我,我将使用正确的组合和导入进行更新

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何决定应使用哪个物理接口RMI传输层? - How to decide which physical interface RMI Transport Layer should use? Spring Boot 是否可以使用接口作为控制器参数并让 spring 使用它的实现来实例化它? - Spring Boot Is it possible to use an interface as controller parameter and let spring use it's implementation to instantiate it? 如何在Spring中使用接口的动态实现? - How to use a dynamic implementation of an interface in Spring? 如何让用户确定按钮的特定颜色 - how to let the user decide a particular color for a button 如何让用户决定按钮的字体? - How to let the user decide a font for a button? Spring,如何决定客户端应该使用哪个消费者服务? - Spring, how to decide on client which consumer should service use? 在 Java 中,如何让子类决定使用哪种类型的参数类作为重写的方法参数? - In Java, how to let child class decide of which type parameter class use as overridden method argument? Java如何知道要使用哪种接口实现? - How does Java know which implementation of an Interface to use? 如何让用户使用JComboBox决定出现的表的数量? - How to let the user decide the number of appearing tables using JComboBox? 如何决定在套接字通信中使用哪个端口 - How to decide which port to use in socket communcation
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM