すぐに春のネイティブ注釈を戦略パターン+工場モデルを実装する方法[ピュアドライ品は]

未定義

序文

復興の仕事をして、チームの周りのこの時間は、一部には、現在のコードベースを分離することであると論理的なビジネスの相互作用を、単一のマイクロサービス、職場での企業の相互作用ロジックの懸念を作るを引き抜きます。

その中で私が使用することは非常に自然な思い戦略パターン+工場モデル、アプローチを、内部パッケージの実装の詳細を呼び出すための統一的な方法を提供し、効果的に削減するif/elseビジネスコードをコード展開し、維持するために容易になり、。

いくつかの記事を読む前に、カスタム注釈+自動BeanProcessorの方法を使用することは、個人的な感情を少しトラブルを達成するために。オリジナルプランと同様の特徴ために生まれた春。

Benpianはすぐにポリシーモード+工場モードを実装するためにネイティブの春のアノテーションを使用して、春のIoC依存性注入を使用する方法を、実際のビジネスシナリオに紹介することを目指しています。私たちはあなたにインスピレーションを与えてきたと思っています。

ビジネスシーン

元のプロジェクトから、それは外部のビジネスの責任と対話すると仮定し、ビジネス・サービスから引き出さ。相互作用が同じ生成するが、インタラクティブな挙動の内部ロジックは、メッセージインタフェースを送るように、異なる達成するものの、異なる企業が、パケットフォーマットは、異なる企業が異なっていてもよいです。

別のインタラクティブなシーンの詳細、のうち企業の抽象的でインタラクティブな動作のために、この別の企業EntStrategyのインターフェイスは、以下に示すようにロジックを簡素化した後、サービスコンシューマの着信エンタープライズに応じて、対応する実装クラス(戦略)を選択します。

spring_ent_demo.png

高速な実装

今度は、高速で、これらのシーンを達成DEMOを使用してみましょう。

私たちの目標は、企業の数に応じて、我々はすぐにメッセージを送信するための操作を実行するには、対応する戦略の実装クラスを見つけることができます、期待しています。

ステップ1実装戦略クラス

APIは、私たちが今ようになっている外部サービスを提供するとし

/**
 * @param entNum 企业编号
 */
public void send(String entNum) {
	// 根据不同的企业编号,我们能够快速找到对应的策略实现类去执行发送报文的操作
}

复制代码

今度は、2つの定義してみましょうEntStrategyインタフェースを

/**
 * @author Richard_yyf
 * @version 1.0 2019/10/23
 */
public interface EntStrategy {

    String getStuff();

    void send();
}
复制代码

三つの戦略

DefaultStrategy

@Component
public class DefaultStrategy  implements EntStrategy {
    @Override
    public String getStuff() {
        return "其他企业";
    }

    @Override
    public void send() {
        System.out.println("发送默认标准的报文给对应企业");
    }

    @Override
    public String toString() {
        return getStuff();
    }
}
复制代码

EntAStrategy

@Component
public class EntAStrategy implements EntStrategy {
    @Override
    public String getStuff() {
        return "企业A";
    }

    @Override
    public void send() {
        System.out.println("发送A标准的报文给对应企业");
    }

    @Override
    public String toString() {
        return getStuff();
    }
}
复制代码

EntBStrategy

@Component
public class EntBStrategy implements EntStrategy {
    @Override
    public String getStuff() {
        return "企业B";
    }

    @Override
    public void send() {
        System.out.println("发送B标准的报文给对应企业");
    }

    @Override
    public String toString() {
        return getStuff();
    }
}
复制代码

強力な春の依存性注入とステップ2

以下は排除するように設計されif/else、ここで私が定義する、重要なコードをEntStrategyHolder工場出荷時のクラスとして来ます。

@Component
public class EntStrategyHolder {

    // 关键功能 Spring 会自动将 EntStrategy 接口的类注入到这个Map中
    @Autowired
    private Map<String, EntStrategy> entStrategyMap;

    public EntStrategy getBy(String entNum) {
        return entStrategyMap.get(entNum);
    }
}
复制代码

