Why is AOP required?
We use Object-Oriented Programming (OOP), Functional-Oriented Programming (FOP) models basically to solve Concerns.
- Concerns like reusability of code in case of FOP.
- Concerns like data access, data integrity, data stability in case of OOP.
Even though we use many techniques in OOP to group and encapsulate the concerns into separate, independent entities by providing abstractions. But some concerns still defy these forms of implementation, and are called crosscutting concerns because they "cut across" multiple abstractions in a program.
Example: Logging
Logging is a crosscutting concern, because a logging strategy necessarily affects every logged part of the system. Logging thereby crosscuts all logged classes and methods.
Now Logging aspect is scattered or tangled as code, making it harder to understand and maintain. It is scattered by virtue of the function being spread over a number of unrelated functions that might use it, possibly in entirely unrelated systems, different source languages, etc.
To change logging means the effect will be cascading to all the classes where logging is implemented. It would be a huge task to modify the places where the logging is called.
Simple Banking Scenario Example – Transfer money to another account
void transfer(Account fromAcc, Account toAcc, int amount , Logger logger)throws Exception{
logger.info("transferring money...");if (fromAcc.getBalance() < amount){
logger.info("Insufficient Funds, sorry");throw new InsufficientFundsException();}
fromAcc.withdraw(amount);toAcc.deposit(amount);logger.info("Successful transaction.");}
Now consider what happens if we suddenly need to change the logging considerations for the application. In the program's current version, logging-related operations appear scattered across numerous methods, and such a change would require a major effort.
AOP’s Rescue Solution
AOP attempts to solve this problem by defining rules :
- To find the places where you need to change the code, and
- To suggest what new requirements or functionality you need to add.
These rules are called Aspects.
So now a class or jar file is created, loaded or at runtime, the new functionality that you declared is automatically inserted. The extent of the new implementation is how you have defined the aspect rules.
Example:
In the above logging example, I need to add the time when the logging was created.
@Aspectpublic class LoggingAspect {@Before("call(void Logger.info(String)) && within(*)")public void findtime() {Logger.out.print(new java.util.Date());}}
So here we have set the :
1st rule is to find the function [Logger.info()] to be modified.
2nd rule is to specify within which all packages [within(*)] the implementation should be done.
3rd rule is to specify what new functionality is to be replaced with [findtime()].
4th rule is to specify whether the new functionality is to be inserted before or after the code [@Before].
Now create a following XML config file in META-INF folder on the classpath.
<aspects>
<aspect name="LoggingAspect"/>
</aspects>
Benefits
Now after each class is loaded in the server, if it pass the aspect conditions then the new functionality will be automatically inserted.
We can create a central place to change the cross cutting concerns. A change in one place is affected in all code.
Deployment in production server is easy as it requires no modification of production code and no or less downtime.