In the previous posts (see [1], [2] and [3]) we have learned how to add metadata to classes and how to work with annotations. Now it’s time to talk about adding advices to the objects using these annotations.

Consider two different functions each defined within a separate class – the original code and the advice handling cross-cutting functionality. AOP allows you to execute both of them in one turn, for example the original code followed by the advice code. We have to connect both pieces of code or, in other words, we have to apply the aspect to the original class.

The process of applying aspects to a class is called weaving.


There are essentially two weaving strategies, Proxy-based and Class-based Weaving.

Proxy-based Weaving – Aspects are woven into objects by creating proxy classes which wrap the target classes. The original code and the advice code are stored in different classes. This weaving strategy uses the Proxy pattern.


Class-based Weaving – generates source for the target class before the class is loaded. It transforms the original code into a woven code which will be loaded by the classloader. The original code and the advice code are put together in one class.


Proxy-based Weaving

The most common approach is to create proxy classes. It is easy to implement because you only have to build a proxy class which wraps the target class and copies its method signatures.

As an example, consider the following class:

The proxy class would look like this:

As you see, there are few steps to create such a proxy:

  • create a class extending the target class
  • instantiate the target class
  • copy all (non-private) methods
  • call target object methods in each copied method, return the result

In this way, in MyTargetClassProxy::doSomething() we are able to execute advice code before and after the invocation of the target method of MyTargetClass.

However, the proxy-based weaving has some disadvantages:

  • we cannot wrap private methods because they are not accessible by proxies
  • we need a container object that would instantiate proxies for us, since the target object doesn’t know that it is proxied
  • if you need the type of a proxied object at runtime for checking something, you always have to use instanceof instead of get_class()

You can see that if you want to implement AOP features in a proxy-based way, you have to adjust the entire application. You always have to keep in mind that you work with proxy objects which cannot be instantiated like non-AOP classes.

Class-based Weaving

Now let’s take a look at class-based weaving. With this strategy, we don’t create any proxies but stay in the target class and extend it with the advice code.

As an example here is our target class again:

After the weaving, MyTargetClass is extended as follows:

As you can see the original method became private and was renamed. A new proxy method is created. If doSomething() is called we can run logic before and after the actual method. This way, we are able to intercept even private methods.

We don’t need other components/containers to instantiate woven objects because after the weaving process they are ready to use without any limitations. Working with such woven objects does not differ from using non-AOP objects. And that’s the reason why Exar uses this approach for creating AOP-aware classes.

Advices in Exar

Our framework will support the following four advice types, which apply to method execution:

  • Before Advice – runs before the advised method is called
  • After Returning Advice – runs after the method finishes execution without exceptions
  • After Throwing Advice – runs after the method throws an exception during execution
  • After Advice – run after the method finishes execution (successful or not)

All these advice types will be described by corresponding interfaces und will be realized as interceptors:

All interceptors have access to the InvocationContext which stores all data around the method execution:

Beside this, AfterReturningInterceptor and AfterInvocationInterceptor consume the result of the method execution. The result can be changed within the interceptor objects.

Now we can write an interceptor that implements one or many of the aforementioned interfaces. For example a simple interceptor that prints a message every time the target method is called:

The most interesting part is to bring interceptors and annotations together, which will allow us to implement annotation-based AOP features. This part will be covered in the next post about Exar.

Continue with Part 5: PHP Class Weaving