March 08, 2018

#Spring part 8: Aspect Oriented Programming Interview Questions & Answers

What is Aspect Oriented Programming?
Aspect-oriented programming or AOP is one of the feature provided by Spring, actually it's not just a feature it a model of programming itself.

Suppose we have a common procedure across different objects, e.g Log message. To implement this, we can have a logMessage() method in all the objects. But this is not really a good design, because we are repeating the same method in all the objects. What we can do, we will create a new Logger class, which has logMessage() method. All other objects will refer to the Logger object's logMessage() method to print the message.

Now, if you are making a design diagram which depicts the relationship between all the objects and you want to know which object is an important one (by checking their relationship with other objects). In such case, the Logger will be the most important object, although it's not adding any business value.

The problem with this approach is that there will be too many relationships to the crosscutting objects and we need to still write the code to call the logMessage() method in all the business objects. In case, we use a different log implementation, then we need to make changes in all the business objects and make the changes accordingly to call the new log method.

All the applications have one other cross cutting concerns like logging, security or transactions. With AOP, we can remove the cross cutting concerns.

With AOP, we will create a 'Logging Aspect' class. After creating the aspect, we do not reference it from the objects, instead we will define the 'aspect configuration' which tells to which objects or methods these aspects apply to.

Suppose we have three business objects Partner, Vendor and Customer, each having the create() method and we need a logging mechanism while creating the Vendor and Customer. We need to do 'aspect configuration', Spring will make sure to call the logging method before creating the Vendor or a Customer. In case you decide to change the logging mechanism, all you need to make changes in 'aspect configuration'.

We can configure aspect to run before or after a particular (target) method.

Steps we need to take to write Aspect oriented program:

  • Write Aspects.
  • Configure where the aspects apply.
AOP Terminologies
  • Aspect: This is a module which has a set of APIs providing cross-cutting requirements. For example, a logging module would be called AOP aspect for logging. An application can have any number of aspects depending on the requirement.
  • Advice: It's the actual action to be taken either before or after the method execution.
  • Join point: It represents a point in your application where we can plug-in the AOP aspect.
  • Pointcut: This is a set of one or more join points where an advice should be executed. We can specify pointcuts using expressions or patterns.
  • Introduction: This allows you to add new methods or attributes to the existing classes.
  • Target object: The object being advised by one or more aspects. This object will always be a proxied object, also referred to as the advised object.
  • Weaving: It is the process of linking aspects with other application types or objects to create an advised object. This can be done at compile time, load time, or at runtime.
What is the difference between a Joint point and Point cut?
Join point is a point of execution of the program, such as the execution of a method or the handling of an exception. In Spring AOP, a join point always represents a method execution.

Pointcut is a predicate or expression that matches join points. Advice is associated with a pointcut expression and runs at any join point matched by the pointcut.



What is Weaving?
Weaving is the process for interleaving separate cross-cutting concerns such as logging into core concerns such as business logic code to complete the system. AOP weaving composes different implementations of aspects into a cohesive system based on weaving rules. The weaving process (aka injection of aspects into Java classes) can happen at:

  • Compile-time: Weaving occurs during compilation process.
  • Load-time: Weaving occurs at the byte-code level at class loading time.
  • Runtime: Similar to load-time where weaving occurs at byte-code level during runtime as join points are reached in the executing application.
On what basis should we decided to use a particular weaving approach?Load-time and runtime weaving have the advantages of being highly dynamic and enabling changes on the fly without having to rebuild and redeploy. But Load-time and runtime weaving adversely affect system performance. Compile time weaving offers better performance but requires rebuilding and redeployment to effect changes. 

How to declare aspect in Spring AOP?
 < bean id="myAspect" class="com.scrutiny.aop.MyAspect" >
   < !-- configure properties of aspect here -- >
 < /bean >

How to declare a pointcut in Spring AOP?
@Pointcut("execution(* update(..))")
private void customerUpdate {}
 

