Event subscribers and listeners, the short version

In drupal 8 we have cool new thing, instead of hooks we can use event subscribers and create event listeners. They do similar things as hooks, we can do something on certain "events" in system, get data and change it or somehow act upon it.

So to subscribe to some event we need to do a service with tags in it, like

services:
  events_example_subscriber:
    class: Drupal\events_example\EventSubscriber\EventsExampleSubscriber
    tags:
      - {name: event_subscriber}

key here is that we add tag name: event_subscriber so drupal will know this service is event subscriber. Then in this service we make new class that implements EventSubscriberInterface

class EventsExampleSubscriber implements EventSubscriberInterface {

which then requires getSubscribedEvents method where we define what events to listen to and which methods to run on those events. For example

$events['kernel.request'][] = array('notifySomeone');

will react on kernel.request event. So we will just add this method notifySomeone below in this same class and pass event object 

public function notifySomeone( $event ) {

This is it in short.

Now for the other part, how are events dispatched?

If it is a new event, we will need to add some constants in some classes and extend Event class,

class NewEvent extends Event {

but this will not be covered here. Lets just jump to how to dispatch an event. Lets use some example from smart IP module and event dispatching that is added when we have build a form method
.....

    $event = \Drupal::service('smart_ip.admin_settings_event');
    // Allow Smart IP source module to add their form elements
    $event->setForm($form);
    $event->setFormState($form_state);
    \Drupal::service('event_dispatcher')->dispatch(SmartIpEvents::DISPLAY_SETTINGS, $event);

    $form = $event->getForm();
    $form_state = $event->getFormState();

so we define and event from service, pass it some arguments and then dispatch an event as seen on last line. So other modules can change this $event variable and basically change $form and $form_state. As you can see right after this dispatching we retrieve $form and $form_state so we have final versions of them. This is all called in form building so we dont have dependency injections used. How we would do this inside a class that uses dependency injection would be like this, we would need to import (among other things) our event we want to act upon and EventDispatcherInterface

use Drupal\commerce_tax\Event\CustomerProfileEvent;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;

and then we would use standard dependency injection for EventDispatcher for the class were we are going to do event dispatching and all the other things needed. Lets just go straight to the point where we dispatch event and act on it.

  protected function resolveCustomerProfile(OrderItemInterface $order_item) {
    $order = $order_item->getOrder();
    $customer_profile = $order->getBillingProfile();
    // A shipping profile is preferred, when available.
    $event = new CustomerProfileEvent($customer_profile, $order_item);
    $this->eventDispatcher->dispatch(TaxEvents::CUSTOMER_PROFILE, $event);
    $customer_profile = $event->getCustomerProfile();
we create NEW event object and pass it to dispatcher, after that we get the changes that were made by subscribers to that event
This example was taken from TaxTypeBase class used in commerce.

So this is it, this is how it works.