単純なケースを見てみましょう。
@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("发送邮件"); } }
上記のコードを実行して効果を観察してください
次のコードと組み合わせます。出力結果、このコードに実装されるロジックは、本業の業務が完了した後、テキスト メッセージや電子メールの送信などの操作を実行する必要があるというものです。このように書くことに問題はありませんが、十分エレガントではありません。その後のビジネスのスケーラビリティの点では十分ではありません。後続の本業のビジネスが完了し、別の監査操作を追加する必要がある場合は、本業のビジネスとブランチ ロジックを緊密に結合する新しいコード ロジックを追加する必要があります。
つまり、私たちは期待しています。その結果、本業のビジネスは他のビジネス操作をまったく気にせず、独自のロジックを完成させるだけで済みます。そのためにはイベント リスナー機能の使用が必要です。 spring によって提供される;
イベント リスナーの変換プロセスを使用する
springboot (spring) でイベント リスナーを使用するには、主に 2 つの方法があります。1 つは ApplicationListener インターフェイスを実装する方法で、もう 1 つは ApplicationListener インターフェイスを追加する方法です。 @EventListener アノテーションをクラスに追加します 次に、これら 2 つのメソッドを 1 つずつ説明します;
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 发邮件业务"); } } }
上記のコードをもう一度実行して、その効果を観察してください。期待される効果をまだ満たしていることがわかります
2. @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 发邮件业务"); } } }
のすぐ下に掲載されています。上記のコードを実行して効果を観察すると、期待どおりの効果が得られます
3。非同期を使用する
ソース コードを見ると、ApplicationEventPublisher はデフォルトでイベントを発行するときに単一のスレッドを使用して同期送信することがわかります。非同期を使用する必要がある場合は、ThreadPoolTaskExecutor と 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イベントリスナーの使用方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。