What are the types of advices in Spring AOP?
There are five types of Advices present in Spring:
  • before: Run advice before the a method execution.
  • after: Run advice after the method execution, regardless of its outcome.
  • after-returning: Run advice after the a method execution only if method completes successfully.
  • after-throwing: Run advice after the a method execution only if method exits by throwing an exception.
  • around: Run advice before and after the advised method is invoked. 
A pointcut declaration has four parts:
  • Matching Method Signature Patterns
  • Matching Type Signature Patterns
  • Matching Bean Name Patterns
  • Combining Pointcut Expressions
 What is the difference between concern and cross-cutting concern in Spring AOP?
A Concern is a behavior, which we want to have in our application like Employment Management. Whereas cross-cutting concern is a concern which is applicable throughout the application e.g logging and security.

What are the available AOP implementations?
AspectJ, Spring AOP and JBoss AOP.

How to enable @AspectJ Support?
Include the below XML code in application XML: < aop:aspectj-autoproxy/ >

What are the Pointcut Designators supported by Spring AOP
  • execution: pointcut expression for matching method execution join points.
  • within: pointcut expression for matching to join points within certain types
  • this: pointcut expression for matching to join points where the bean reference is an instance of the given type
  • target: pointcut expression for matching to join points where the target object is an instance of the given type
  • args: pointcut expression for matching to join points where the arguments are instances of the given types
  • @target: pointcut expression for matching to join points where the class of the executing object has an annotation of the given type
  • @args: pointcut expression for matching to join points where the runtime type of the actual arguments passed have annotations of the given type
  • @within: pointcut expression for matching to join points within types that have the given annotation
  • @annotation: pointcut expression for matching to join points where the subject of the join point has the given annotation
Some examples of common pointcut expressions are:
  • the execution of any public method: execution(public * *(..))
  • the execution of any method with a name beginning with "set": execution(* set*(..))
  • the execution of any method defined by the PolicyService interface: execution(* com.scrutiny.service.PolicyService.*(..))
  • the execution of any method defined in the service package: execution(* com.scrutiny.service.*.*(..))
  • the execution of any method defined in the service package or a sub-package: execution(* com.scrutiny.service..*.*(..))
  • any join point (method execution only in Spring AOP) within the service package: within(com.scrutiny.service.*)
  • any join point (method execution only in Spring AOP) within the service package or a sub-package: within(com.scrutiny.service..*)
  • any join point (method execution only in Spring AOP) where the proxy implements the PolicyService interface: this(com.scrutiny.service.PolicyService)
  • any join point (method execution only in Spring AOP) where the target object implements the PolicyService interface: target(com.scrutiny.service.PolicyService)
  • any join point (method execution only in Spring AOP) which takes a single parameter, and where the argument passed at runtime is Serializable:
  • args(java.io.Serializable)
  • any join point (method execution only in Spring AOP) where the target object has an @Transactional annotation: @target(org.springframework.transaction.annotation.Transactional)
  • any join point (method execution only in Spring AOP) where the declared type of the target object has an @Transactional annotation: @within(org.springframework.transaction.annotation.Transactional)
  • any join point (method execution only in Spring AOP) where the executing method has an @Transactional annotation: @annotation(org.springframework.transaction.annotation.Transactional)
  • any join point (method execution only in Spring AOP) which takes a single parameter, and where the runtime type of the argument passed has the @Classified annotation: @args(com.xyz.security.Classified)
  • any join point (method execution only in Spring AOP) on a Spring bean named 'policyService': bean(policyService)
  • any join point (method execution only in Spring AOP) on Spring beans having names that match the wildcard expression '*Service': bean(*Service)
What is the difference between Spring AOP and AspectJ AOP?AspectJ is the industry-standard implementation for Aspect Oriented Programming whereas Spring implements AOP for some cases. Main differences between Spring AOP and AspectJ are:
  • Spring AOP is simpler to use than AspectJ because we don’t need to worry about the weaving process.
  • Spring AOP supports AspectJ annotations, so if you are familiar with AspectJ then working with Spring AOP is easier.
  • Spring AOP supports only proxy-based AOP, so it can be applied only to method execution join points. AspectJ support all kinds of pointcuts.
  • One of the shortcoming of Spring AOP is that it can be applied only to the beans created through Spring Context.