このステップでは、春は自動的になり、非常に重要であるEntStrategy実装クラスは、地図の中に注入されるインターフェイス。あなたはこの種を持っていることを提供することはSpringコンテナ管理を実現することです。

地図のキーの値は、あなたですbean idあなたが使用することができ、@Component("value")デフォルトの方法のように直接私の上、提供、そして、最初の文字を小文字です。値は、ポリシー実装クラスの対応する値と比較します。

image.png

この時点で、私たちは、実際に必要な機能は、大部分が達成されている、のは、単純なクラスの試みから始めましょう。

/**
 * @author Richard_yyf
 * @version 1.0 2019/10/23
 */
@Configuration
@ComponentScan("ric.study.demo.ioc.autowire_all_implementation_demo_set")
public class Boostrap {

    public static void main(String[] args) {
        String entNum = "entBStrategy";
        send(entNum);
        entNum = "defaultStrategy";
        send(entNum);
    }

    // 用这个方法模拟 企业代理服务 提供的Api
    public static void send(String entNum) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Boostrap.class);
        context.getBean(EntStrategyHolder.class).getBy(entNum).send();
    }
}
复制代码

出力

发送B标准的报文给对应企业
发送默认标准的报文给对应企业
复制代码

ステップ3エイリアス翻訳

私たちが目少しアジャイルポイントをする場合は、私は、企業数の内のクラスを開始しているものを見つけるでしょうentNum塗りつぶし実際にあるbean id値。確かにそうではない実際のビジネスでは、どのように同社はとても奇妙数がまだ定義できます。

だからここにも、一歩、入ってくる企業の数を必要とするクラスに対応する戦略にエスケープbean id

実際には、これはあなたの実際のビジネス・ロジックのステップとは強い相関があるためである私のビジネスであり、entNum特定し識別するために、どのようにプログラムを解析し、実際には特定の種類、対応する戦略の実装クラスを見つけ、それがあるべきあなたのビジネスのニーズに応じてカスタマイズされました。

私は主にあなたのアイデアを提供したい、この手順が書かれていませんここです。

私のサービスはSpringBootとマイクロ基地フレームを行うことですので、私はこのようにして達成特性SpringBoot外部のコンフィギュレーションの一部を使用します。

追加EntAliasカテゴリを

/**
 * @author Richard_yyf
 * @version 1.0 2019/10/15
 */
@Component
@EnableConfigurationProperties
@ConfigurationProperties(prefix = "ent")
public class EntAlias {

    private HashMap<String, String> aliasMap;
    
    public static final String DEFAULT_STATEGY_NAME = "defaultStrategy";

    public HashMap<String, String> getAliasMap() {
        return aliasMap;
    }

    public void setAliasMap(HashMap<String, String > aliasMap) {
        this.aliasMap = aliasMap;
    }

    String of(String entNum) {
        return aliasMap.get(entNum);
    }
}
复制代码

対応するプロファイルでapplication.ymlの設定:

ent:
  aliasMap:
    entA: entAStrategy
    entB: entBStrategy

....省略
复制代码

ここで対応を実現するために、ああ注意getterしてsetter、それ以外のプロパティは行っていない注入します。

再起草のEntStrategyHolderクラス

@Component
public class EntStrategyHolder {
    
    @Autowired
    private EntAlias entAlias;

    // 关键功能 Spring 会自动将 EntStrategy 接口的类注入到这个Map中
    @Autowired
    private Map<String, EntStrategy> entStrategyMap;

    // 找不到对应的策略类,使用默认的
    public EntStrategy getBy(String entNum) {
        String name = entAlias.of(entNum);
        if (name == null) {
            return entStrategyMap.get(EntAlias.DEFAULT_STATEGY_NAME);
        }
        EntStrategy entStrategy = entStrategyMap.get(name);
        if (entStrategy == null) {
            return entStrategyMap.get(EntAlias.DEFAULT_STATEGY_NAME);
        }
        return entStrategy;
    }
}
复制代码

今、私たちはそれを起動し、参照してください。

/**
 * @author Richard_yyf
 * @version 1.0 2019/10/23
 */
