Android(安卓)AOP(二):AspectJ在Android中实现Aop
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.IMessageimport org.aspectj.bridge.MessageHandlerimport org.aspectj.tools.ajc.Mainapply 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 {}
@Aspectpublic 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语法的使用
aspecjt文档
更多相关文章
- Android中执行java命令的方法及java代码执行并解析shell命令
- Android中,在C++层使用TinyXML解析XML文件
- Android(安卓)MP4取得播放时长的方法
- 如何保证Android设备的安全性
- 浅谈Java中Collections.sort对List排序的两种方法
- 箭头函数的基础使用
- NPM 和webpack 的基础使用
- Python list sort方法的具体使用
- 【阿里云镜像】使用阿里巴巴DNS镜像源——DNS配置教程