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添加下面依赖
dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:28.0.0' implementation 'com.android.support.constraint:constraint-layout:1.1.3' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' //使用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对象非空时运行) public Object weaveJoinPoint(ProceedingJoinPoint joinPoint) throws Throwable { Log.e("zdh", "-------------前"); 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","------------测试"); } }
//运行代码就可以看到打印日志如下
是不是很简单。
总结:1:在依赖时需要注意1.9前和1.9的SDK最低版本问题,
2:在依赖导报可以添加镜像仓看看。
3:如果使用Around注解需要返回proceed对象,要不然注解方法里面代码不执行
4:使用注解的方法一般是不会影响方法里面代码执行的,所以要考虑方法里面代码执行后的效果,
//下面以实际项目需要写个demo,一般在开发中我们有些页面是需要用户登录后才能进入的,这里面就以登录为实例写个demo
源码地址https://github.com/zhudaihao/AOP_aspectj