2016-07-02 21 views
5

Próbowałem użyć AspectJ do tkania w aspektach wokół funkcji Kotlin, ale bez powodzenia. Może po prostu konfiguruję coś niepoprawnie, a może AspectJ tego nie obsługuje.Czy w Kotlinie jest jakiś sposób, aby utkać w kodzie przed/po/wokół funkcji, jak to jest z AspectJ w Javie?

Czy ktoś wie, czy jest to możliwe przy użyciu np. Maven i Eclipse (lub IntelliJ)? Czy chcesz wyjaśnić, dlaczego nie jest to możliwe?

+2

Wszelkie oprzyrządowanie na poziomie bajtowym musi działać. Jeśli nie, potrzebujemy minimalnego przykładu niedziałającego kodu + plików kompilacji, aby określić, gdzie jest problem. – voddan

Odpowiedz

1

To właśnie zrobiłem, aby splotować aspekty "binarnie", po tym jak skompilowano kod Java i Kotlin.

Nie udało mi się uzyskać aspectj-maven-plugin, aby prawidłowo wykorzystać aspekt "binarny", więc zamiast tego użyłem wtyczki jcabi-maven-plugin. Zobacz http://plugin.jcabi.com/example-ajc.html

POM, który pracował dla mnie:

<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>my.group.id</groupId> 
<artifactId>my.artifact.id</artifactId> 
<version>0.0.1-SNAPSHOT</version> 

<properties> 
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 
    <maven.compiler.source>1.6</maven.compiler.source> 
    <maven.compiler.target>1.6</maven.compiler.target> 
    <complianceLevel>1.6</complianceLevel> 
</properties> 

<dependencies> 

    <dependency> 
     <groupId>org.jetbrains.kotlin</groupId> 
     <artifactId>kotlin-stdlib</artifactId> 
     <version>1.0.3</version> 
    </dependency> 

    <dependency> 
     <groupId>org.aspectj</groupId> 
     <artifactId>aspectjrt</artifactId> 
     <version>1.8.9</version> 
    </dependency> 

</dependencies> 

<build> 

    <plugins> 

     <plugin> 
      <artifactId>maven-compiler-plugin</artifactId> 
      <groupId>org.apache.maven.plugins</groupId> 
      <version>3.3</version> 
      <configuration> 
       <source>${maven.compiler.source}</source> 
       <target>${maven.compiler.target}</target> 
      </configuration> 
     </plugin> 

     <plugin> 
      <artifactId>kotlin-maven-plugin</artifactId> 
      <groupId>org.jetbrains.kotlin</groupId> 
      <version>1.0.3</version> 
      <configuration> 
       <sourceDirs> 
        <sourceDir>src/main/kotlin</sourceDir> 
        <sourceDir>src/test/kotlin</sourceDir> 
       </sourceDirs> 
      </configuration> 
      <executions> 
       <execution> 
        <id>compile</id> 
        <phase>compile</phase> 
        <goals> 
         <goal>compile</goal> 
        </goals> 
       </execution> 
       <execution> 
        <id>test-compile</id> 
        <phase>test-compile</phase> 
        <goals> 
         <goal>test-compile</goal> 
        </goals> 
       </execution> 
      </executions> 
     </plugin> 

     <plugin> 
      <groupId>com.jcabi</groupId> 
      <artifactId>jcabi-maven-plugin</artifactId> 
      <version>0.14.1</version> 
      <executions> 
       <execution> 
        <goals> 
         <goal>ajc</goal> 
        </goals> 
       </execution> 
      </executions> 
     </plugin> 

     <plugin> 
      <groupId>org.codehaus.mojo</groupId> 
      <artifactId>exec-maven-plugin</artifactId> 
      <version>1.5.0</version> 
      <configuration> 
       <mainClass>my.package.MyMainClassKt</mainClass> 
      </configuration> 
     </plugin> 
    </plugins> 
</build> 

Tak to działa z aspektów i kilku adnotacji określonych w Javie, a następnie przy użyciu tych adnotacji do opisywania metod Kotlin i klas , aby aspekty zostały skutecznie wstrzyknięte do kodu Kotlina.

Pamiętaj, że jeśli plik Kotlin ma zarówno metodę główną, jak i klasę zdefiniowaną w tym samym pliku, kompilator Kotlin tworzy dwa pliki klasy. Jedna klasa z nazwą klasy i jedną klasą z "Kt" dodaną do nazwy. Dobrze wiedzieć, jeśli spróbujesz użyć exec-maven-plugin do uruchomienia kodu Kotlin.

Jednak to nie grało zbyt dobrze w przypadku zaćmienia. Może IntelliJ zrobi lepszą robotę tutaj.

+1

jest jakiś przykład zastosowania aspektj w kotlinach? próbowałem tego, ale to nie zadziałało. – junk

3

Oprócz innych komentarzy/odpowiedzi, myślę, że warto podkreślić, że można "splatać" kod przed/po/wokół kodu funkcji za pomocą inline functions. np .:

fun main(vararg args: String) = nanoTimeAppendedTo(System.out, name = "main") { 
    /* do something, e.g.: */ 
    Thread.sleep(0) 
} 

inline fun nanoTimeAppendedTo(appendable: Appendable, name: String, block:() -> Unit) { 
    val nanoTime = measureNanoTime(block) 
    appendable.appendln("`$name` took $nanoTime ns") 
} 

Nie będzie mieć dostęp do wszystkich informacji, które AspectJ daje jednak do prostych przypadkach, gdy chcesz po prostu ponowne wykonywanie kodu przed/po/wokół innego kodu to działa dobrze.