简体   繁体   English

多模块项目中带有Gradle的Android AspectJ

[英]Android AspectJ with Gradle in multimodule project

Is there any way to apply aspectJ pointcuts from library module to whole project? 有什么方法可以将库模块中的AspectJ切入点应用于整个项目? It means that I need attach library to existitng project, and it must intercept method calls from main project with all it dependencies (also including Android SDK methods) For now I trying to do this by script in build.gradle: 这意味着我需要将库附加到existitng项目,并且它必须拦截来自主项目及其所有依赖项的方法调用(还包括Android SDK方法)现在,我尝试通过build.gradle中的脚本来执行此操作:

android.libraryVariants.all { variant ->

variant.javaCompile.doLast {
// Find the android.jar and add to iajc classpath
    def androidSdk = android.adbExe.parent + "/../platforms/" + android.compileSdkVersion +    "/android.jar"
    println 'Android SDK android.jar path: ' + androidSdk

    def iajcClasspath;
    iajcClasspath = androidSdk;


    project.rootProject.allprojects.each { proj ->
        if (proj.configurations.hasProperty("compile"))
            iajcClasspath += ":" + proj.configurations.compile.asPath
        // handle aar dependencies pulled in by gradle (Android support library and etc)
        tree = fileTree(dir: "${proj.buildDir}/exploded-aar", include: '**/classes.jar')
        tree.each { jarFile ->
            iajcClasspath += ":" + jarFile
        }
    }
    println 'Classpath for iajc: ' + iajcClasspath
    ant.taskdef(resource: "org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties", classpath: configurations.ajc.asPath)
    println 'ajctPath : ' + configurations.ajc.asPath.toString()
    println 'aspectPath : ' + configurations.aspects.asPath.toString()
    println 'inpath : ' + configurations.ajInpath.asPath.toString()
    ant.iajc(
            source: sourceCompatibility,
            target: targetCompatibility,
            fork: true,
            destDir: "${project.buildDir}/classes/${variant.dirName}",
            aspectPath: configurations.aspects.asPath,
            inpath: configurations.ajInpath.asPath,
            sourceRootCopyFilter: "**/*.java",
            classpath: iajcClasspath
    ) {
        sourceroots {
            android.sourceSets.main.java.srcDirs.each {
                pathelement(location: it.absolutePath)
            }
// Build config file
            pathelement(location: "${project.buildDir}/source/buildConfig/${variant.dirName}")
// Android resources R.***
            pathelement(location: "${project.buildDir}/source/r/${variant.dirName}")
        }
    }
}
}

But pointcuts works only on methods, called from this module. 但是切入点仅适用于从此模块调用的方法。 Also, even if I move script to main build.gradle, and replace android.libraryVariants to android.applicationVariants, pointcuts aren't work on attached .jar libraries and modules, but work on gradle dependencies (such as compile 'com.googlecode.mp4parser:isoparser:1.0.1', for example). 此外,即使我将脚本移至主要的build.gradle,并将android.libraryVariants替换为android.applicationVariants,切入点也不适用于附加的.jar库和模块,但适用于gradle依赖项(例如编译'com.googlecode。 mp4parser:isoparser:1.0.1')。

And if there no way to do this with AspectJ, maybe there is some other way to intercept method calls in all project from project library? 而且,如果没有使用AspectJ进行此操作的方法,也许还有其他方法可以拦截项目库中所有项目中的方法调用? The most important thing is that there should not be any changes in main module code, just in library. 最重要的是,主模块代码不应仅在库中进行任何更改。

After read document from ant ajcTask , I finally implement with my gradle plugin GradleAndroidAspectJPlugin . 从ant ajcTask阅读文档之后,我终于用gradle插件GradleAndroidAspectJPlugin实现了。

I use the iajc classpath and inpath property to specify which classes(jars) will be compile as classpath or will be re-compile from aspectj compiler. 我使用iajc classpath和inpath属性来指定哪些类(罐)将被编译为类路径,或者将从Aspectj编译器重新编译。

def aopTask = project.task("compile${buildTypeName}AspectJ") {
                doFirst {
                    project.configurations.aspectsInPath.each {
                        aspectsInPaths.add(it);
                        aspectsInPathsAbsolute.add(it.absolutePath);
                    }
                }

                doLast {
                    ant.taskdef(
                            resource: "org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties",
                            classpath: project.configurations.aspectjTaskClasspath.asPath
                    )
                    ant.iajc(
                            source: project.android.compileOptions.sourceCompatibility,
                            target: project.android.compileOptions.targetCompatibility,
                            fork: "true",
                            destDir: variant.javaCompile.destinationDir,
                            bootClasspath: project.android.bootClasspath.join(File.pathSeparator),
                            inpathDirCopyFilter: "java/**/*.class"
                    ) {
                        classpath {
                            variant.javaCompile.classpath.each {
                                if (!aspectsInPathsAbsolute.contains(it)) {
                                    pathElement(location: it)
                                }
                            }
                        }
                        inpath {
                            pathElement(location: copyDir)
                            aspectsInPaths.each {
                                if (!it.name.startsWith("aspectjrt")) {
                                    pathElement(location: it)
                                }
                            }
                        }
                    }
                }
            }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM