• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

Archinamon/android-gradle-aspectj: gradle plug-in adding supports of AspectJ int ...

原作者: [db:作者] 来自: 网络 收藏 邀请

开源软件名称(OpenSource Name):

Archinamon/android-gradle-aspectj

开源软件地址(OpenSource Url):

https://github.com/Archinamon/android-gradle-aspectj

开源编程语言(OpenSource Language):

Kotlin 100.0%

开源软件介绍(OpenSource Introduction):

GradleAspectJ-Android

AspectJ Kotlin Download
Android Arsenal contributions welcome GitHub license

A Gradle plugin which enables AspectJ for Android builds. Supports writing code with AspectJ-lang in .aj files and in java-annotation style. Full support of Android product flavors and build types. Support Kotlin, Groovy, Scala and any other languages that compiles into java bytecode.

Actual version supporting of AGP 4.1.+: com.archinamon:android-gradle-aspectj:4.3.0.

Friendly with jRebel for Android!

This plugin is completely friendly with APT (Android Annotation Processing Tools) and Retrolambda project (but Java 8 not supported in .aj files). AndroidAnnotations, Dagger are also supported and works fine.

This plugin has many ideas from the others similar projects, but no one of them grants full pack of features like this one. Nowadays it has been completely re-written using Transform API.

Key features

Augments Java, Kotlin, Groovy bytecode simultaneously!
Works with background mechanics of jvm-based languages out-of-box!
How to teach Android Studio to understand the AspectJ!
May not work properly for AS 3.0 :(

It is easy to isolate your code with aspect classes, that will be simply injected via cross-point functions, named advices, into your core application. The main idea is — code less, do more!

AspectJ-Gradle plugin provides supply of all known JVM-based languages, such as Groovy, Kotlin, etc. That means you can easily write cool stuff which may be inject into any JVM language, not only Java itself! :)