When to use Spring AOP and when to use full AspectJ?
If we only need to advice the execution of operations on Spring beans then we should use Spring AOP. Spring AOP is simpler than AspectJ. Full AspectJ requires the AspectJ complier in the build process. In case if we advice objects not to be managed by Spring Container, use AspectJ.

What are the required libraries to run AspectJ LTW in Spring?
spring-aop.jar, aspectjrt.jar and aspectjweaver.jar
 

Writing Aspect using Aspect Oriented Programming
Let us create first Aspect using Aspect Oriented Programming. For this we will first add dependencies in pom.xml

##pom.xml
 < ?xml version="1.0" encoding="UTF-8"? >
 < project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" >
     < modelVersion > 4.0.0 < /modelVersion >

     < groupId > com.example < /groupId >
     < artifactId > AOPTest < /artifactId >
     < version > 0.0.1-SNAPSHOT < /version >
     < packaging > jar < /packaging >

     < name > AOPTest < /name >
     < description > Demo project for Spring Boot < /description >

     < parent >
         < groupId > org.springframework.boot < /groupId >
         < artifactId > spring-boot-starter-parent < /artifactId >
         < version > 1.5.10.RELEASE < /version >
         < relativePath / >
     < /parent >
     < properties >
         < project.build.sourceEncoding > UTF-8 < /project.build.sourceEncoding >
         < project.reporting.outputEncoding > UTF-8 < /project.reporting.outputEncoding >
         < java.version > 1.8 < /java.version >
     < /properties >
     < dependencies >
         < dependency >
             < groupId > org.springframework.boot < /groupId >
             < artifactId > spring-boot-starter < /artifactId >
         < /dependency >
         < dependency >
             < groupId > org.springframework < /groupId >
             < artifactId > spring-aspects < /artifactId >
             < version > 4.1.1.RELEASE < /version >
         < /dependency >
         < !-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt -- >
         < dependency >
             < groupId > org.aspectj < /groupId >
             < artifactId > aspectjrt < /artifactId >
             < version > 1.8.10 < /version >
         < /dependency >
         < dependency >
             < groupId > org.springframework.boot < /groupId >
             < artifactId > spring-boot-starter-test < /artifactId >
             < scope > test < /scope >
         < /dependency >
         < dependency >
             < groupId > aopalliance < /groupId >
             < artifactId > aopalliance < /artifactId >
             < version > 1.0 < /version >
         < /dependency >
         < dependency >
             < groupId > cglib < /groupId >
             < artifactId > cglib < /artifactId >
             < version > 3.2.6 < /version >
         < /dependency >
         < dependency >
             < groupId > asm < /groupId >
             < artifactId > asm < /artifactId >
             < version > 3.3.1 < /version >
         < /dependency >
     < /dependencies >
     < build >
         < plugins >
             < plugin >
                 < groupId > org.springframework.boot < /groupId >
                 < artifactId > spring-boot-maven-plugin < /artifactId >
             < /plugin >
         < /plugins >
     < /build >
 < /project >


##We will create a class AOPMain which will have a main method. We will be instatiating the Spring context.
package com.test.aop;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.test.aop.service.ShapeService;

public class AOPMain {
    public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
        ShapeService shapeService=context.getBean("shapeService", ShapeService.class);
        System.out.println("*****AOPMain: Inside main(), the Shape circle name is "+shapeService.getCircle().getName());
    }
}


##Create Spring.xml
 < ?xml version="1.0" encoding="UTF-8"? >  
 < 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 name="traingle" class="com.test.aop.model.Traingle" >
         < property name="name" value="Traingle Name" / >
     < /bean >
     < bean name="circle" class="com.test.aop.model.Circle" >
         < property name="name" value="Circle Name" / >
     < /bean >
     < bean name="shapeService" class="com.test.aop.service.ShapeService"    autowire="byName" / >
     < bean name="loggingAspect" class="com.example.aspect.LoggingAspect" / >
 < /beans >


