Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AOP with Kotlin

Tags:

kotlin

aop

I used AOP a lot with Java. It looks like that traditional java approaches can easily be reused with Kotlin. Given Kotlin emphasis on immutability JDK proxies seem to be the most feasible solution in Kotlin provided that you're following the same interface-first (better say trait-first in Kotlin) programming style, e.g.:

trait MyService {
 fun add(a: Int, b: Int): Int
}

class MyServiceImpl: MyService {...}

So now one can easily write an aspect in, say, Spring/AOP and apply it to the instances of MyServiceImpl. It should be mentioned that Java interface-based generated proxies may be more favored by Kotlin developers as cglib requires to get rid of final (i.e. resort to open classes in Kotlin) and use parameterless public constructors for every class which should be wrapped by AOP proxies.

At the same time Java interface-based generated proxies unfortunately impose significant performance penalty so I'm wondering if AOP programming can be done more intuitively or natively to Kotlin in some cases.

So, consider the following example, when I want to use AOP for:

  • Logging arguments and return result of each method exposed from a service.
  • Starting transaction before function call and closing it after function call completes (commit/rollback depending on whether or not an exception has been thrown while making a particular service call).

The most effective but unfortunately the most verbose brute-force solution in the aforementioned example with MyService/MyServiceImpl might look as follows:

class MyServiceLoggingWrapper(val delegate: MyService): MyService {
  val logger = LoggerFactory.getLogger(this.javaClass)

  override fun add(a: Int, b: Int): Int {
    val result = delegate.add(a, b);
    logger.info("MyService.add({}, {}) = {}", a, b, result);
    return result;
  }
} 

class MyServiceTxWrapper(val delegate: MyService, val txManager: TransactionManager): MyService {
 // similar lengthy implementation
}

The LoC complexity of that approach is O(N*K) where N is a number of method and K is a number of aspects that I want to apply.

So what I'm looking is a possible effective (both in terms of performance and LoC) solution for aspects in Kotlin preferrably without resorting to cglib-generated proxies as they impose too many limitations like saying goodbye to final classes and not having parameterless public constructors.

like image 325
Alex Avatar asked Feb 06 '15 00:02

Alex


People also ask

What is Spring AOP example?

Spring AOP takes out the direct dependency of crosscutting tasks from classes that we can't achieve through normal object oriented programming model. For example, we can have a separate class for logging but again the functional classes will have to call these methods to achieve logging across the application.

How does AOP work in spring boot?

AOP (Aspect-Oriented Programming) is a programming pattern that increases modularity by allowing the separation of the cross-cutting concern. These cross-cutting concerns are different from the main business logic. We can add additional behavior to existing code without modification of the code itself.

What is AOP Baeldung?

AOP is a programming paradigm that aims to increase modularity by allowing the separation of cross-cutting concerns. It does this by adding additional behavior to existing code without modifying the code itself. Instead, we can declare the new code and the new behaviors separately.


1 Answers

I am not a Kotlin user, but given the fact that it is targetting the JVM I would suggest trying full-blown AspectJ instead of a proxy-based "AOP lite" approach like Spring AOP. AspectJ does not need/use dynamic proxies, it generates byte code, either during compile time or after compilation (binary weaving) or even during class-loading (load-time weaving).

like image 165
kriegaex Avatar answered Sep 17 '22 12:09

kriegaex