To start from you may look at my example project. And also you may find useful to look at reference manual of AspectJ language and simple code snippets. In case aspectj-native not supported by Android Studio (even with IDE-plugin it's using is complicated), you may write a java-classes with aspectj annotations.

Two simple rules you may consider when writing aspect classes.

  • Do not write aspects outside the src/$flavor/aspectj source set! These aj-classes will be excluded from java compiler.
  • Do not try to access aspect classes from java/kotlin/etc. In case java compiler doesn't know anything about aspectj, it will lead to compile errors on javac step.

These rules affects only in case you're writing in native aj-syntax. You may write aspects in java-annotation style and being free from these limitations.

Usage

First add a maven repo link into your repositories block of module build file:

mavenCentral()

Don't forget to add mavenCentral() due to some dependencies inside AspectJ-gradle module.

Add the plugin to your buildscript's dependencies section:

Kotlin
classpath("com.archinamon:android-gradle-aspectj:4.3.0")
Groovy
classpath 'com.archinamon:android-gradle-aspectj:4.3.0'

Apply the `aspectj` plugin:
Kotlin
plugins {
    id("com.android.application")
    id("com.archinamon.aspectj")
}
Groovy
plugins {
    id 'com.android.application'
    id 'com.archinamon.aspectj'
}

Now you can write aspects using annotation style or native (even without IntelliJ IDEA Ultimate edition). Let's write simple Application advice:
import android.app.Application;
import android.app.NotificationManager;
import android.content.Context;
import android.support.v4.app.NotificationCompat;

aspect AppStartNotifier {

    pointcut postInit(): within(Application+) && execution(* Application+.onCreate());

    after() returning: postInit() {
        Application app = (Application) thisJoinPoint.getTarget();
        NotificationManager nmng = (NotificationManager) app.getSystemService(Context.NOTIFICATION_SERVICE);
        nmng.notify(9999, new NotificationCompat.Builder(app)
            .setTicker("Hello AspectJ")
            .setContentTitle("Notification from aspectJ")
            .setContentText("privileged aspect AppAdvice")
            .setSmallIcon(R.drawable.ic_launcher)
            .build());
    }
}

Tune extension

Kotlin
aspectj {
    compileTests = true // default value

    ajc = "1.9.4" // default value
    java = JavaVersion.VERSION_1_7 // default value

    /* @see Ext plugin config **/
    includeAllJars = false // default value
    includeJar.addAll(arrayOf("design", "support-v4", "dagger")) // default is empty
    excludeJar.addAll(arrayOf("support-v7", "joda")) // default is empty
    extendClasspath = true // default value

    includeAspectsFromJar.addAll(arrayOf("my-aj-logger-lib", "any-other-libs-with-aspects")) // default is empty
    ajcArgs.apply {
        add("-warn:deprecation")
        add("-referenceInfo")
    }

    weaveInfo = true // default value
    debugInfo = false // default value
    addSerialVersionUID = false // default value
    noInlineAround = false // default value
    ignoreErrors = false // default value
    
    breakOnError = true // default value
    experimental = false // default value
    buildTimeLog = true // default value

    transformLogFile = "ajc-transform.log" // default value
    compilationLogFile = "ajc-compile.log" // default value
}
Groovy
aspectj {
    dryRun false // default value
    compileTests true // default value

    ajc '1.9.4' // default value
    java = JavaVersion.VERSION_1_7 // default value

    /* @see Ext plugin config **/
    includeAllJars false // default value
    includeJar 'design', 'support-v4', 'dagger' // default is empty
    excludeJar 'support-v7', 'joda' // default is empty
    extendClasspath true // default value

    includeAspectsFromJar 'my-aj-logger-lib', 'any-other-libs-with-aspects'  // default is empty
    ajcArgs << '-referenceInfo' << '-warn:deprecation'

    weaveInfo true // default value
    debugInfo false // default value
    addSerialVersionUID false // default value
    noInlineAround false // default value
    ignoreErrors false // default value
    
    breakOnError true // default value
    experimental false // default value
    buildTimeLog true // default value

    transformLogFile 'ajc-transform.log' // default value
    compilationLogFile 'ajc-compile.log' // default value
}

Note that you may not include all these options!

All the extension parameters are have default values (all of them are described above, except of includeJar/Aspects/ajcArgs options). So no need to define them manually.

  • compileTests Workaround to disable compileDebugUnitTestAspectJ for unitTest variant

  • ajc Allows to define the aspectj runtime jar version manually (1.8.12 current)

  • java What jvmTarget will ajc use to compile bytecode into

  • extendClasspath Explicitly controls whether plugin should mutate the classpath with aspectj-runtime itself

  • includeAllJars Explicitly include all available jar-files into -inpath to proceed by AJ-compiler

  • includeJar Name filter to include any jar/aar which name or path satisfies the filter

  • excludeJar Name filter to exclude any jar/aar which name or path satisfies the filter

  • includeAspectsFromJar Name filter to include any jar/aar with compiled binary aspects you wanna affect your project

  • ajcExtraArgs Additional parameters for aspectj compiler

  • weaveInfo Enables printing info messages from Aj compiler

  • debugInfo Adds special debug info in aspect's bytecode

  • addSerialVersionUID Adds serialVersionUID field for Serializable-implemented aspect classes

  • noInlineAround Strict ajc to inline around advice's body into the target methods

  • ignoreErrors Prevent compiler from aborting if errors occurs during processing the sources

  • breakOnError Allows to continue project building when ajc fails or throws any errors

  • experimental Enables experimental ajc options: -XhasMember and -Xjoinpoints:synchronization,arrayconstruction. More details in issue #18

  • buildTimeLog Appends a BuildTimeListener to current module that prints time spent for every task in build flow, granularity in millis

  • transformLogFile Defines name for the log file where all Aj compiler info writes to, new separated for Transformer

  • compilationLogFile Defines name for the log file where all Aj compiler info writes to, new separated for CompileTask

Extended plugin config

Kotlin
plugins {
    id("com.android.application")
    id("com.archinamon.aspectj-ext")
}
Groovy
plugins {
    id 'com.android.application'
    id 'com.archinamon.aspectj-ext'
}

Ext config: - allows usage of `includeJar` and `includeAllJars` parameters, with workaround to avoid `Multiple dex files exception` - supports `multiDex` - supports `Instrumented tests`

Currently it has some limitations:

  • InstantRun must be switched off (Plugin detects IR status and fails build if IR will be found).

Provider plugin config

Kotlin
plugins {
    id("com.android.application")
    id("com.archinamon.aspectj-provides")
}
Groovy
plugins {
    id 'com.android.application'
    id 'com.archinamon.aspectj-provides'
}

Plugin-provider may be useful for that cases when you need to extract aspect-sources into separate module and include it on demand to that modules where you only need it. Therefor this behavior will save you build-time due to bypassing aspectj-transformers in provide-only modules.

You ain't limited to describe as much provider-modules as you need and then include them using includeAspectsFromJar parameter in the module which code or dependencies you may want to augment.

With example project you could learn how to write such provider-module.

DryRun plugin config

Kotlin
plugins {
    id("com.android.application")
    id("com.archinamon.aspectj-dryRun")
}
Groovy
plugins {
    id 'com.android.application'
    id 'com.archinamon.aspectj-dryRun'
}

Disables aspectj-compiler and transformation task for the hole project.

Working tests

Kotlin
plugins {
    id("com.android.application")
    id("com.archinamon.aspectj-junit")
}
Groovy
plugins {
    id 'com.android.application'
    id 'com.archinamon.aspectj-junit'
}

Test scope overloads JUnit compilation flow with AJC instead of JavaC. So any aspects has been written within `test` directory will be compiled with all java sources and aspects will weave them if need.

ProGuard

Correct tuning will depends on your own usage of aspect classes. So if you declares inter-type injections you'll have to predict side-effects and define your annotations/interfaces which you inject into java classes/methods/etc. in proguard config.

Basic rules you'll need to declare for your project:

-adaptclassstrings
-keepattributes InnerClasses, EnclosingMethod, Signature, *Annotation*

-keepnames @org.aspectj.lang.annotation.Aspect class * {
    ajc* <methods>;
}

If you will face problems with lambda factories, you may need to explicitly suppress them. That could happen not in aspect classes but in any arbitrary java-class if you're using Retrolambda. So concrete rule is:

-keep class *$Lambda* { <methods>; }
-keepclassmembernames public class * {
    *** lambda*(...);
}

Changelog

4.2.1 -- Improve jar archives

  • better api for AGP 4.0.+;
  • fix java.lang.NoClassDefFoundError: Failed resolution of: Landroidx/appcompat/R$drawable;

4.2.0 -- Support AGP 4.0.+

  • this release supports agp 4.0.+ but earlier versions not;

4.1.0 -- Support AGP 3.6.+

  • this release supports agp 3.6.+ but earlier versions not;

4.0.1 -- Fix synchronous run

  • fixed async running of ajc (which is not supporting async compiling);

4.0.0 -- Support AGP 3.5.+

  • this release supports agp 3.5.+ but earlier versions not;

3.4.5 -- Fix for Gradle 6.0

  • create task explicitly instead of project.task();

3.4.3 -- Once more fix :(

  • hotfixed provides plugin mode — transformation should not starts;

3.4.2 -- Hotfix provides

  • hotfixed provides plugin mode — transformation should not starts;

3.4.1 -- Fix provides

  • fixed aspectj-provides plugin mode — do not cleanup destination dir;

3.4.0 -- Better DryRun mode

  • fixed support of 3.5.0 Android Gradle Plugin — thanks to @superafroman;
  • remove aj runtime check;
  • standalone DryRun plugin mode to avoid transformation and compilation steps;

3.3.12 -- Fix 'Dependencies resolution fail'

  • fixed rare bug — 'failed to attach configuration after dependencies has been resolved';
  • better properties extraction within kts script;

3.3.11 -- Fix legacy AGP support

  • better legacy support — fixed AGP 3.1.4 compatibility;

3.3.10 -- Update AJC

  • bump aspectj compiler version;

3.3.9 -- Small fix dryRun

  • to prevent aj transformation with empty outputs — use -PdryRunAjc=true;

3.3.8 -- Fix unitTest variant

  • added workaround to disable unitTest aj compile step if classpath is broken;

3.3.7 -- Fixes ext plugin

  • fixed aspectj-ext plugin to work properly with transform api;
  • added transform output dir to inPath;
  • fix ajc inPath for compilation step;

3.3.6 -- Fixes

  • fix dryRun option for transformer;
  • better readme;

3.3.5 -- Dry run

  • fix classpath resolving;
  • implement dry run to disable compiler/transformation in gradle;

3.3.3 -- Support AGP 3.3.+

  • fixed support AGP 3.3.+ api;
  • added legacy compatibility fallbacks;
  • added java bytecode target version for ajc;
  • upgrade bundled ajc runtime and tools jars to 1.9.2;
  • upgrade default aspectj runtime library to 1.9.2;

3.3.0 -- JUnit tests support

  • implementing com.archinamon.aspectj-junit plugin supporting weaving unit tests;
  • com.archinamon.aspectj-test has been removed as not working legacy sh$t;
  • updated android-gradle-plugin to 3.2.0 inside (might be a breaking change);
  • migration to Kotlin-DSL;
  • new plugin tests allows to check does it weaves android's junit source code;

3.2.0 -- Gradle 3.0.0 support

  • added support of stable gradle plugin 3.0.0;
  • updated internal ajc and provided aj runtime library versions to the latest 1.8.12;

3.1.1 -- Useful improvements

  • added an extension trigger to append BuildTime logger for current module;
  • back from grave — added exclude-filter for aspectj-ext plugin;

3.1.0 -- Provider

  • implemented provides plugin split to effectively extract aspects to external/sub modules;
  • small code improvements and cleanups;

3.0.3 -- Minor fixes

  • fixed aar detecting mechanism;
  • registered plugin in mavenCentral!

3.0.0 -- Grand refactoring in Kotlin

  • all groovy classes was obsolete;
  • new code-base in Kotlin 1.1.1 stable;

2.4.3 -- Hot-fixed two-step compilation

  • compiled in first step aspect classes have not been copied to final output;

2.4.2 -- Hot-fix

  • fixed missed variable;
  • fixed imports;

2.4.0 -- Added aspectj-ext plugin

  • includeJar parameter now able to read aar's manifest file to exactly detect required library;
  • com.archinamon.aspectj-ext plugin added to properly weave inpath jars, in this mode InstantRun doesn't allowed;
  • small fixes and package/name refactoring;

2.3.1 -- New two-step build mechanic

  • renamed extension parameter: ajcExtraArgs -> ajcArgs;
  • split parameter: logFileName -> [transformLogFile, compilationLogFile];
  • added separate compile task to build all sources under /aspectj folder;
  • aj-transformer now looks into /build/aspectj/$variantName folder for aspects class';
  • updated ajc-version to 1.8.10;
  • fixed issue with missing error printing to Messages when failing;
  • added inpath/aspectpath clearance before emitting transform inputs (by @philippkumar);

2.3.0 -- Major fixes

  • InstantRun support;
  • fails androidTest hot launch;
  • ZipException within augmenting third party libraries via AspectJ;
  • more clear logging and errors emitting;

热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap