banner
NEWS LETTER

Aop第三方aspectjrt的使用

Scroll down

介绍:

AspectJ是一款面向切面(AOP)的第三方框架,当在AseptJ环境下编译java代码的时候,将使用ajc来替换javac编译,所以Asept是在编译期间就改变了代码结构。

配置:

1. 首先添加maven仓库路径:

在项目的build.gradle中加入以下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
buildscript {
repositories {
google()
jcenter()
mavenCentral()
}
dependencies {
classpath "com.android.tools.build:gradle:4.1.2"
classpath 'org.aspectj:aspectjtools:1.9.6'
classpath 'org.aspectj:aspectjweaver:1.9.6'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}

2. 在module的build.gradle里添加以下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main
android {
···
···

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 = 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;
}
}
}
}
}


dependencies {

···

implementation files('libs/aspectjrt.jar')
//或者
// implementation 'org.aspectj:aspectjrt:1.9.6'

}

3. 创建注解类IFirstAnnotation

@Target 注解目标,表示注解使用在什么地方,这里是METHOD方法;@Retention 保留策略,表示注解调用时机,这里RUNTIME运行时
1
2
3
4
5
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface IFirstAnnotation {
String value();
}

4. 创建切面类MethodBehaviorAspect

自定义注解行为
@Aspect指定切面类;@Pointcut切入点;@Around是切入方式Advice的一种,表示在切入点前后插入代码,还有@Before、@After;Pointcut语法,execution,表示根据Advice在执行方法内部代码前后插入代码,call,表示根据Advice在调用方法前后插入代码......
@pointcut(execution(@全类名 * *(. .)))
后面的两个表示*匹配所有的方法名,两个.表示匹配所有的方法参数.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
@Aspect
public class MethodBehaviorAspect {
private static final String TAG = "aspect_aby";

@Pointcut("execution(@com.test.qby.aspectjlib.annotation.IFirstAnnotation * *(..))")
public void firstMethodAnnotationBehavior() {
}

@Pointcut("execution(* com.test.qby.newtestapplication.ui.MainActivity.aspectClick(android.view.View))")
public void secondMethodAnnotationBehavior() {
}

@Around("firstMethodAnnotationBehavior()")
public Object wavePointcutAround(ProceedingJoinPoint joinPoint) throws Throwable {

MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
// 类名
String className = methodSignature.getDeclaringType().getSimpleName();
// 方法名
String methodName = methodSignature.getName();
// 功能名
IFirstAnnotation behaviorTrace = methodSignature.getMethod()
.getAnnotation(IFirstAnnotation.class);
String value = behaviorTrace.value();
// String value = "点击";
long start = System.currentTimeMillis();
Object result = joinPoint.proceed();
long duration = System.currentTimeMillis() - start;
Log.e(TAG, String.format("%s类中%s方法执行%s功能,耗时:%dms", className, methodName, value, duration));
Toast.makeText(getContext(joinPoint.getThis()), String.format(Locale.CHINESE, "%s类中%s方法执行%s功能,耗时:%dms", className, methodName, value, duration), Toast.LENGTH_SHORT).show();
return result;
}

/**
* 通过对象获取上下文
* @param o o
* @return c
*/
private Context getContext(Object o) {
if (o instanceof Activity) {
return (Activity) o;
} else if (o instanceof Fragment) {
Fragment fragment = (Fragment) o;
return fragment.getContext();
} else if (o instanceof View) {
View view = (View) o;
return view.getContext();
}
return null;
}
}

5. 页面调用

@IFirstAnnotation调用注解,()内部为在IFirstAnnotation中写的value的值,去掉value()后此处去掉()
1
2
3
4
5
6
7
8
@IFirstAnnotation("测试Aspect")
public void aspectClick(View view) {
try {
Thread.sleep(new Random().nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
其他文章
目录导航 置顶
  1. 1. 介绍:
  2. 2. 配置:
请输入关键词进行搜索