自从在徐医生的公众号上面看到了AOP的介绍,心中一阵窃喜,还有这么牛逼的技术。赶紧github了一把,看了几个大神的项目之后,就要自己去尝试下。还是先把感谢的链接帖下吧。
徐医生:http://mp.weixin.qq.com/s/Io9q9OT4fhkkaPGuqFs0-A 大家可关注他的微信公众号,很多的技术干活在等着你哦。
https://github.com/android10/Android-AOPExample 这是外国友人写的一个项目,我拿过来下学习。所以本篇博文只是记下笔记。
另外一个就是Jake大神的Hugo:https://github.com/JakeWharton/hugo
当我写完一个AOP的项目时,最大的感受就是,可以在任何地方,无形的插入代码。只能说牛逼。
AOP,即面向切面编程,平时的项目开发中,基本上用的是OOP面向对象开发,但是,耦合性很高。比如说,你需要在某些相同的地方加个日志,或者缓存处理等。如果需要改动,意味着每个地方都要改动,这是一个很大的工作量,但是,使用AOP的话,就完全不用担心了,write once,run everywhere。切面编程的好处就是将一些代码剥离开来,降低项目的耦合性,提高开发效率。
先上代码:
@Aspect
public class AspectTest {
private static final String TAG="MainActivity";
@Before("execution(* android.app.Activity.on**(..))")
public void onActivityMethodBefore(JoinPoint joinPoint) throws Throwable{
String key=joinPoint.getSignature().toString();
Log.d(TAG,"onActivityMethodBefore:"+key);
}
}
这个里面涉及到了Before,execution关键字,下面会讲。
Activity 里面就只有下面几句代码
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
效果截图
先自定义一个gradle插件,由于只是本地使用,不发布到网络库中。所以新建的Module的名字必须是buildsrc,然后在main目录下新建一个groovy目录,再在这个目录下新建一个包,例如:com.app.plugin。再新建一个文件,后缀名是groovy的文件。然后开始编写代码,在此贴上代码
package com.app.plugin
import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main
import org.gradle.api.Plugin
import org.gradle.api.Project
/**
* @使用ajc编译java代码 , 同 时 织 入 切 片 代 码
* 使用 AspectJ 的编译器(ajc,一个java编译器的扩展)
* 对所有受 aspect 影响的类进行织入。
* 在 gradle 的编译 task 中增加额外配置,使之能正确编译运行。
*/
public class AspectjPlugin implements Plugin<Project> {
void apply(Project project) {
project.dependencies {
compile 'org.aspectj:aspectjrt:1.8.9'
}
final def log = project.logger
log.error "========================";
log.error "Aspectj切片开始编织Class!";
log.error "========================";
project.android.applicationVariants.all { variant ->
def 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;
}
}
}
}
}
}
别忘了,在app目录下加上
apply
plugin
: com.app.plugin.AspectjPlugin
还有就是在AspectJ相关的那个module的gradle里面配置一下,具体不贴了,请访问文章末尾的链接。
AspectJ实际上是对AOP编程思想的一个实践,除了AspectJ之外,还有许多,但是目前来说,这个是最好的了
Join Points是AspectJ中最关键的一个概念。其实呢,我的理解就是程序运行时的一些执行点,比如,函数、变量等等。都可以成为Join Points。这些地方都是可以插入新的代码的,但是并不是所有地方都能给你插的。
Pointcuts,一个程序中有很多的JPoints,但是,我们怎么知道选择自己的JPoints,所以,我觉得Pointcuts是带有条件的JPoints,比如call、execution类型的JPoint.
然后就是Advice,这个理解就是怎么插入的问题,Before,After,Around几种。
项目中用的不是太多,大家可以自行试试。
最后送上链接 点击打开链接,欢迎star。