One, foreword
Yesterday I wrote my first article on the basics of Netty, and for those of you who have read this article, I wrote this ** placeholder ** when I wrote about event-driven
Today, I took advantage of working overtime to quietly learn event-driven content. As I am engaged in finance, I am very busy every day. Only in the evening can I spare a little time for study.
What is event driven?
Baidu’s explanation
The basic structure of an event driver consists of an event collector, an event sender and an event handler. The event collector is dedicated to collecting all events from the user (such as mouse, keyboard events, etc.), from hardware (such as clock events, etc.), and from software (such as the operating system, the application itself, etc.). The event sender is responsible for distributing the events collected by the collector to the target object. Event handlers do the specific event response work
According to Baidu’s explanation, I think the event driving is mainly divided into the following contents:
- Event source: An object responsible for generating events, such as a Button. Clicking on a Button causes the event to be clicked
- Event collectors, or event objects, are the information Bridges between event sources and event listeners and are the driving core of the entire event model
- Event listener (event handler) : The object responsible for handling events
Here’s an example: since I started in finance, I’ll use banks as an example
- Event collector: calling machine
- Event source: caller
- Event listener: customer
Morning after morning session open and customer came to your turn device take number, and event listener is registered to the event) in the collector, teller machine (events), click on your cueing machine began to call * * “please customers to 5, 001 counter business” * *, at this time of the teller and customer for binding (i.e., event sources and event listeners binding)
3. Simple examples
Implementation approach
- First, you need to implement the event listener, the event collector, and register the event listener with the event collector
- The event sender sends an event to the event center, which finds and processes the listener for the event
Event sender -----(2)-----> Event collector <--------(1)----- Event listenerCopy the code
3.1 Implementing the event collector
explain
- 1.ConcurrentHashMap is used to store the binding relationship between the event source and the event listener
private finalConcurrentHashMap<Class<? >, List<EventListener>> subscribers =new ConcurrentHashMap<>();
Copy the code
The first argument is the Class object of the data source, and the second is the listener
- 2.Executor
Flexible and powerful asynchronous execution framework, which supports a variety of different types of task execution strategy, provides a standard method of decoupling tasks submission process and execution process development, based on producers - consumer model, its submit task thread is equivalent to producers, perform a task thread is equivalent to the consumer, and represented a Runnable task,Copy the code
- 3.EventCenter
Constructor to instantiate an Executor object
public EventCenter(Executor executor) {
this.executor = executor;
}
Copy the code
- 4.registry
The first parameter is the Class object of the event source, and the second is the object of the listener
/** * Bind the event to the event listener@param clazz
* @param eventListener
*/
public void registry(Class clazz,EventListener eventListener){
// Run the ConcurrentHashMap command to check whether the listener is registered
List<EventListener> eventListeners = subscribers.get(clazz);
// If the listener is not registered, initialize the List
if(eventListener == null){
eventListeners = new ArrayList<>();
}
// Add listeners to the List
eventListeners.add(eventListener);
// Event and event listener binding
subscribers.put(clazz,eventListeners);
}
Copy the code
- 5.send
It is used for publishing events, where BanderEvent requires a custom implementation, which we will explain later
/** * Event send *@param bankerEvent
*/
public void send(BankerEvent bankerEvent) throws EventException {
// Check whether the listener is registered
List<EventListener> eventListeners = subscribers.get(bankerEvent.getClass());
if(eventListeners == null || eventListeners.size() == 0) {// Throw an exception if it is not registered
throw new EventException((short) 500."Event listener not registered");
}
// Loop through the listener and publish the event
for(EventListener eventListener : eventListeners){ executor.execute(()->eventListener.trigger(bankerEvent)); }}Copy the code
Complete structure
** * Event collector/Registry */public class EventCenter {
/** * is used to bind events to event listeners */
private finalConcurrentHashMap<Class<? >, List<EventListener>> subscribers =new ConcurrentHashMap<>();
// Task processing
private final Executor executor;
public EventCenter(Executor executor) {
this.executor = executor;
}
/** * Bind the event to the event listener@param clazz
* @param eventListener
*/
public void registry(Class clazz,EventListener eventListener){
// Run the ConcurrentHashMap command to check whether the listener is registered
List<EventListener> eventListeners = subscribers.get(clazz);
// If the listener is not registered, initialize the List
if(eventListener == null){
eventListeners = new ArrayList<>();
}
// Add listeners to the List
eventListeners.add(eventListener);
// Event and event listener binding
subscribers.put(clazz,eventListeners);
}
/** * Event send *@param bankerEvent
*/
public void send(BankerEvent bankerEvent) throws EventException {
// Check whether the listener is registered
List<EventListener> eventListeners = subscribers.get(bankerEvent.getClass());
if(eventListeners == null || eventListeners.size() == 0) {// Throw an exception if it is not registered
throw new EventException((short) 500."Event listener not registered");
}
// Loop through the listener and publish the event
for(EventListener eventListener : eventListeners){ executor.execute(()->eventListener.trigger(bankerEvent)); }}}Copy the code
3.2 Implementing event listeners
explain
- ConsumerListener mainly implements the EventListener interface
- 2. The trigger method is called when the event is triggered
/** * Response to event trigger *@param bankerEvent
*/
@Override
public void trigger(BankerEvent bankerEvent) {
Integer number = bankerEvent.getNumber();
log.info("Please go to window 5 for customer {}",number);
}
Copy the code
- 3. The Registry method is used to register and bind events and event listeners to the registry
@Autowired
private EventCenter eventCenter;
/** * Registering with the event collection center is also equivalent to identifying events to be subscribed to */
@PostConstruct
public void registry(a){
eventCenter.registry(BankerCreateEvent.class,this);
}
Copy the code
To define an event listener, we first need to define an interface
/** * Event listener interface */
public interface EventListener {
* is called when the event is triggered@param bankerEvent
*/
public void trigger(BankerEvent bankerEvent);
}
Copy the code
Specific operation
Implement the class and register with EvnetCenter
/** * Client listener */
@Component
@Slf4j
public class ConsumerListener implements EventListener {
@Autowired
private EventCenter eventCenter;
/** * Registering with the event collection center is also equivalent to identifying events to be subscribed to */
@PostConstruct
public void registry(a){
eventCenter.registry(BankerCreateEvent.class,this);
}
/** * Response to event trigger *@param bankerEvent
*/
@Override
public void trigger(BankerEvent bankerEvent) {
Integer number = bankerEvent.getNumber();
log.info("Please go to window 5 for customer {}",number); }}Copy the code
3.3 Implementing the event source
Create the interface
/** * Teller incident */
public interface BankerEvent {
public Integer getNumber(a);
}
Copy the code
The implementation class
public class BankerCreateEvent implements BankerEvent {
Integer number = 100;
@Override
public Integer getNumber(a) {
returnnumber; }}Copy the code
3.4 Implement event publishers
@Component
public class EventSender {
@Autowired
private EventCenter eventCenter;
public void send(BankerEvent bankerEvent){
// Send the eventeventCenter.send(bankerEvent); }}Copy the code
3.5 Event Registry configuration class
@Configuration
public class EventCenterConfig {
@Bean
public EventCenter eventCenter(a){
ThreadFactory namedThreadFactory = Executors.defaultThreadFactory();
int corePoolSize = Runtime.getRuntime().availableProcessors();
int maximumPoolSize = corePoolSize * 2;
Create a thread pool
Executor pool = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, 10L,
TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(1024),
namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());
return newEventCenter(pool); }}Copy the code
3.6 Event Invocation
@Slf4j
@SpringBootApplication
public class LinkedApplication {
public static void main(String[] args) throws InterruptedException {
ApplicationContext applicationContext = SpringApplication.run(LinkedApplication.class, args);
// Get the EventSender context
EventSender eventSender = applicationContext.getBean(EventSender.class);
while(true) {long orderId = ThreadLocalRandom.current().nextLong();
// Send the event
eventSender.send(new BankerCreateEvent());
Thread.sleep(ThreadLocalRandom.current().nextLong(1000.10000)); }}}Copy the code
The 2020-12-24 00:55:22. 5315-335 the INFO [] – thread pool – 1-1 C.Y.L inked. Listener. ConsumerListener: please customers at counter number 5, 100
Making the address
Github.com/13150702172…
Let’s call it a day. Because I have to go back to work tomorrow. Good night! 🌛