Springbootイベントリスナーの使用方法

PHPz
リリース: 2023-05-14 10:01:20
転載
905 人が閲覧しました

ガイダンス ケース

単純なケースを見てみましょう。

@Configuration
public class SelfBusiness {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SelfBusiness.class);
        context.getBean(MyService.class).doBusiness();
        context.close();
    }
    @Component
    static class MyService {
        private static final Logger logger = LoggerFactory.getLogger(MyService.class);
        @Autowired
        private ApplicationEventPublisher publisher;
        public void doBusiness (){
            logger.debug("主线业务");
            logger.debug("发送短信");
            logger.debug("发送邮件");
        }
    }
ログイン後にコピー

上記のコードを実行して効果を観察してください

Springbootイベントリスナーの使用方法

次のコードと組み合わせます。出力結果、このコードに実装されるロジックは、本業の業務が完了した後、テキスト メッセージや電子メールの送信などの操作を実行する必要があるというものです。このように書くことに問題はありませんが、十分エレガントではありません。その後のビジネスのスケーラビリティの点では十分ではありません。後続の本業のビジネスが完了し、別の監査操作を追加する必要がある場合は、本業のビジネスとブランチ ロジックを緊密に結合する新しいコード ロジックを追加する必要があります。

つまり、私たちは期待しています。その結果、本業のビジネスは他のビジネス操作をまったく気にせず、独自のロジックを完成させるだけで済みます。そのためにはイベント リスナー機能の使用が必要です。 spring によって提供される;

イベント リスナーの変換プロセスを使用する

springboot (spring) でイベント リスナーを使用するには、主に 2 つの方法があります。1 つは ApplicationListener インターフェイスを実装する方法で、もう 1 つは ApplicationListener インターフェイスを追加する方法です。 @EventListener アノテーションをクラスに追加します 次に、これら 2 つのメソッドを 1 つずつ説明します;

1. ApplicationListener インターフェイスを実装して手順を実装します

##1. イベント クラス (オブジェクト) をカスタマイズしますApplicationEvent

 static class MyEvent extends ApplicationEvent {
        public MyEvent(Object source) {
            super(source);
        }
    }
ログイン後にコピー

コードでは、このように理解できます。イベントには多くの種類があり、異なるビジネスが異なるイベントに対応します。特定のリスナーについては、リッスンすることだけを望んでいます。タイプ A のイベントへ;

