AOP : Aspect Oriented Programming
AOP : programming paradigm that aims to increase modularity by allowing the separation of cross-cutting concerns.
In any Application development we will have 2 things
1)Business Logic
2)Cross cutting logic
1) : Actual business related code : ex adding an employee details to DB
2): cross-cutting concerns are aspects of a program that affect other concerns. Ex: adding logging to the method execution
Lets create a class ManageEmployees
- package com.kb.AOPNeed;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class ManageEmployees {
- void addEmployee(long empId){
- System.out.println("addEmployee is running");//DAO call to persist Employee into DB }
- void removeEmployee(long empId){
- System.out.println("removeEmployee is running");//DAO call to delete Employee from DB }
- public static void main(String[] args) {
- ApplicationContext applicationContext = new ClassPathXmlApplicationContext("com/kb/AOPNeed/beans.xml");
- ManageEmployees manageEmployees = applicationContext.getBean("manageEmployees",ManageEmployees.class);
- manageEmployees.addEmployee(100);
- manageEmployees.removeEmployee(100);
- }
- }
package com.kb.AOPNeed; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class ManageEmployees { void addEmployee(long empId){ System.out.println("addEmployee is running");//DAO call to persist Employee into DB } void removeEmployee(long empId){ System.out.println("removeEmployee is running");//DAO call to delete Employee from DB } public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("com/kb/AOPNeed/beans.xml"); ManageEmployees manageEmployees = applicationContext.getBean("manageEmployees",ManageEmployees.class); manageEmployees.addEmployee(100); manageEmployees.removeEmployee(100); } }
Now in the above class we have 2 methods addEmployee() and removeEmployee()
Each method is performing its own logic( business logic).
Now if I want to track the entry and exit of these 2 methods , what can we do
Possibly we can write log statements at the beginning and end of those 2 methods which is as below
- package com.kb.AOPNeed;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class ManageEmployees {
- void addEmployee(long empId){
- System.out.println("addEmployee() begin");
- System.out.println("addEmployee is running");//DAO call to persist Employee into DB
- System.out.println("addEmployee() end");
- }
- void removeEmployee(long empId){
- System.out.println("removeEmployee() begin");
- System.out.println("removeEmployee is running");//DAO call to delete Employee from DB
- System.out.println("removeEmployee() begin");
- }
- public static void main(String[] args) {
- ApplicationContext applicationContext = new ClassPathXmlApplicationContext("com/kb/AOPNeed/beans.xml");
- ManageEmployees manageEmployees = applicationContext.getBean("manageEmployees",ManageEmployees.class);
- manageEmployees.addEmployee(100);
- manageEmployees.removeEmployee(100);
- }
- }
package com.kb.AOPNeed; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class ManageEmployees { void addEmployee(long empId){ System.out.println("addEmployee() begin"); System.out.println("addEmployee is running");//DAO call to persist Employee into DB System.out.println("addEmployee() end"); } void removeEmployee(long empId){ System.out.println("removeEmployee() begin"); System.out.println("removeEmployee is running");//DAO call to delete Employee from DB System.out.println("removeEmployee() begin"); } public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("com/kb/AOPNeed/beans.xml"); ManageEmployees manageEmployees = applicationContext.getBean("manageEmployees",ManageEmployees.class); manageEmployees.addEmployee(100); manageEmployees.removeEmployee(100); } }
Now the output is
see the output , before and after performing business logic, our method have executed the logs which is as expected since it’s a method body.
Assume if we have 1000 such methods in our application then we need to add log message in all the 1000 methods both at the beginning and at the end of the method.
So this kind of adding cross cutting concerns to all other concerns(business logic) can be achieved very well using AOP.
Lets resolve the same above problem using AOP.
We will use Spring supported AspectJ style AOP.
To use AOP with Spring , we need to add following jars to the classpath
aspectjrt.jar aspectjweaver.jar aopalliance-1.0.jar spring-aop.jar
Redefine same ManageEmployees class by removing log messages
- package com.kb.AOPNeed;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class ManageEmployees {
- void addEmployee(long empId){
- System.out.println("addEmployee is running");//DAO call to persist Employee into DB
- }
- void removeEmployee(long empId){
- System.out.println("removeEmployee is running");//DAO call to delete Employee from DB
- }
- public static void main(String[] args) {
- ApplicationContext applicationContext = new ClassPathXmlApplicationContext("com/kb/AOPNeed/beans.xml");
- ManageEmployees manageEmployees = applicationContext.getBean("manageEmployees",ManageEmployees.class);
- manageEmployees.addEmployee(100);
- manageEmployees.removeEmployee(100);
- }
- }
package com.kb.AOPNeed; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class ManageEmployees { void addEmployee(long empId){ System.out.println("addEmployee is running");//DAO call to persist Employee into DB } void removeEmployee(long empId){ System.out.println("removeEmployee is running");//DAO call to delete Employee from DB } public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("com/kb/AOPNeed/beans.xml"); ManageEmployees manageEmployees = applicationContext.getBean("manageEmployees",ManageEmployees.class); manageEmployees.addEmployee(100); manageEmployees.removeEmployee(100); } }
Now create LoggingAspect using AspectJ style of AOP as below
- package com.kb.AOPNeed;
- import org.aspectj.lang.JoinPoint;
- import org.aspectj.lang.annotation.After;
- import org.aspectj.lang.annotation.Aspect;
- import org.aspectj.lang.annotation.Before;
- @Aspect
- public class LoggingAspect {
- @Before("execution(* com.kb.AOPNeed.*.*(..))")
- public void logBeforeExecutingMethod(JoinPoint joinPoint){
- System.out.println("logBeforeExecutingMethods is running for the method "+joinPoint.getSignature().getName());
- }
- @After("execution(* com.kb.AOPNeed.*.*(..))")
- public void logAfterExecutingMethod(JoinPoint joinPoint){
- System.out.println("logAfterExecutingMethods is running for the method "+joinPoint.getSignature().getName());
- }
- }
package com.kb.AOPNeed; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; @Aspect public class LoggingAspect { @Before("execution(* com.kb.AOPNeed.*.*(..))") public void logBeforeExecutingMethod(JoinPoint joinPoint){ System.out.println("logBeforeExecutingMethods is running for the method "+joinPoint.getSignature().getName()); } @After("execution(* com.kb.AOPNeed.*.*(..))") public void logAfterExecutingMethod(JoinPoint joinPoint){ System.out.println("logAfterExecutingMethods is running for the method "+joinPoint.getSignature().getName()); } }
Create a bean configuration file beans.xml
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
- http://www.springframework.org/schema/aop
- http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
- <aop:aspectj-autoproxy />
- <bean id="manageEmployees" class="com.kb.AOPNeed.ManageEmployees" />
- <!-- Aspect -->
- <bean id="logAspect" class="com.kb.AOPNeed.LoggingAspect" />
- </beans>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd "> <aop:aspectj-autoproxy /> <bean id="manageEmployees" class="com.kb.AOPNeed.ManageEmployees" /> <!-- Aspect --> <bean id="logAspect" class="com.kb.AOPNeed.LoggingAspect" /> </beans>
Now run the ManageEmployees class defined above
Output is
since we have defined a pointcut to match any method in the ManageEmployees class, our aspect is applied to any number of methods we define inside this class.
So cross cutting concerns is completely separated from the actual business logic.
Lets try to understand terms in AOP
1)Aspect – cross cutting concern ,something global feature of the application.
In our example -> it is LoggingAspect
2)Join Point – point during the execution of the program such as method execution or exception handling code. In simple words the point where the cross cutting concerns can be applied
In our example -> 2 methods addEmployee() and removeEmployee()
3)Advice – the Action taken at the join point. means implementation of any global feature/cross cutting feature.
Printing log message before and after method execution
4)Point cut – Expression which matches the exact join points, it will have many join points in it.
In our example -> @Before(“execution(* com.kb.AOPNeed.*.*(..))”) and @After(“execution(* com.kb.AOPNeed.*.*(..))”) which matches any method inside our ManageEmployees class