There are multiple ways to handle events at different levels in CQ. In this post, I'd show you some sample code that starts a corresponding job based on an event (e.g. the action type of the ReplicationAction event) triggered at the Sling level.
To put the above into context, let's assume we have a 'custom CQ workflow process step' (a.k.a. automated step) - PostPageActivationWorkFlow.java - developed already. The customer step is normally part of some workflow. This custom process step was designed so that it will 'replicate' the payload (the entity upon which a workflow instance acts) to a hypothetical remote place via HTTP POST. To run and trigger this custom process step (which in terms will execute PostPageActivationWorkFlow.replicate() method that I named and implemented), you normally create a workflow by dropping this custom process step into it. When the workflow runs into this step, its execute() will be executed. However, instead of triggering the process step from the workflow, what if we also want such 'replication' to be triggered by an CQ event (specifically, by the action type of the ReplicationAction event)? The following code sample will show you how.
First, let's take a quick look at the custom workflow process step - PostPageActivationWorkFlow.java. I'm not going into details about how to code a custom workflow process step. This custom workflow process step was implemented according to an article titled Extending Workflow Functionality if you're interested to know. But the only thing I'd point out is that the class is registered as an OSGi service, and it is a method that we named it replicate() we want to start based on a triggered event. As you'll see later, it will be called by a job processor's process() to process a job in the background.
 When the workflow runs into this step, its execute() will be executed.
Below is the actual hook to the event so that when the even happens, the event job will be processed (put to a queue to be executed) as soon as the resource is available. The combination of event, job, and queue assure the job is guaranteed to be processed and won't be lost in the oblivion after an event was triggered.
At Sling level, the hook to events is done by:
 Register event handler to listen to replication actions. handleEvent(Event) will be called each time the a replication action is applied to a payload. A replication action can be of different types - activate, deactivate, reverse, delete. For the same effect, the following code inside the class may (not tested) serve the same purpose instead.
 You must implements EventHandler interface to hook an handler to an event.
 You must implements JobProcessor interface for the parameter class to be passed to EventUtil.processJob(Event, JobProcessor).
 Inject a registered OSGi service by class name using Felix SCR annotation.
 Implicitly called when the registered event happens. This event listener handles event by calling into EventUtil.processJob(Event, JobProcessor) which will in terms calls into JobProcessor.process().
 Start processing a job (calls JobProcessor.process()) in the background.
 A job processor's process() processes a job in the background is called by EventUtil.processJob(event, this)
 Get an OSGi bundle context to be used toward getting a reference to a specific OSGi service in the context.
 A special syntax of filter to be used toward located a specific OSGi service registered under the WorkFlowProcess interface.
 Get the reference to a list of registered OSGi service(s) using Interface class and a filter string.
 Get the reference to the registered OSGi service (the first one).
 Do different thing based on the replication action types - activate, deactivate, delete, reverse.
 full path (jcr:content excluded) of the content node the action applied to.
 The core of the job.