Spring – AOP

Before learning how to implement Aspect-oriented programming with Spring, we should first learn what Aspect-oriented programming is. The definition of Aspect-oriented programming says it is a programming paradigm that aims to increase modularity by allowing the separation of cross-cutting concerns. It does so by adding additional behavior to existing code (an advice) without modifying the code itself.

Now, what did we mean by cross-cutting concerns? Let's explore.

In a real-life project, multiple components play their own role. For example, if we take our previous scenario into account, the Student class itself is a component, similarly there could be a faculty component who would evaluate the student based on his/her performance. So, let's add a faculty to our program.

The Faculty class should be simple enough, with just a method to evaluate a student. Just as follows:

    class Faculty { 
      fun evaluateAssignment() { 
        val marks = Random().nextInt(10) 
        println("This assignment is evaluated and given $marks points") 
      } 
    } 

Now, how should the faculty grade a student? He/she must somehow know that the student has completed an assignment. A common implementation of this business logic would be by modifying the Student class, as follows:

    class Student(val assignment: Assignment, 
      val faculty: Faculty) { 
        fun completeAssignment(assignmentDtl:String) { 
          assignment.performAssignment(assignmentDtl) 
          faculty.evaluateAssignment() 
        } 
      } 

The Faculty instance will be passed to a Student instance, and, once the student is done with performing the assignment, it will call the Faculty instance and instruct it to evaluate the assignment. However, think again. Is this a proper implementation? Why should a student instruct his/her faculty? It's the faculty's job to evaluate assignments of a student; it just needs to get notified somehow.

That very thing is known as a cross-cutting concern. Faculty and Student are different components of the program. They shouldn't have direct interaction at the time of the assignment review.

AOP let's implement the same. So, here, the Student class will be back to almost its original state:

    open class Student(public val assignment: Assignment) { 
      open public fun completeAssignment(assignmentDtl:String) { 
        assignment.performAssignment(assignmentDtl) 
      } 
    } 

Did you notice the differences in the actual code for the Student class in the previous section? Yes, here we added open keyword to the class declaration and all the properties and functions of the class. The reason is that, to implement AOP, Spring sub-classes our beans and overrides methods (including getters of our properties). However, with Kotlin, everything is final unless you specify it as open, and that will block Spring AOP to accomplish its purpose. So, in order to make Spring work, we have to mention each property and method as open.

The main method will be similar, except that we are back to XML-based configuration. Take a look at the following piece of code:

    fun main(args: Array<String>) { 
      val context = ClassPathXmlApplicationContext( 
            "META-INF/spring/student_faculty.xml" 
      ) 
      val student = context.getBean(Student::class.java) 
      student.completeAssignment("One") 
      student.completeAssignment("Two") 
      student.completeAssignment("Three") 
 
      context.close() 
    } 

The only file with new things is the configuration file. Take a look at the configuration file here before we explain it:

    <?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.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd"> <bean id="student" class="com.rivuchk.reactivekotlin.
springdi.aop_student_assignment.Student"> <constructor-arg ref="assignment"/> </bean> <bean id="assignment" class="com.rivuchk.reactivekotlin.springdi.
aop_student_assignment.Assignment" /> <bean id="faculty"
class="com.rivuchk.reactivekotlin.springdi.aop_student_assignment.
Faculty" /><!--1-->
<aop:config><!--2--> <aop:aspect
ref="faculty"><!--3-->
<aop:pointcut
id="assignment_complete"

expression="execution(* *.completeAssignment(..))"/><!--4-->

<aop:after
pointcut-ref="assignment_complete"
method="evaluateAssignment" /><!--5-->
</aop:aspect> </aop:config> </beans>

So, let's explain the configuration. On comment (1), we declared a new bean named faculty, although it really isn't a new thing to you and you may have already expected it. I mentioned it in order to prepare you for the next few lines.

On comment (2), we indicated that the AOP configuration begins. On comment (3), we indicated that this AOP is regarding the Faculty class, as the Faculty class is the class that should be notified.

On comment (4), we declared pointcut. A pointcut is like a bookmark on a method, so whenever that method is called, your class should get notified. The id field denotes the id for that pointcut, so that you can refer to it in your code. The expression field denotes the expression for which we should create the pointcut. Here, with the execution expression, we stated that the pointcut should be on execution of the completeAssignment method.

On comment (5), we declared the method in Faculty class that should get called after the pointcut expression is executed. We can also declare a method to execute before pointcut by using aop:before.

So, now, let's take a look at the following output:

Cropped output of DI with Spring AOP program

As you can see, the evaluateAssignment method is called from the Faculty class every time we call the completeAssignment method, apparently, with no code, but only with configuration.

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

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