亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何根據應用程序參數注入依賴項?

如何根據應用程序參數注入依賴項?

呼啦一陣風 2021-12-30 19:46:33
我是 Spring 框架的新手。我開發了一個獨立的控制臺應用程序。應用程序將獲得多個不同格式(CSV、JSP、XML)的文件作為參數。我想根據文件格式注入解析器的某個實現。這是我的服務:@Servicepublic class ParsingService {private final Parser parser;@Autowiredpublic ParsingService(Parser parser) {    this.parser = parser;}public List<Order> parse(String filePath) {    try {        return parser.parse(filePath);    } catch (IOException e) {        e.printStackTrace();    }    return null;}}我的主要課程:public class Main {public static void main(String[] args) throws IOException {    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConf.class);    for (String arg : args) {        ParsingService service = context.getBean(ParsingService.class);        List<Order> listOfParsedObjects = service.parse(arg);        listOfParsedObjects.forEach(System.out::println);    }}}我將向命令行傳遞幾個文件路徑,我需要 Spring 根據文件格式注入必要的實現。
查看完整描述

3 回答

?
慕標琳琳

TA貢獻1830條經驗 獲得超9個贊

假設這Parser是你自己的接口,你可以添加一個方法來告訴它能夠解析的格式:


public interface Parser {

   List<Order> parse(String filePath);

   String getFormat();

}

然后在所有實現中覆蓋它:


@Component

public class CsvParser implements Parser {


    public static final String FORMAT = "csv";


    public String getFormat(){

        return FORMAT;

    }


    // ...

}

通過使用 @Bean/@Component 注釋類或在配置類中創建實例來配置解析器 bean。(如果您使用的是 SpringBoot,我建議您使用@ConditionalOn...注釋以避免創建不必要的 bean)


現在您可以將所有Parser實例注入到ParserService.


@Service

public class ParsingService {


    private final Map<String, Parser> parsers;


    @Autowired

    public ParsingService(List<Parser> allParsers) {

        this.parsers = allParsers

                           .stream()

                           .collect(Collectors.toMap(Parser::getFormat, p -> p));

    }


    public List<Order> parse(String filePath) {

        try {

            String format = getFormat(filePath);

            Parser parser = parsers.get(format);

            if(parser == null) {

                // Replace this exception by a more appropriate one

                throw new RuntimeException("No parsers found for format : " + format);

            } else {

                return parser.parse(filePath);

            }

        } catch (Exception e) {

            e.printStackTrace();

        }

        return null;

    }


    private String getFormat(String filePath){

        int i = filePath.lastIndexOf('.');

        if (i > 0) {

            return filePath.substring(i+1).toLowerCase();

        } else {

            // Replace this exception by a more appropriate one

            throw new RuntimeException("Cannot determine the file format!");

        }   

    }

}

這樣,您ParserService和Main類都不會依賴于您的自定義Parser實現。一旦你需要一個新的解析器,你可以簡單地定義一個實現接口的新類。不再需要更改。


更新


添加Main和AppConfig類


public class Main {


    public static void main(String[] args) {

        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConf.class);

        ParsingService service = context.getBean(ParsingService.class);


        for (String arg : args) {

            List<Order> listOfParsedObjects = service.parse(arg);

            listOfParsedObjects.forEach(System.out::println);

        }

    }

}


@Configuration

@ComponentScan(basePackages = "your.root.package")

public class AppConf {

    // Do something here

}

對于并行處理,請嘗試Main使用以下代碼替換您的 for 循環:


 Arrays.stream(args)

       .parallel()

       .map(service::parse)

       .flatMap(List::stream)

       .forEach(System.out::println);

或者您可以使用ExecutorService:


int poolSize = 3;

ExecutorService executorService =  new ThreadPoolExecutor(poolSize, poolSize, 0L, TimeUnit.MILLISECONDS,

            new LinkedBlockingQueue<Runnable>());


for (String arg : args) {

    executorService.submit(() -> {

        service.parse(arg).forEach(System.out::println);

    });

}


查看完整回答
反對 回復 2021-12-30
?
墨色風雨

TA貢獻1853條經驗 獲得超6個贊

您可能想要注入一組解析器


@Autowired

private List<Parser> parsers;

然后從該列表中選擇正確的解析器。此外,這可以通過 Map Spring Annotations - Injecting Map of Objects 來完成


您可以在解析器接口中定義方法,該方法返回擴展集合,如下所示


 public interface Parser {

    List<String> getExtensions();

}

然后你可以利用 Java 8 流來尋找正確的解析器:


parsers.stream().filter(p->p.getExtensions().contains(extension)).findFirst();

這將返回可能包含所需解析器的可選當您添加解析器時,您需要的是添加解析器并定義擴展。無需更改 main 中的代碼


查看完整回答
反對 回復 2021-12-30
?
牧羊人nacy

TA貢獻1862條經驗 獲得超7個贊

我的建議是考慮使用 Spring Boot 和@ConditionalOnProperty注釋。在下面的代碼示例中,只有csvParserImpl當 的屬性my.parser值為 時才會調用 bean csv。通過將屬性值從 更改csv為json,jsonParserImpl將創建而不是csvParserImpl。如果my.parser未定義或設置為既不包含csv也不包含 的值json,則不會有 的實例Parser。


@Configuration

public class MyAutoconfiguration {

  @Bean

  @ConditionalOnProperty(name="my.parser", havingValue="csv")

  CsvParserImpl csvParserImpl() {

    return new CsvParserImpl();

  }


  @Bean

  @ConditionalOnProperty(name="my.parser", havingValue="json")

  JsonParserImpl jsonParserImpl() {

    return new JsonParserImpl();

  }

}

當我提到“財產”時,它在 Spring Boot 中具有特定的含義。 Spring Boot 中的外部化配置可以從多個來源拉取屬性值,包括環境變量、系統變量和命令行變量。


查看完整回答
反對 回復 2021-12-30
  • 3 回答
  • 0 關注
  • 202 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號