@Configuration
@ComponentScan("ric.study.demo.ioc.autowire_all_implementation_demo_set")
public class Boostrap {
    public static void main(String[] args) {
        String entNum = "entA";
        send(entNum);
        entNum = "entB";
        send(entNum);
        entNum = "entC";
        send(entNum);
    }
    
    public static void send(String entNum) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Boostrap.class);
        context.getBean(EntStrategyHolder.class).getBy(entNum).send();
    }
}
复制代码

出力

发送A标准的报文给对应企业
发送B标准的报文给对应企业
发送默认标准的报文给对应企业
复制代码

非SpringBoot

私は、変換コードがより美しく見えるようにすることです別名を管理するためにYMLファイルによってSpringBoot特性上記のコードを使用していました。それは、その後、Springフレームワークがある場合。私はこれを実現することがしたいと思います。(参考値)

/**
 * @author Richard_yyf
 * @version 1.0 2019/10/23
 */
public class EntAlias {

    private static Map<String, String> aliasMap;

    private static final String ENTA_STATEGY_NAME = "entAStrategy";
    private static final String ENTB_STATEGY_NAME = "entBStrategy";
    public static final String DEFAULT_STATEGY_NAME = "defaultStrategy";

    static {
        // 这个别名容器怎么注册别名、初始化,有很多种方式。
        aliasMap = new LinkedHashMap<>();
        aliasMap.put("entA", ENTA_STATEGY_NAME);
        aliasMap.put("entB", ENTB_STATEGY_NAME);
    }

    public static String of(String entNum) {
        return aliasMap.get(entNum);
    }
}
复制代码

春のIoC依存性注入

ここで私は前述の第2のステップについてお話したいと思い、第二段階のコアは、ポリシー実装クラスの登録プロセスを達成するために春のIoC依存性注入を介して行われ(このステップは、自分を達成するために多くの作業が必要になりますし、コードがしません)非常に素晴らしいです。

実際には、この変数の型の地図だけでなく、春には、自動的に変数をリストするために組み立てることができます。このような次のコードのように。

@Component
public class EntStrategyHolder {

    @Autowired
    private Map<String, EntStrategy> entStrategyMap;

    @Autowired
    private List<EntStrategy> entStrategyList;

    public EntStrategy getBy(String entNum) {
        return entStrategyMap.get(entNum);
    }

    public void print() {
        System.out.println("===== implementation Map =====");
        System.out.println(entStrategyMap);
        entStrategyMap.forEach((name, impl)-> {
            System.out.println(name + ":" + impl.getStuff());
        });
        System.out.println("===== implementation List =====");
        System.out.println(entStrategyList);
        entStrategyList.forEach(impl-> System.out.println(impl.getStuff()));
    }
}
复制代码

スタートアップクラス

@Configuration
@ComponentScan("ric.study.demo.ioc.autowire_all_implementation_demo_set")
public class Boostrap {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Boostrap.class);
        context.getBean(EntStrategyHolder.class).print();
    }
}
复制代码

出力

===== implementation Map =====
{defaultStrategy=其他企业, entAStrategy=企业A, entBStrategy=企业B}
defaultStrategy:其他企业
entAStrategy:企业A
entBStrategy:企业B
===== implementation List =====
[其他企业, 企业A, 企业B]
其他企业
企业A
企业B
复制代码

image.png

私たちは見ることができますentStrategyList割り当ての成功を。

しかし、私は、この機能のシナリオを見つけ、そのビットのために一人で来ていません。

エピローグ

ここでは、全体の実装プロセスが記載されています。

春は戦略の実装クラスの登録プロセスを達成するために、春のIoC依存性注入によって、最も一般的に使用されるノートを処理するために使用され、最終的に全体の機能。

あなたを刺激することを望んで。

あなたは春のIoCを超えている場合はまた、どのようにMapしてList変動持分譲渡、私が説明するために、次の関連するソースコードとデバッグのヒントの記事になります。

我々は、技術に従事するこれらの事がなぜ知っている必要があります知っています。

ブログ記事複数のプラットフォームからこの記事OpenWriteリリース!

おすすめ

転載: juejin.im/post/5db0e910518825648f2ef355