2. ApplicationListener インターフェイスを実装するビジネス クラスを定義します

  
	@Data
    static class Params {
        private String id ;
        private String name;
        private String phone;
    }
	@Component
    static class SmsApplicationListener implements ApplicationListener<MyEvent> {
        private static final Logger logger = LoggerFactory.getLogger(SmsApplicationListener.class);
        @Override
        public void onApplicationEvent(MyEvent myEvent) {
            Object source = myEvent.getSource();
            try {
                Params params = objectMapper.readValue(source.toString(), Params.class);
                logger.debug("userId : {}",params.getId());
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
            logger.debug("执行 sms 发短信业务");
        }
    }
    @Component
    static class EmailApplicationListener implements ApplicationListener<MyEvent> {
        private static final Logger logger = LoggerFactory.getLogger(SmsApplicationListener.class);
        @Override
        public void onApplicationEvent(MyEvent myEvent) {
            Object source = myEvent.getSource();
            logger.debug("执行 email 发邮件业务");
        }
    }
ログイン後にコピー

明らかに、ここでのリスナーがリッスンしたいイベント タイプは次のとおりです。まさに上で定義した MyEvent なので、ビジネスがトリガーされたときに onApplicationEvent で使用できます 渡されたパラメーターを取得し、テキスト メッセージ (電子メール) ビジネス オペレーションを実行します

3. メインライン ビジネス パブリッシング イベント

@Component
    static class MyService {
        private static final Logger logger = LoggerFactory.getLogger(MyService.class);
        @Autowired
        private ApplicationEventPublisher publisher;
        public void doBusiness (){
            Params params = new Params();
            params.setId("001");
            params.setName("xiaoma");
            params.setPhone("133******");
            logger.debug("主线业务");
            try {
                publisher.publishEvent(new MyEvent(objectMapper.writeValueAsString(params)));
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
            //publisher.publishEvent(new MyEvent("MyService doBusiness()"));
            //logger.debug("发送短信");
            //logger.debug("发送邮件");
        }
    }
ログイン後にコピー

メインライン ビジネスの場合は、これでテキスト メッセージや電子メールを送信するためのロジックを作成する必要がなくなります。パブリッシャーのみがイベントを公開する必要があります。パラメーターを渡す必要がある場合は、パラメーターを渡します。一緒に

#完全なコード
@Configuration
public class SelfBusiness {
    private static ObjectMapper objectMapper = new ObjectMapper();
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SelfBusiness.class);
        context.getBean(MyService.class).doBusiness();
        context.close();
    }
    @Data
    static class Params {
        private String id ;
        private String name;
        private String phone;
    }
    /**
     * 自定义事件对象
     */
    static class MyEvent extends ApplicationEvent {
        public MyEvent(Object source) {
            super(source);
        }
    }
    @Component
    static class MyService {
        private static final Logger logger = LoggerFactory.getLogger(MyService.class);
        @Autowired
        private ApplicationEventPublisher publisher;
        public void doBusiness (){
            Params params = new Params();
            params.setId("001");
            params.setName("xiaoma");
            params.setPhone("133******");
            logger.debug("主线业务");
            try {
                publisher.publishEvent(new MyEvent(objectMapper.writeValueAsString(params)));
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
            //publisher.publishEvent(new MyEvent("MyService doBusiness()"));
            //logger.debug("发送短信");
            //logger.debug("发送邮件");
        }
    }
    /**
     * 监听事件触发后要执行的业务
     */
    @Component
    static class SmsApplicationListener implements ApplicationListener {
        private static final Logger logger = LoggerFactory.getLogger(SmsApplicationListener.class);
        @Override
        public void onApplicationEvent(MyEvent myEvent) {
            Object source = myEvent.getSource();
            try {
                Params params = objectMapper.readValue(source.toString(), Params.class);
                logger.debug("userId : {}",params.getId());
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
            logger.debug("执行 sms 发短信业务");
        }
    }
    @Component
    static class EmailApplicationListener implements ApplicationListener {
        private static final Logger logger = LoggerFactory.getLogger(SmsApplicationListener.class);
        @Override
        public void onApplicationEvent(MyEvent myEvent) {
            Object source = myEvent.getSource();
            logger.debug("执行 email 发邮件业务");
        }
    }
}
ログイン後にコピー

上記のコードをもう一度実行して、その効果を観察してください。期待される効果をまだ満たしていることがわかります

Springbootイベントリスナーの使用方法2. @EventListener アノテーションを追加してこれを実現します

このメソッドは ApplicationListener インターフェイスを実装する必要がなくなり、@EventListener アノテーションをリスニング クラスのメソッドに直接追加するだけです。完全なコードは

package com.congge.config;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@Configuration
public class SelfBusiness2 {
    private static ObjectMapper objectMapper = new ObjectMapper();
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SelfBusiness2.class);
        context.getBean(MyService.class).doBusiness();
        context.close();
    }
    @Data
    static class Params {
        private String id ;
        private String name;
        private String phone;
    }
    /**
     * 自定义事件对象
     */
    static class MyEvent extends ApplicationEvent {
        public MyEvent(Object source) {
            super(source);
        }
    }
    @Component
    static class MyService {
        private static final Logger logger = LoggerFactory.getLogger(MyService.class);
        @Autowired
        private ApplicationEventPublisher publisher;
        public void doBusiness (){
            Params params = new Params();
            params.setId("001");
            params.setName("xiaoma");
            params.setPhone("133******");
            logger.debug("主线业务");
            try {
                publisher.publishEvent(new MyEvent(objectMapper.writeValueAsString(params)));
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
        }
    }
    @Component
    static class SmsListenerService {
        private static final Logger logger = LoggerFactory.getLogger(SmsListenerService.class);
        @EventListener
        public void smsListener(MyEvent myEvent){
            Object source = myEvent.getSource();
            try {
                SelfBusiness2.Params params = objectMapper.readValue(source.toString(), SelfBusiness2.Params.class);
                logger.debug("userId : {}",params.getId());
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
            logger.debug("执行 sms 发短信业务");
        }
    }
    @Component
    static class EmailListenerService {
        private static final Logger logger = LoggerFactory.getLogger(EmailListenerService.class);
        @EventListener
        public void emailListener(MyEvent myEvent){
            Object source = myEvent.getSource();
            try {
                SelfBusiness2.Params params = objectMapper.readValue(source.toString(), SelfBusiness2.Params.class);
                logger.debug("userId : {}",params.getId());
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
            logger.debug("执行 email 发邮件业务");
        }
    }
}
ログイン後にコピー

のすぐ下に掲載されています。上記のコードを実行して効果を観察すると、期待どおりの効果が得られます

Springbootイベントリスナーの使用方法3。非同期を使用する

さらに、本業のロジック実行効率を高めるために、イベント発行のビジネスロジックを非同期で実行したいのですが、どうすればよいでしょうか?

ソース コードを見ると、ApplicationEventPublisher はデフォルトでイベントを発行するときに単一のスレッドを使用して同期送信することがわかります。非同期を使用する必要がある場合は、ThreadPoolTask​​Executor と SimpleApplicationEventMulticaster をカスタマイズする必要があるため、これら 2 つの Bean を上書きするだけで済みます。コンポーネントを作成し、次の 2 つの Bean を上記のビジネス クラスに追加します。

@Bean
    public ThreadPoolTaskExecutor executor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(100);
        return executor;
    }
    @Bean
    public SimpleApplicationEventMulticaster applicationEventMulticaster(ThreadPoolTaskExecutor executor) {
        SimpleApplicationEventMulticaster eventMulticaster = new SimpleApplicationEventMulticaster();
        eventMulticaster.setTaskExecutor(executor);
        return eventMulticaster;
    }
ログイン後にコピー

この時点でコードを再度実行し、複数回実行すると、効果がわかります

#上記のシングルスレッド効果を比較してくださいSpringbootイベントリスナーの使用方法

##

以上がSpringbootイベントリスナーの使用方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:yisu.com
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート