Observer pattern with spring guava events

1. Observer Pattern

Observer mode, also known as Publish/Subscribe mode, observer mode is relatively simple, but very commonly used, of course, very practical.

The biggest benefit of the observer pattern is that when the business logic becomes complicated, the coupling can be alleviated by the observer pattern.

To give a simple example, a simple user recharge event, when the business is complicated, in addition to processing orders, you may also need to send coupons, reward points and gold coins, prompt VIP levels, send lottery and other incentive activities, process invitation codes, and send important activities. Event logging, handling of important event exception operations, etc.

If these logics are placed in the process of "user recharge", then the logical coupling will explode. So, generally don't do that.

If the user scale is large and the service is split, then the message system is used, which is essentially the observer mode.

Observer pattern components like guava's EventBus come in handy if service splitting is not done.

components illustrate
Subject Abstract subject, observed, usually events, such as user recharge, configuration change, VIP level upgrade and other events
ConcreteSubject It mainly provides an interface for observer registration, cancellation, and callback to registered observers when an event is sent
Observer abstract observer
ConcreteObserver Specific observer, the specific logic to be executed after a specific event, such as user recharge, is sent

2. Guava EventBus

First, you can define some custom events, such as user recharge:

import vip.mycollege.tool.guava.bean.ChargeBean;
import vip.mycollege.tool.guava.bean.UserBean;

import java.io.Serializable;

public class ChargeEvent implements Serializable{

    private static final long serialVersionUID = -8775590840527884827L;

    private UserBean user;

    private ChargeBean charge;

    public UserBean getUser() {
        return user;
    }

    public void setUser(UserBean user) {
        this.user = user;
    }

    public ChargeBean getCharge() {
        return charge;
    }

    public void setCharge(ChargeBean charge) {
        this.charge = charge;
    }
}

Then, add the observer, that is, the logic that needs to be executed when the event occurs:

import com.google.common.eventbus.Subscribe;
import vip.mycollege.tool.guava.event.ChargeEvent;

import java.util.concurrent.TimeUnit;

public class CommonListener {

    @Subscribe
    public void dealChargeGold(ChargeEvent event){
        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("处理gold");
    }

    @Subscribe
    public void dealChargeLevel(ChargeEvent event){
        System.out.println("处理level");
    }
}

The observer in guava is very simple. It does not need to implement any interface. It only needs to add the @Subscribe method annotation. The parameter of the method is the specific event to be observed.

Next, a Subject is needed, which is also very simple in guava:

import com.google.common.eventbus.AsyncEventBus;
import com.google.common.eventbus.EventBus;
import vip.mycollege.tool.guava.event.ChargeEvent;
import vip.mycollege.tool.guava.listener.CommonListener;

import java.util.concurrent.Executors;

public class EventBusStart {
    public static void main(String[] args) {
        EventBus eventBus = new EventBus();
        eventBus.register(new CommonListener());
        eventBus.post(new ChargeEvent());

        AsyncEventBus asyncEventBus = new AsyncEventBus(Executors.newCachedThreadPool());
        asyncEventBus.register(new CommonListener());
        asyncEventBus.post(new ChargeEvent());
        System.out.println("main");
    }
}

EventBus is a synchronous event, which uses a main thread to dispatch Events sequentially.

AsyncEventBus can specify a thread pool to dispatch Events asynchronously. When using AsyncEventBus, it should be noted that there should be no sequence constraints in business logic.

**register method: **Registration time, specifically to scan the @Subscribe annotation method in the parameter class.

**post method:** When a specific event occurs, it is triggered, and then EventBus goes to the callback register to observe the @Subscribe method of the event (the parameters are consistent with the event type).

3. Spring Event

In addition to guava, the Spring suite also provides an implementation of the observer pattern, important classes:

  1. ApplicationEvent: abstract event, concrete events can inherit this class
  2. ApplicationListener: Observer, you need to implement the onApplicationEvent method to handle specific event logic
  3. ApplicationEventPublisher: publish events, which are triggered when specific events occur

Or a simple example:

import org.springframework.context.ApplicationEvent;

public class LoginEvent extends ApplicationEvent {

    public LoginEvent(Object source) {
        super(source);
    }
}

Observer:

import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

import java.util.Map;

@Component
public class LoginEventListener implements ApplicationListener<LoginEvent> {

    @Override
    public void onApplicationEvent(LoginEvent event) {
       Map<String,String> map = (Map<String, String>) event.getSource();
        System.out.println(map.keySet());
        System.out.println(map.values());
    }
}

In addition to inheriting ApplicationListener, you also need to add annotations such as @Component, so that this class can be created through annotation scanning.

Event release:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;

import java.util.HashMap;

@Component
public class LoginLogic {

    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;

    public void login(){
        HashMap<String, String> params = new HashMap<>();
        params.put("name","tim");
        params.put("age","25");
        LoginEvent loginEvent = new LoginEvent(params);
        applicationEventPublisher.publishEvent(loginEvent);
    }

}

When Spring starts, it will automatically create an ApplicationEventPublisher, so we can inject it directly.

When a specific event occurs, it is good to trigger the corresponding event directly through the ApplicationEventPublisher, and you only need to simply encapsulate the event parameters.

Spring's observer mode is slightly more complicated than guava's. If you only need observer mode, it is recommended to use guava. If you have already used Spring and need observer mode, you can consider using Spring's own observer mode implementation.

{{o.name}}
{{m.name}}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324133419&siteId=291194637