AOP is a programming paradigm, which defines some set of principles. If you write a program following the AOP principles then it is called AOP style of programming.
In every program there will be two types of logic
o primary business logic
o helper logic
which makes primary business logic work better. For example calculating the loan amount will be primary business logic, but in addition we may write some logging, here logging is called secondary logic because without logging our functionality will be fulfilled but without loan calculation logic we cannot say our application is complete.
As logging will be done across various components of the application so it is called cross-cutting logic.
Examples of cross-cutting concerns are Auditing, Security, Logging, Transactions, Profiling and Caching etc.
AOP principles
• Aspect – Aspect is the place of code that has to be applied across various classes of the application.
• JoinPoint – The point at which you want to apply the aspect logic, generally in spring you can apply an aspect at method execution.
• Advice – Action taken by an aspect at a particular JoinPoint. Advice indicates how you want to apply the aspect on a JoinPoint. There are multiple types of advices like before advice, after returning advice, around advice and throws advice.
• Pointcut – Collection oj JoinPoint representing on whom you want to advice the aspect.
• Target – The class on which you want to advice the aspect.
• Weaving – The process of advising a target class with an aspect based on a pointcut to build proxy.
• Proxy – The outcome of weaving is called proxy, where the end class generated out of weaving process contains cross-cutting logic as well.
There are many frameworks in the market which allows you to work with AOP programming few of them are Spring AOP, AspectJ, JAC (Java aspect components), JBossAOP etc.
The most popular once are AspectJ and SpringAOP.
Spring AOP
• Only supported joinpoint is method execution.
• Spring supports run-time weaving; this means the proxy objects will be built on fly at runtime in the memory.
• Spring supports static and dynamic pointcuts.
AspectJ AOP
• It supports various types of JoinPoints like constructor execution, method execution, field set or field get etc.
• AspectJ uses compile-time weaving; this indicates your proxy classes will be available whenever you compile your code.
• AspectJ supports only static pointcuts.
At the time spring released AOP, already aspect AOP has acceptance in the market, and seems to be more powerful than spring AOP. Spring developers instead of comparing the strengths of each framework, they have provided integrations to AspectJ to take the advantage of it, so spring 2.x not only supports AOP it allows us to work with AspectJ AOP as well.
In spring 2.x it provided two ways of working with AspectJ integrations
1. Declarative programming model
2. AspectJ Annotation model
With this we are left with three ways of working with spring AOP as follows.
1. Spring AOP API (alliance API) – Programmatic approach
2. Spring AspectJ declarative approach
3. AspectJ Annotation approach
Even spring has integrated with ApsectJ, it supports only few features of AspectJ described as below.
1. Still the supported JoinPoint is only a method execution.
2. Spring doesn’t rely on AspectJ weaving capabilities, and uses its own weaving module so the weaving will happens at run-time.
3. As AspectJ doesn’t support dynamic pointcut’s, integrating with spring doesn’t make any difference.
Types of Advices
Spring AOP implementation supports 4 types of advices, each one is described below.
1. Around advice – This is the advice that executes the aspect around the target class joinpoint, so here the advice method will be called before the target class method execution. So, the advice can control the target method execution.
2. Before advice – In this always the advice method executes before the target class method executes. Once the advice method finishes execution the control will not returned back to the advice method.
3. After Returning advice – Here the advice method executes after the target class method finishes execution, but before it returns the value to the caller.
4. Throws Advice – This advice method will be invoked only when the target class method throws an exception.
Programmatic AOP
We use Spring AOP API’s to work with programmatic AOP. As described programmatic AOP supports all the types of advices described above. Let us try to work with each advice type in the following section.
Around Advice
Aspect is the cross-cutting concern which has to be applied on a target class; advice represents the action indicating when to execute the aspect on a target class. Based on the advice type we use, the aspect will gets attached to a target class. If it is an around advice, the aspect will be applied before and after, which means around the target class joinpoint execution.
1. We have control over arguments; it indicates we can modify the arguments before executing the target class method.
2. We can control the target class method execution in the advice. This means we can even skip the target class method execution.
3. We can even modify the return value being returned by the target class method.
In order to work with any advice, first we need to have a target class, let us build the target class first.
Math.java
public class Math { public int add(int a, int b) { return a+b; } public int multiply(int a, int b) { return a*b; } }
After creating the target class, we need to code the aspect representing the advice it is using. Create a class for example LoggingAspect which implements from MethodInterceptoe and need to override the method invoke; this method accepts a parameter MethodInvocation, into which the entire information about the actual method would be passed.
LoggingAspect.java
import org.aopalloance.intercept.MethodInterceptor; import org.aopalloance.intercept.MethodInvocation; public class LoggingAspect implements MethodInterceptor { @Override public Object invoke(MethodInvocation methodInvocation) throws Throwable { Object args[] = methodInvocation.getArguments(); String methodName = methodInvocation.getMethod().getName(); //log statement before execution System.out.println(“entering into method : “ +methodName+”(“+args[0]+”,”+args[1]+”)”); //modify arguments before calling args[0] = (Integer) args[0] + 10; args[1] = (Integer) args[1] + 10; //proceed() calls the target method add Object ret = methodInvocation.proceed(); //log statement after execution System.out.println(“existing the method :”+methodName+”(“+args[0] +”,”+args[1]+”)return value :”+ret); //modify return value ret = (Integer) ret + 10; return ret; } }
Once the target and advice has been built, we can perform weaving to attach the aspect to the target. In order to perform weaving to build proxy, we need to use ProxyFactory class. To the ProxyFactory we need to add Advice and supply the target class on to which you want to apply that advice.
As we are working on programmatic AOP, the weaving process will be done programmatically.
AATest.java
import org.springframework.aop.framework.ProxyFactory; import org.springframework.aop.support.DefaultPointcutAdvisor; import com.aa.beans.LoggingAspect; import com.aa.beans.LoggingDynamicPointcut; import com.aa.beans.LoggingStaticPointCut; import com.aa.beans.Math; public class AATest { public static void main(String[] args) { ProxyFactory pf = new ProxyFactory(); Pf.addAdvice(new LoggingAspect()); Pf.setTarget(new Math()); Math math = (Math) pf.getProxy(); System.out.println(“Sum : “+math.add(4,20)); //System.out.println(“Multiplication :”+ math.multiply(1,2)); } }
Before Advice
In a Before advice always the advice method executes before your target class joinpoint executes. Once the advice method finishes execution the control will be automatically transferred to the target class method and will not be returned back to the advice. So, in a Before Advice we have only one control point, which is only we can access arguments and can modify them.
1. Can access and modify the arguments of the original method.
2. Cannot control the target method execution, but we can abort the execution by throwing an exception in the advice method.
3. Capturing and modifying the return value is not applicable as the control doesn’t return back to the advice method after finishing you target method.
In order to create a Before Advice, we need to first build a target class. Then we need to create an Aspect class which implements from MethodBeforeAdvice and should override before method. This method has three arguments java.reflect.Method method, Object[] args and Object targetObject. Use these parameters we can access the original method arguments and the method information.
LoanCalculator.java
public class LoanCalculator { public float calculateInterest(Long principle, int noOfYears, float rateOfInterest) { return (principle * noOfYears * rateOFInterest) / 100; } }
LoanCalculator is the target class, before calling the calculateInterest, we want to check whether the caller is logged in and authenticated to call the method or not. We can check this in the calculateInterest() method itself, but if we don’t want impose security check for this method, we need to modify source of this method to get rid of cross-cutting security code.
UserInfo.java (Class holding username and password values)
public class UserInfo { private String userName; private String password; public UserInfo(String username, String password) { this.userName = userName; this.password = password; } //setter and getters on userName and password attributes }
AuthenticationManager.java (helper class to perform login, authenticate and logout)
public class AuthenticationManager { private static ThreadLocal<UserInfo> threadLocal = new ThreadLocal<UserInfo>(); public void login(String un, String pwd); threadLocal.set(new UserInfo(un,pwd)); } public void logout() { threadLocal.set(null); } public boolean isAuthenticated() { boolean flag = false; UserInfo userInfo = threadLocal.get(); if(userInfo != null) { if(userInfo.getUserName().equals(“ramu”) && userInfo.getPassword().equals(“welcome1”)) { flag = true; } } return flag; } }
SecurityAspect.java (Aspect class which executes before target method execution)
import java.lang.reflect.Method; import org.springframework.aop.MethodBeforeAdvice; public class SecurityAspect implements MethodBeforeAdvice { @Override public void before(Method method, Object[] args, Object target) throws Throwable { System.out.println(“entering into method :” + method); //check authenticated AuthenticationManager am = new AuthenticationManager(); boolean flag = am.isAuthenticated(); if(flag == false) { throw new IllegalAccessException(“Invalid username/password”); } //if authentication success //modify arguments args[0] = (Long) args[0] + 33; } }
The code for building the proxy is same as for around advice. In the above the before method in the advice will execute before the calculateInterest() method in LoanCalculator class, here we are checking whether the user is authenticated to access the method or not. If not authenticated, will throw IllegalAccessException and aborting the calculateInterest() method execution.
BATest.java
import org.springframework.aop.framework.ProxyFactory; import com.ba.beans.AuthenticationManager; import com.ba.beans.LoanCalculator; import com.ba.beans.SecurityAspect; public class BATest { public static void main(String[] args) { ProxyFactory pf = new ProxyFactory(); pf.addAdvice(new SecurityAspect()); pf.setTarget(new LoanCalculator()); LoanCalculator proxy = (LoanCalculator) pf.getProxy(); AuthenticationManager am = new AuthenticationManager(); am.login(“ramu”,”welcome1”); System.out.println(“Interest :” + proxy.calculateInterest(10L, 1, 12.0f)); } }
After Returning Advice
In this the advice method will be executed only after the target method finishes execution and before it returns the value to the caller. This indicates that the target method has almost returned the value, but just before returning the value it allows the advice method to see the return value but doesn’t allows to modify it. So, in a After returning advice we have the below control points.
1. We can see parameters of the target method, even we modify there is no use, because by the time the advice method is called the target method finished execution, so there is no effect of changing the parameter values.
2. You cannot control the target method execution as the control will enters into advice method only after the target method completes.
3. You can see the return value being returned by the target method, but you cannot modify it, as the target method has almost returned the value. But you can stop/abort the return value by throwing exception in the advice method.
In order to create an After returning advice, after building the target class, you need to write the aspect class implementing the AfterReturningAdvice and should override the method afterReturning, the parameters to this method are Object returnvalue (returned by actual method), java.reflect.Method method (original method), Object[] args (target method arguments), Object targetObject (with which the target method has been called).
KeyGenerator.java
import java.util.Random; public class KeyGenerator { public int generateKey(int size) { Random random = new Random(size); random.setSeed(5); int key = random.nextInt(); return key; } }
WeakKeyCheckerAspect.java
aspect checks whether the key computed by KeyGenerator class is strong or weak key.
import java.lang.reflect.Method; import org.springframework.aop.AfterReturningAdvice; public class WeakKeyCheckerAspect implements AfterReturningAdvice { @Override public void afterReturning(Object retVal, Method method, Object[] args, Object target) throws Throwable { if((Integer) retVal <= 0) { throw new IllegalArgumentException(“Weak Key Generated”); } } }
Throws Advice
Throws advice will be invoked only when the target class method throws exception. The idea behind having a throws advice is to advice to have a centralized error handling mechanism or some kind of central processing whenever a class throws exception.
Following are the control points a throws advice has.
1. It can see the parameters that are passed to the original method.
2. There is no point in controlling the target method execution, as it would be invoked when the target method rises as exception.
3. When a method throws exception, it cannot return a value, so there is nothing like seeing the return value or modifying the return value.
In order to work with throws advice, after building the target class, you need to write a class implementing the ThrowsAdvice interface. The ThrowsAdvice is a marker interface this means; it doesn’t define any method in it.
When a target class throws exception spring IOC container will tries to find a method with name afterThrowing in the advice class, having the appropriate argument representing the type of exception class. We can have afterThrowing method signatures shown below.
afterThrowing([Method, args, target], subclassOFThrowable)
In the above signature, Method, args and target is optional and only mandatory parameter is subclassOfThrowable. If a advice class contains afterThrowing method with both the signature handling the same subclassOfThrowable, the max parameter method will be executed upon throwing the exception by target class.
Thrower.java
public class Thrower { public int willThrow(int i) { if(i <= 0) { throw new IllegalArgumentException(“Invalid parameter i”); } return i + 10; } }
ExceptionLoggerAspect.java
import java.lang.reflect.Method; import og.springframework.aop.ThrowsAdvice; public class ExceptionLoggerAspect implements ThrowsAdvice { public void afterThrowing(IllegalArgumentException ie) { System.out.println(“thrown :” + ie.getMessage()); } public void afterThrowing(Method method, Object[] args, Object target, IllegalArgumentException ie) { System.out.println(“Exception thrown by :”+method.getName() + “(“ +args[0] + “) with exception message :”+ie.getMessage()); } }
Pointcut
In all the above examples, we haven’t specified any pointcut while advising the aspect on a target class; this means the advice will be applied on all the joinpoints of the target class. With all the methods of the target class will be advised, so if you want to skip execution of the advice logic on a specific method of a target class, in the advice logic we can check for the method name on which the advice is being called and based on it we can execute the logic.
In order to overcome this you need to attach a pointcut while performing the weaving, so that the proxy would be generated based on the pointcut specified and will do some optimizations in generating proxies.
Spring AOP API supports two types of pointcuts. Those a static and dynamic pointcuts. All the pointcut implementations are derived from org.springframework.aop.Pointcut interface. Spring has provided in-built implementation classes from this Interface.
Static Pointcut:
1. StaticMethodMatcherPointcut
2. NameMatchMethodPointcut
3. JdkRegexpMethodPointcut
Dynamic Pointcut:
• DynamicMethodMatcherPointcut
Static Pointcut
In order to use a StaticMethodMatcherPointcut, we need to write a class extending from StaticMethodMatcherPointcut and needs to override the method matches. The matches method takes arguments as Class and Method as arguments.
Spring while performing the weaving process, it will determines whether to attach an advice on a method of a target class by calling matches method on the pointcut class.
LoggingStaticPointcut.java
import java.lang.reflect.Method;
import org.springframework.aop.support.StaticMethodMatcherPointcut;
public class LoggingStaticPointCut extends StaticMethodMatcherPointcut {
@Override
public boolean matches(Method method, Class targetClass) {
if(Math.class == targetClass && method.getName().equals(“multiply”)) {
return true;
}
return false;
}
}
While performing the weaving, we need to supply the pointcut as input to the ProxyFactory.
BATest.java
Skipped logic for clarity
ProxyFactory pf = new ProxyFactory();
Pf.addAdvisor(new DefaultPointcutAdvisor(new LoggingDynamicPointcut(), new LoggingAspect()));
Pf.setTarget(new Math());
Math math = (Math) pf.getProxy();
Dynamic Pointcut
If you observe in static pointcut we have hardcoded the class and method names on whom we need to advice the aspect. So, the decision of advising the aspect on a target would be done at the time of weaving and would not be delayed till the method call. In case of Dynamic Pointcut, the decision of whether to attach an aspect on a target class would be made based on the parameters with which the target method has been called.
LoggingDynamicPointcut.java
import java.lang.reflect.Method; import org.springframework.aop.support.DynamicMethodMatcherPointcut; public class LoggingDynamicPointcut extends DynamicMethodMatcherPointcut { @Override public boolean matches(Method method, Class<?> targetClass, Object[] args) { if(Math.class == targetClass && method.getName().equals(“add”) && (Integer) args[0] > 5) { return true; } return false; } }
Table representing the control points for several advices.
Declaration AOP
Spring 2.x has added support to declarative AspectJ AOP. The main problem with programmatic approach is your application code will tightly couple with spring, so that you cannot detach from spring. If you use declarative approach your advice or aspect classes are still pojo’s, you don’t need to implement or extend from any spring specific interface or class. Your advice classes uses AspectJ AOP API classes, in order to declare the pojo as aspect you need to declare it in the configuration file rather than weaving it using programmatic approach.
The declarative approach also supports all the four types of advices and static pointcut.
Around Advice
In this approach the aspect class is not required to implement from any spring specific class or interface, rather it should be declared as aspect in configuration file.
public Object methodName(ProceedingJoinPoint pjp)
This acts as an advice method. The return type of the method should be Object as the around advicw has control over the return value. The advice method name could be anything but should take the parameter as ProceedingJoinPoint, the method on a target class is called JoinPoint in AOP.
Using the ProceedingJoinPoint, you can access the actual method information similar to MethodInterceptor.
LoggingAspect.java
import org.aspectj.lang.ProceedingJoinPoint; public class LoggingAspect { public Object log(ProceedingJoinPoint pjp) throws Throwable { String methodName = pjp.getSignature().getName(); Object args[] = pjp.getArgs(); System.out.println(“entering into” + methodName + “(“ + args[0] + “,” +args[1] + ”)”); //modify parameters args[0] = (Integer) args[0] + 10; Object ret = pjp.proceed(args); System.out.println(“exiting from “ + methodName + “(“ + args[0] + “,” +args[1] + “) with return value (original) : “ +ret); //modify ret val ret = (nteger) ret + 10; System.out.println(“exiting from” + methodName + “(“ + args[0] + “,” + args[1] + “) with return value (modified) : “ + ret); return ret; } }
While declaring a class as a aspect, you need to import the “aop” namespace and need to use the tag
application-context.xml
<bean id=”math” class=”com.aa.beans.Math”/> <bean id=”loggingAspect” class=”com.aa.beans.LoggingAspect”/> <aop:config> <aop:pointcut expression=”execution(* com.aa.beans.Math.*(..))” id=”pc1”/> <aop:aspect id=”la1” ref=”loggingAspect”> <aop:around method=”log” pointcut-ref=”pc1”/> </aop:aspect> </aop:config>
If you observe we have used a pointcut expression rather than referring to a class representing as pointcut. This pointcut expression is a static pointcut expression, and it has been written in OGNL expression language. OGNL stands for Object Graph Navgation Language.
Expression starts with execution as aword representing apply the advice to all the class executions and the syntax.
execution(
when you create a core container with the following configuration, spring ioc container while creating will apply the advice on the target class (based on the pointcut) and creates proxy classes and instantiates these classes and host in IOC container.
Before Advice
While working with Before Advice the entire approach is same like creating the aspect class and should declare a method, here the method should be public and the return type should be void as the Before advice cannot control the return value. The parameter to the advice method is JoinPoint rather than ProceedingJoinPoint as we don’t have control on method execution.
SecurityAspect.java
import org.aspectj.lang.JoinPoint; public class SecurityAspect { public void check(JoinPoint jp, long principal, int noOfYears, float rateOfInterest) throws Throwable { System.out.println(“Principal :” + principal); AuthenticationManager am = new AuthenticationManager(); boolean flag = am.isAuthenticates(); if(flag == Boolean.FALSE) { throw new IllegalAccessException(“User not logged in”); } } }
application-context.xml
<aop:config> <aop:pointcut expression=”execution(* com.ba.beans.*.*(..)) and args(principal,noOfYears,rateOfIntetest))” id=”pc1”/> <aop:aspect id=”ap1” ref=”securityAspect”> <aop:before method=”check” pointcut-ref=”pc1”/> </aop:aspect> </aop:config>
After Returning Advice
In the after returning advice while writing the advice method in the aspect, you need to have declared the method with return type as void as it cannot control the return value and the method takes two parameters. The first parameter is the JoinPointn and the second would be the variable in which you want to receive the return value of the target method execution.
WeakKeyCheckerAspect.java
public class WeakKeyCheckerAspect { public void checkKey(JoinPoint jp, int generatedKey) { //write the code to execute the logic with the return value. } }
application-context.xml
<aop:config> <aop:pointcut expression=”execution(* com.ar.beans.*.*(..))” id=”pc1”/> <aop:aspect id=”ap1” ref=”weakKeyCheckerAspect”> <aop:afterReturning method=”checkKey” returning=”generatedKey” pointcut-ref=”pc1”/> </aop:aspect> </aop:config>
Throws Advice
In this we need to write the aspect class with advice method taking the signature as below.
public void methodName([Method, args[], targetObject], subClassOfThrowable)
declaration we need to declare the variable in which you are receiving the exception as throwing.
application-context.xml
<aop:config> <aop:pointcut expression=”execution(* com.ta.beans.*.(..))” id=”pc1”/> <aop:aspect id=”ap1” ref=”loggingExceptionAspect”> <aop:afterReturning method=”handle” throwing=”ex” pointcut-ref=”pc1”/> </aop:aspect> </aop:config>
AspectJ Annotation AOP
In this approach instead of using declarations to expose the classes as aspect and advice, we will annotate the classes with annotations. In order to make a class as aspect, we need to annotate the class with @Aspect. To expose a method as advice method, we need to annotate the method in aspect class with @Around or @Before or @AfterReturning or @AfterThrowing representing the types of advice. These annotations take the pointcut expression as value in them.
Working with advices
The same rules defined in declarative aop section applies in writing the advice method in annotation approach as well, but only difference is annotate the class as @Aspect and annotate the method with @Around(“pointcut expression”).
LoggingSecurityAspect.java
import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; @Aspect public class LoggingSecurityAspect { @Around(“execution(* com.ba.beans.Math.*(..))”) public Object log(ProceedingJoinPoint pjp) throws Throwable { String methodName = pjp.getSignature().getName(); System.out.println(“entering into “ + methodName); Object ret = pjp.proceed(); System.out.println(“exiting from “ + methodName); return ret; } }
In order to detect the annotations marked on the classes, we need to add
If we are using pointcut expression on the multiple advice methods, instead of re-writing the expression in all the places you can declare a method representing the pointcut expression. Annotate that method with @Pointcut(“expression”) and in the @Around or @Before or other advice annotations, use the method name as value representing the pointcut expression.
LoggingSecurityAspect.java
import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annoatation.AfterThrowing; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; @Aspect public class LoggingSecurityAspect { @Pointcut(“execution(* com.ba.beans.Math.*(..))”) public void mathPointcut() { } @Around(“mathPointcut()”) public Object log(ProceedingJoinpoint pjp) throws Throwable { String methodName = pjp.getSignature().getName(); System.out.println(“entering into “ + methodName); Object ret = pjp.proceed(); System.out.println(“exiting from “ + methodName); return ret; } @Before(“mathPointcut()”) public void check(JoinPoint jp) throws Throwable { AuthenticationManager am = new AuthenticationManager(); boolean flag = am.isAuthenticated(); if(flag == false) { throw new IllegalAccessException(“Invalid user/pwd”); } System.out.println(“Aunthenticated successfully”); } @AfterThrowing(pointcut = “mathPointcut()”, throwing = “ex”) public void handle(IllegalAccessException ex) { System.out.println(“I am in handle method”); System.out.println(“Exception Message : “ + ex.getMessage()); } @AfterReturning(pointcut = “mathPointcut()”, returning = “sum”) public void monitor(JoinPoint jp, int sum) { System.out.println(“In monitor method”); System.out.println(“Returning value : “ + sum); } }
Aspect Oriented Programming (AOP)
Java Collections
Inserting Data in Table
Create Table
Spring ORM(Object Relational Mapping)
Java,Javac,path,classpath,JDK,JVM,JRE
Port already in Use - Tomcat
Thanks for reading. If you like this post please follow us for more updates about technology related updates.
No comments:
Post a Comment