赞
踩
AOP面向切面编程,通过预编译方式和运行期动态代理实现程序的统一维护的一种技术。
Aspectj框架就是通过预编译方式实现程序的统一维护,今天介绍如何使用:
//配置版本信息分两步,使用分三步
最新版本的aspectj是1.9.4但是需要SDK最低版本24,这里我就是使用1.8.9版本
//配置信息
1:在工程的build.gradle添加下面依赖
buildscript { repositories { google() //镜像仓,解决需要翻墙下载的 maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } jcenter() } dependencies { classpath 'com.android.tools.build:gradle:3.2.0' //aspectj框架 classpath 'org.aspectj:aspectjtools:1.8.9' classpath 'org.aspectj:aspectjweaver:1.8.9' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } } allprojects { repositories { google() //镜像仓,解决需要翻墙下载的 maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } jcenter() } }
2:在module的build.gradle添加下面依赖
apply plugin: 'com.android.application' android { compileSdkVersion 29 buildToolsVersion "30.0.0" defaultConfig { applicationId "com.example.myaspectj" minSdkVersion 16 targetSdkVersion 29 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } } dependencies { implementation fileTree(dir: "libs", include: ["*.jar"]) implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'androidx.constraintlayout:constraintlayout:2.0.4' testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test.ext:junit:1.1.2' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' //使用aspectj框架 implementation 'org.aspectj:aspectjrt:1.8.9' } //aspectj配置打印log import org.aspectj.bridge.IMessage import org.aspectj.bridge.MessageHandler import org.aspectj.tools.ajc.Main final def log = project.logger final def variants = project.android.applicationVariants variants.all { variant -> if (!variant.buildType.isDebuggable()) { log.debug("Skipping non-debuggable build type '${variant.buildType.name}'.") return } //如果JavaCompile报红能编译过不影响使用 JavaCompile javaCompile = variant.javaCompile javaCompile.doLast { String[] args = ["-showWeaveInfo", "-1.8",//注意版本保存一致 "-inpath", javaCompile.destinationDir.toString(), "-aspectpath", javaCompile.classpath.asPath, "-d", javaCompile.destinationDir.toString(), "-classpath", javaCompile.classpath.asPath, "-bootclasspath", project.android.bootClasspath.join(File.pathSeparator)] log.debug "ajc args: " + Arrays.toString(args) MessageHandler handler = new MessageHandler(true) new Main().run(args, handler) for (IMessage message : handler.getMessages(null, true)) { switch (message.getKind()) { case IMessage.ABORT: case IMessage.ERROR: case IMessage.FAIL: log.error message.message, message.thrown break case IMessage.WARNING: log.warn message.message, message.thrown break case IMessage.INFO: log.info message.message, message.thrown break case IMessage.DEBUG: log.debug message.message, message.thrown break } } } }
使用三部曲
1>自定义注解:根据你的需要设置注解的目标,和作用域
- @Target(ElementType.METHOD)
- @Retention(RetentionPolicy.RUNTIME)
- public @interface LoginTrace {
- String value() default "";
-
- }
2>创建个切面处理类,处理所有使用注解的逻辑,统一在这个类处理
//切面 @Aspect public class LoginAapect { //切入点 ("execution(@注解全类名 * *(..)") @Pointcut("execution(@com.example.administrator.aop_aspectj.annotation.LoginTrace * *(..))") public void methodAnnotationWithLoginTrace() { } //切入点逻辑处理(可以对 切入点 前处理 后处理 前后处理 ) //参数--->切入点方法名()--->methodAnnotationWithLoginTrace() // @After("methodAnnotationWithLoginTrace()")//切入点后运行 --》使用注解LoginTrace的方法运行完后执行这个方法代码(可以不返回对象) // @Before("methodAnnotationWithLoginTrace()")//切入点前运行(可以不返回对象) @Around("methodAnnotationWithLoginTrace()")//切入点前 后 都运行(后运行是在ProceedingJoinPoint对象非空时运行) (必须返回object对象) public Object weaveJoinPoint(ProceedingJoinPoint joinPoint) throws Throwable { Log.e("zdh", "-------------前"); //如果想要获取自定义注解属性值 必须使用@Around 通过ProceedingJoninPoint获取 //例如 LoginTrace loginTrace=((MethodSignarure)joinPoint.getSignature()).getMethod().getAnnotation(LoginTrace.class);//获取自定义注解对象 String value=loginTrace.value();//注解属性值 Object proceed=null; if (joinPoint != null) { //如果使用Around注解需要返回proceed对象,要不然注解方法里面代码不执行 proceed = joinPoint.proceed(); Log.e("zdh", "-------------后"); } return proceed; } }
//在需要统一处理的方法添加注解
- public class MainActivity extends AppCompatActivity {
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- }
-
- //如果你想区分不同方法可以使用标记区分--》@LoginTrace("send")
- @LoginTrace
- public void send(View view) {
- Log.e("zdh","------------测试");
- }
- }
//运行代码就可以看到打印日志如下
注意混淆 在项目的build.build里面配置 扫描指定文件,防止扫描其他文件导致错误
aspectjx { //指定只对含有关键字'universal-image-loader', 'AspectJX-Demo/library'的库进行织入扫描,忽略其他库,提升编译效率 // includeJarFilter 'universal-image-loader', 'AspectJX-Demo/library' include 'com.gemini' exclude 'com.amitshekhar' exclude 'com.mobile' exclude 'com.nirvana' exclude 'com.cmic' exclude 'com.unicom' // excludeJarFilter '.jar' // ajcArgs '-Xlint:warning' }
是不是很简单。
总结:1:在依赖时需要注意1.9前和1.9的SDK最低版本问题,
2:在依赖导报可以添加镜像仓看看。
3:如果使用Around注解需要返回proceed对象,要不然注解方法里面代码不执行
4:使用注解的方法一般是不会影响方法里面代码执行的,所以要考虑方法里面代码执行后的效果,
//下面以实际项目需要写个demo,一般在开发中我们有些页面是需要用户登录后才能进入的,这里面就以登录为实例写个demo
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。