How It Works?

The approach is very straight forward. There is a static hash map with keys
as "method coordinates" and values as their results. Method coordinates consist
of the object, an owner of the method and a method name with parameter types.

In the example above, right after the method load()
finishes, the map gets a new entry (simplified example, of course):

key: [page, "load()"]
value: "<html>...</html>"

Every consecutive call to load() will be intercepted by the aspect
from jcabi-aspects and resolved immediately
with a value from the cache map. The method will not get any control until
the end of its lifetime, which is five minutes in the example above.

What About Cache Flushing?

Sometimes it's necessary to have the ability to flush cache before
the end of its lifetime. Here is a practical example:

It's obvious that the number of employees in the database
will be different after add() method execution and the
result of size() should be invalidated in cache. This invalidation
operation is called "flushing" and @Cacheable.FlushBefore triggers it.

Actually, every call to add() invalidates all cached methods
in this class, not only size().

There is also @Cacheable.FlushAfter. The difference is that
FlushBefore guarantees that cache is already invalidated
when the method add() starts.
FlushAfter invalidates cache after method add() finishes. This small difference makes a big one, sometimes.