AspectJ
AspectJ实际上是对AOP编程思想的一个实践,当然,除了AspectJ以外,还有很多其它的AOP实现,例如ASMDex,但目前最好、最方便的,依然是AspectJ。
AOP的用处非常广,从Spring到Android,各个地方都有使用,特别是在后端,Spring中已经使用的非常方便了,而且功能非常强大,但是在Android中,AspectJ的实现是略阉割的版本,并不是所有功能都支持,但对于一般的客户端开发来说,已经完全足够用了。
在Android上集成AspectJ实际上是比较复杂的,不是一句话就能compile,但是,鄙司已经给大家把这个问题解决了,大家现在直接使用这个SDK就可以很方便的在Android Studio中使用AspectJ了。Github地址如下:
https://github.com/HujiangTechnology/gradle_plugin_android_aspectjx
另外一个比较成功的使用AOP的库是Jake大神的Hugo:
https://github.com/JakeWharton/hugo
AOP 能做什么?
持久化
性能监控
数据校验
缓存
…
1.引入 AspectJ
app/build.grade加入以下配置项,app和library配置相同:
import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main
apply plugin: 'com.android.library'
android {
compileSdkVersion 26
defaultConfig {
minSdkVersion 15
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
repositories {
jcenter()
mavenCentral()
}
buildscript {
repositories {
jcenter()
mavenCentral()
}
dependencies {
classpath 'org.aspectj:aspectjtools:1.8.9'
// 如果是android library 要加上
classpath 'org.aspectj:aspectjweaver:1.8.9'
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'org.aspectj:aspectjrt:1.8.9'
// compile 'com.android.support:appcompat-v7:27.1.1'
}
android.libraryVariants.all { variant ->
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", android.bootClasspath.join(
File.pathSeparator)]
MessageHandler handler = new MessageHandler(true)
new Main().run(args, handler)
def log = project.logger
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:
case IMessage.INFO:
log.info message.message, message.thrown
break
case IMessage.DEBUG:
log.debug message.message, message.thrown
break
}
}
}
}
2.AspectJ 语法
JPoint:代码可注入的点,比如一个方法的调用处或者方法内部、“读、写”变量等。
Pointcut:用来描述 JPoint 注入点的一段表达式,比如:调用 Animal 类 fly 方法的地方,call(* Animal.fly(..))。
Advice:常见的有 Before、After、Around 等,表示代码执行前、执行后、替换目标代码,也就是在 Pointcut 何处注入代码。
Aspect:Pointcut 和 Advice 合在一起称作 Aspect。
3.使用
统计一下某个方法的运行时间
public class StopWatch {
private long startTime;
private long endTime;
private long elapsedTime;
public StopWatch() {
//empty
}
private void reset() {
startTime = 0;
endTime = 0;
elapsedTime = 0;
}
public void start() {
reset();
startTime = System.nanoTime();
}
public void stop() {
if (startTime != 0) {
endTime = System.nanoTime();
elapsedTime = endTime - startTime;
} else {
reset();
}
}
public long getTotalTimeMillis() {
return (elapsedTime != 0) ? TimeUnit.NANOSECONDS.toMillis(endTime - startTime) : 0;
}
}
public class DebugLog {
private DebugLog() {}
/**
* Send a debug log message
*
* @param tag Source of a log message.
* @param message The message you would like logged.
*/
public static void log(String tag, String message) {
// Log.i(tag, message);
System.out.print(message);
}
}
@Retention(RetentionPolicy.CLASS)
@Target({ ElementType.CONSTRUCTOR, ElementType.METHOD })
public @interface DebugTrace {}
@Aspect
public class TraceAspect {
private static final String POINTCUT_METHOD =
"execution(@com.example.libraryaspectj.DebugTrace * *(..))";
private static final String POINTCUT_CONSTRUCTOR =
"execution(@com.example.libraryaspectj.DebugTrace *.new(..))";
@Pointcut(POINTCUT_METHOD)
public void methodAnnotatedWithDebugTrace() {}
@Pointcut(POINTCUT_CONSTRUCTOR)
public void constructorAnnotatedDebugTrace() {}
@Around("methodAnnotatedWithDebugTrace() || constructorAnnotatedDebugTrace()")
public Object weaveJoinPoint(ProceedingJoinPoint joinPoint) throws Throwable {
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
String className = methodSignature.getDeclaringType().getSimpleName();
String methodName = methodSignature.getName();
final StopWatch stopWatch = new StopWatch();
stopWatch.start();
Object result = joinPoint.proceed();
stopWatch.stop();
DebugLog.log(className, buildLogMessage(methodName, stopWatch.getTotalTimeMillis()));
Log.i("*** yang",buildLogMessage(methodName, stopWatch.getTotalTimeMillis()));
return result;
}
/**
* Create a log message.
*
* @param methodName A string with the method name.
* @param methodDuration Duration of the method in milliseconds.
* @return A string representing message.
*/
private static String buildLogMessage(String methodName, long methodDuration) {
StringBuilder message = new StringBuilder();
message.append("methodName --> ");
message.append(methodName);
message.append(" --> ");
message.append("[");
message.append(methodDuration);
message.append("ms");
message.append("]");
return message.toString();
}
}
然后在app中的某activity
...
@DebugTrace
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_file_list);
...
即会打印出 I/* yang: Libraryaspectj –> onCreate –> [82ms]
以上就是对aspectj的简单实现后续展开都是遵循aspectj语法的使用