AOP introduction

While writing any software application, the best practice is to divide your code into multiple independent modules based on business use cases. For example, you write an Employee Service class for all employee-related functions, an HRService class for all HR-related functions, and so on and so forth.

In general, the whole application consists of a set of independent classes that span multiple verticals and doesn’t share the same class hierarchy. This diagram depicts this scenario: 

Irrespective of the independent nature of each vertical, there are a few common items you need to implement across all of them, such as transaction management, session management, audit logging, security, caching, or any such custom processing mechanism based on rules.

If you wish to implement these common services across verticals with a traditional approach, you need to put them into each of the methods in these classes manually. Taking an example of a logging mechanism, for this, you would need to write a little bit of code at the beginning and end of every method.

This leads to code duplication, as the same logic needs to be placed several times. This leads to a maintenance nightmare in the later part of the application development process when any changes are introduced. Let's understand how.

Suppose, as per your business requirements, you add audit logs after each update and delete method. You put the method name and its time in the log. Now, let's say your business needs to place the name of currently logged-in users in the log. In this case, you need to update the logging details manually in several methods.

This is just one example. You will end up changing the code for each of the common services, spread across multiple verticals. The effective solution is to keep them isolated from verticals. Implement them in one place and plug them into other core business classes as and when required based on certain rules or criteria.

In essence, the core part of the business logic does not have to know that something that is common across multiple classes has been included, removed, or changed, and can keep working as before. Separating common functionalities (cross-cutting concerns in the AOP paradigm) and turning them on and off without touching or modifying the core business logic, will eventually increase modularity and bring great flexibility in terms of maintenance in any applicationAOP aims to provide a way to achieve this solution. AOP is mainly used to provide declarative services.

To understand AOP concepts, it's crucial to understand the terminology used in the AOP paradigm:

  • Concern: This is a behavior or functionality we want to achieve in our application. For example, HR management and employee management are two functionalities, and are thus considered as concerns in AOP.
  • Aspect: In very simple terms, this is a common behavior that spans multiple classes in the same or different hierarchy. In other words, the common concept that cuts across multiple concerns is called the aspect. In our example, the logging mechanism is called the aspect in AOP terminology. 
  • Join-point: This is a point during the execution flow of the application where you need to apply Advice. For example, a method invocation or a place where you need to handle an exception could be join-point.
  • Advice: This is an action performed on a specific join-point by the AOP framework. Conceptually, it's a common functionality implementation at that join-point. The process of applying Advice can be controlled by specifying various types, such as around, before, after, throws, and so on. 
  • Point-cut: This is an expression that describes a pattern of applicable join-points. In other words, the AOP framework will apply the Advice (common functionality) on join-points (methods) that are described by a point-cut (for example, set* means all methods start with the word set). We can say a point-cut is a filter criterion to choose join-points in the system.

In most cases, developers get confused between join-point and point-cut. Let's take a real-life example to understand the difference. Suppose you want to buy cooking oil and you go to the department store. You reach the grocery section and find various edible oils made from difference sources, such as sunflower, groundnut, cotton seed, rice brand, corn, and so on.

Your requirement is to choose light oil (in terms of low cholesterol) for your daily needs, and hence you choose either sunflower oil or rice brand oil. In this case, all the available edible oils are the join-points, and your choice of sunflower/rice brand oil, based on your needs, is considered a point-cut. In short, all available options are considered as join-points, while the one you choose, based on your needs, is called a point-cut.

  • Target object: That is the object in which the common functionalities are being implemented. In other words, this is the object on which the Advice is applied by a set of aspects.
  • AOP-Proxy: Proxy is a design pattern used to encapsulate the object and control access to it. The AOP framework creates a proxy/dynamic object to implement various aspects (in the form of Advice). In short, AOP creates a proxy object that looks like the object on which the proxy was created, but with a few additional features. In Spring Framework, AOP-proxy is supplied through the JDK or the CGLIB library.
  • Weaving: As we have seen, the main idea behind AOP is to plug common behaviors (or aspects) into business classes without modifying them. The process of linking such aspects with other classes to apply Advice is called weaving.

Weaving can be done at compile or run time. Spring AOP supports load-time weaving, while the AspectJ framework supports both compile-time and load-time weaving.

  • Compile-time weaving: In this type of weaving, the process of linking aspects is performed at compile time. The AOP framework will apply the aspects to your Java source file and create a binary class file, which is woven with those aspects. AspectJ uses a special compiler to achieve compile-time weaving.
  • Post-compile-time (or binary) weaving: This is similar to compile-time weaving. The process of linking aspects is performed on precompiled classes, or JAR files. The aspects that are woven may be in either source or binary form. This, again, can be done through a special compiler. Both compile-time and post-compile-time weaving can be achieved through AspectJ.
  • Runtime weaving: Compile-time and post-compile-time weaving happens before the actual class file is loaded into memory, whereas runtime (or load-time) weaving happens once the target class is loaded into JVM by the class loader. Runtime weavers are supported by both the Spring AOP and AspectJ frameworks.

The process of weaving can be expressed through the following diagram:

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.143.235.219