2016-07-02 23 views
5

Ho provato ad usare AspectJ per intrecciare aspetti attorno alle funzioni di Kotlin, ma senza successo. Forse sto solo configurando qualcosa in modo non corretto, o forse AspectJ non supporta questo.C'è qualche modo in Kotlin per tessere in codice prima/dopo/intorno a funzioni come c'è con AspectJ in Java?

Qualcuno sa se questo è possibile utilizzando ad esempio maven ed Eclipse (o IntelliJ)? O preoccuparsi di spiegare perché non è possibile?

+2

Qualsiasi strumento a livello di bytecode deve funzionare. In caso contrario, abbiamo bisogno di un esempio minimale di un codice non funzionante + di file di build per sapere dove si trova il problema. – voddan

risposta

1

Questo è quello che ho fatto per tessere negli aspetti il ​​modo "binario", dopo che il codice Java e Kotlin è stato compilato.

Non ho potuto ottenere il aspectj-maven-plugin per tessere correttamente l'aspetto "binario", quindi ho usato il plugin jcabi-maven-plugin. Vedere http://plugin.jcabi.com/example-ajc.html

Il pom che ha funzionato per me:

<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> 

Quindi, questo funziona con gli aspetti e qualche annotazioni definite in Java, e quindi utilizzando queste annotazioni per annotare i metodi e classi Kotlin , per avere gli effetti iniettati con successo nel codice Kotlin.

Si noti che se il file Kotlin ha sia un metodo principale sia una classe definiti nello stesso file, il compilatore Kotlin produce due file di classe. Una classe con il nome della classe e una classe con "Kt" aggiunta al suo nome. Buono a sapersi se si tenta di utilizzare il plugin exec-maven per eseguire il codice Kotlin.

Tuttavia, questo non ha funzionato molto bene con eclipse. Forse IntelliJ farà un lavoro migliore qui.

+1

c'è qualche esempio per usare aspectj in kotlin? ho provato questo, ma non ha funzionato. – junk

3

In aggiunta agli altri commenti/risposte, penso che sia importante sottolineare che è possibile "tessere" codice prima/dopo/attorno al codice funzione utilizzando inline functions. es .:

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") 
} 

Non avrete accesso a tutte le informazioni che ti dà AspectJ, ma per i casi semplici in cui si desidera semplicemente riutilizzare l'esecuzione di un codice prima/dopo/intorno a qualche altro codice questo funziona bene.