在本文的第一部分中 ,我展示了在测试方面AspectJ在android开发中很有用的一些方法。 最后一部分演示了一种结合AspectJ的方法,以及如何在构建过程中使Aspect编织变得可配置。
Android + AspectJ
在互联网上进行的搜索表明,有多种方法可以将AspectJ集成到Android构建过程中,包括手动进行或使用gradle插件进行。 最近几年,我一直在使用android-gradle-aspectj插件,因为它具有一些有用的功能,并且作者似乎保持了相当好的状态。
此插件的基本设置要求将其添加到buildscript存储库和依赖项块中。 我在项目根目录的build.gradle中有此文件。
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:xxx'
classpath 'com.archinamon:android-gradle-aspectj:xxx'
} }
然后在需要的地方应用插件,因此在模块build.gradle中:
apply plugin: 'com.archinamon.aspectj'
要么
plugins {
id 'com.android.application'
id 'com.archinamon.aspectj' }
这足以运行一个简单的案例,例如第一篇文章中的示例 。 请参阅插件文档以获取更多高级配置。
- 模块构建目录中的aspectj目录,其中包含已编译的方面类文件
- 插件在模块build目录中生成的一些日志文件ajc-transform.log和ajc-compile.log
- AspectJ插件任务的构建输出日志,请编译[Build variant] Aspectj和transformClassesWithAspectjFor [Build variant] 。
确定何时使用方面
如果我们仅使用方面进行测试,则大多数时候我们不希望将方面代码合并到构建过程中。 确定何时编织外观代码的一种简单方法是使用布尔条件。
例如,在方面文件中,在切入点中包含布尔条件,以确定建议是否适用:
pointcut myPointcut(): if (aspectjEnabled) && ... // the rest of the pointcut
此处,布尔值“ AspectjEnabled ”用作标志,它将确定方面代码是否将应用建议。
将此标志传递给Aspect类的一种方法是使用生成的BuildConfig类,可以在应用程序的构建文件( build.gradle )中对其进行设置。
android {
buildTypes {
debug {
// Flags for Aspect testing
buildConfigField 'boolean' , 'aspectjEnabled' , true
}
} }
然后,在外观文件的切入点中,包括标志作为条件。
pointcut myPointcut(): if (BuildConfig.aspectjEnabled) && ... // the rest of the pointcut
当然,我们可以更进一步,并从gradle项目属性中设置该标志,而不是在build.gradle中对其进行硬编码。
现在,当构建完成时,传递一个项目属性来确定是否要设置纵横比标志。
-PaspectjEnabledProperty = true

如果未指定project属性,则我还有一点额外的选择将Aspect标志设置为false(这是当我们要进行没有方面的常规构建时的默认设置)。
ext.aspectjEnabledProperty = getAspectJEnabledFlag() def getAspectJEnabledFlag() {
if (project.hasProperty( 'aspectjEnabledProperty' ))
return project. property ( 'aspectjEnabledProperty' )
else
return false }
然后,在应用程序的构建文件中,将动态设置要放入BuildConfig类中的Aspect标志的值。
android {
buildTypes {
debug {
// Flags for Aspect testing
buildConfigField 'boolean' , 'aspectjEnabled' , "${aspectjEnabledProperty}"
}
} }
总而言之,这意味着如果没有将属性'aspectjEnabledProperty'传递给构建或将其设置为false,则不会进行AspectJ编织。 然后,在需要时,可以设置该属性以测试该特定代码位。
当然,您不仅限于一个方面标志,还可以为要运行的不同测试设置任意多个标志。
-PexceptionTestProperty = true -PcrashTestProperty = false -PservicesTestProperty = true
测试多种类型的错误
在上面的配置中,我使用了布尔值作为标志来启用/禁用切入点中的方面编织。 使用布尔标志是最简单的情况,并且可能是最常用的类型。
但是,如果要测试多种类型的错误和错误处理该怎么办。 例如,如果您要测试是否使用建议方法抛出不同类型的异常。 另一个示例是,如果您想模拟不同的状态代码作为网络呼叫的响应。
然后,不要使用布尔值作为标志,而是使用整数(或任何其他简单类型)。
-PaspectjTestingProperty = 1
然后在构建文件中:
ext.aspectTestingFlag = getAspectTestingFlag() def getAspectTestingFlag() {
if (project.hasProperty( 'aspectjTestingProperty' ))
return project. property ( 'aspectjTestingProperty' )
else
// default value if property not specified
return 0 } android {
buildTypes {
debug {
// Flags for Aspect testing
buildConfigField 'int' , 'aspectTestingFlag' , "${aspectjTestingProperty}"
}
} }
然后,在方面中,您可以将整数标志用作切入点中的条件,也可以用作指示符,在建议中运行不同的代码。
aspect TestAspect {
pointcut myPointcut(): if (BuildConfig.aspectjTestingFlag != 0 ) && ... // the rest of the pointcut
int around(): myPointcut() {
switch (BuildConfig.aspectjTestingFlag) {
case 1 :
// return a particular status code, or throw a particular exception type
case 2 :
// return a different status code, or throw a different exception type
case 3 :
// return yet another status code, or throw a third different exception type
default :
return proceed();
}
} }
注意事项
请注意以下几点:
- 如前所述,由于我们只能为Android开发编排AspectJ编译时间,因此这意味着需要为AspectJ任务增加一些构建时间。
- 不幸的是, Android Studio不支持AspectJ,因为它基于IntelliJ IDEA社区版。
尽管Intellij的终极版确实支持AspectJ ,但我更喜欢使用Android Studio。小费:
有时,为了正确设置切入点,我会将带有方面,要建议的类及其lib依赖关系的文件复制到虚拟Eclipse项目中,以便可以使用AspectJ开发工具(AJDT)来微调切入点。 这使我可以查看切入点是否正确地应用于了我想要的连接点。 - 使用Gradle插件来处理将AspectJ纳入构建过程确实使事情变得容易。 但是,这有时意味着必须等待插件的作者跟上最新版本的android gradle插件或gradle。
翻译自: https://www.javacodegeeks.com/2020/06/is-aspectj-still-useful-for-android-part-2.html