##Circle class
package com.test.aop.model;

public class Circle {
    private String name;
    //getters and setters
}


##Traingle class
package com.test.aop.model;

public class Traingle {
    private String name;
    //getters and setters
}


##Create ShapeService
package com.test.aop.service;

import com.test.aop.model.Circle;
import com.test.aop.model.Traingle;

public class ShapeService {

    private Circle circle;
    private Traingle traingle;

    //getters and setters
}


##Create a LoggingAspect, which will contain list of all the Aspects.
package com.example.aspect;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class LoggingAspect {
   
    /* The advice will run before the execution of getName() method.
     * In this case the advice will executed before calling any method with name getName()*/
    @Before("execution(public String getName())")
    public void getNameAdvice() {
        System.out.println("*****LoggingAspect: getNameAdvice is executed..");
    }
       
    /* If you want advice to execute only before executing a particular method in
     * a specific class then, you need to full path of the class before the method name.*/
    @Before("execution(public String com.test.aop.model.Traingle.getName())")
    public void getTraingleNameAdvice() {
        System.out.println("*****LoggingAspect: getTraingleNameAdvice is executed..");
    }
   
    /* If you want advice to execute every time a method which starts with get and
     * returns a String*/
    @Before("execution(public String get*())")
    public void getAllStringAdvice() {
        System.out.println("*****LoggingAspect: getAllAdvice is executed..");
    }
   
    /* If you want advice to execute every time a method which starts with get, irrespective of the return type*/
    @Before("execution(public * get*())")
    public void getAllAdvice() {
        System.out.println("*****LoggingAspect: getAllAdvice is executed..");
    }
   
    /*Suppose you want to execute two advice's before calling a particular method.
     * 1). You need to declare a methods (e.g forAllGetters() with a @PointCut
     * 2). Declare two advice's and instead of execution, write the name of method which has @PointCut annotation.
     */
   
    @Before("forAllGetters()")
    public void firstAdvice() {
        System.out.println("*****LoggingAspect: firstAdvice is executed..");
    }   
    @Before("forAllGetters()")
    public void secondAdvice() {
        System.out.println("*****LoggingAspect: secondAdvice is executed..");
    }
   
    @Pointcut("execution(* get*())")
    public void forAllGetters()
    {}
   
    /*If you want to apply point cuts to all the methods of a particular class*/   
    @Pointcut("within(com.test.aop.model.Traingle)")
    public void forAllMethodsOfClass()
    {}
   
    /*If you want to apply point cuts to all the methods inside a particular package/ sub package*/
    @Pointcut("within(com.test..*)")
    public void forAllMethodsPackages()
    {}
}


JoinPoints
If you want a advice to print a message depending on which method has actually triggered the advice, this can be done by JoinPoints. The JoinPoints has information about the actual method call, that has triggered the advice.

JoinPoints means, all the places in our code, where we can apply advice.

@Aspect
public class LoggingAspect {
    @Before("forAllMethodsOfCircle()")
    public void circleAdvice(JoinPoint joinPoint) {
        System.out.println("*****LoggingAspect: Circle Advice is executed: "+joinPoint.toString());
        //get Target, returns the object whose method us called which triggered the advice
        Circle circle=(Circle)joinPoint.getTarget();       
    }
   
    /*If you want to apply point cuts to all the methods of a particular class*/   
    @Pointcut("within(com.test.aop.model.Circle)")
    public void forAllMethodsOfCircle()
    {}
   
    /*This will be called for all the methods which takes String as an argument and to get the argument which is passed.*/
    @Before("args(name)")
    public void stringArgumentMethods(String name)
    {
        System.out.println("*****LoggingAspect: methods with String argument:"+name);
    }
}


No comments:

Post a Comment

RSSChomp Blog Directory