本文旨在帮助Andoird开发者快速实现AOP开发,少走弯路欢迎点赞和收藏。
网上关于AspectJ的介绍已经很多了,本文就不做过多介绍了。有兴趣的同学可以参考以下链接,感谢大神分享
自定义注解学习 : https://www.cnblogs.com/peida/archive/2013/04/26/3038503.html
AspectJ 自己去找找吧 !网上文章一堆一堆的
先简单说一下需求吧
在开发的时候,我们经常会遇到登录拦截的业务逻辑,简单说就是有些功能必须需要登录才能使用,有些功能不需要登录。在OOP 面向对象的编程开发中,我们可能需要定义一个工具类,然后在需要登录的地方做一些判断,比如:
if (LoginUtils.isLogin()){
//已经登录 处理正常逻辑
}else{
//未登录 跳转登录页面
}
这样处理起来是完全没有任何问题的,也能够达到拦截的目的,但是这样写代码耦合性太强,不够优雅,而且代码量也超多,所以下边我来简单介绍一下在Android中怎么样来使用AOP思想来实现登录拦截的逻辑。
1、 在项目的 build.gradle中添加 :
dependencies {
......
classpath 'org.aspectj:aspectjtools:1.8.10'
classpath 'org.aspectj:aspectjweaver:1.8.8'
}
2、 在app的build.gradle中添加依赖 :
dependencies {
//aop
implementation 'org.aspectj:aspectjrt:1.9.5'
}
3、还需要引入在app的build.gradle中引入以下内容 (最外层添加即可)
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 = variant.javaCompile
variant.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;
}
}
}
}
4、同步一下之后,准备撸码 :
4.1、首先我们定义一个LoginTrace的自定义注解(不了解的小童鞋自己抓紧学习)
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginTrace {
int type() default -1;
}
根据自己的业务需求来吧,当然也可以不需要添加type属性
4.2、接下来我们需要定义一个 LoginAspect 的切面,直接上代码
@Aspect
public class LoginAspect {
/**
* 对含有某个方法的特定注解打上切点
*/
@Pointcut("execution(@com.sdzte.mvparchitecture.aop.LoginTrace * *(..))")
// @Pointcut(POINTCUT_ONMETHOD)
public void pointCutLogin(){
}
/**
* 处理 特定的打上切点的方法
* @param proceedingJoinPoint
* @throws Throwable
*/
@Around("pointCutLogin()")
public void aroundLogin(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
// 这一步判断比较暴力,大家根据自己需要判断把
if (!TextUtils.isEmpty(CommonUtils.getUserToken())){
proceedingJoinPoint.proceed();
}else {
// 获得注解参数
MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
LoginTrace annotation = signature.getMethod().getAnnotation(LoginTrace.class);
int type = annotation.type();
dealWithType(type);
}
}
/**
* 在这里处理
* @param type
*/
private void dealWithType(int type){
switch (type){
case 0:
Intent intent = new Intent(MyApplication.getContext(), LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MyApplication.getContext().startActivity(intent);
break;
default:
break;
}
}
}
4.3、 经过几步简单的配置时候我们就可以愉快的玩耍了,下面是使用方法:
btnTest.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
testLogin();
}
});
......
@LoginTrace(type = 0)
public void testLogin(){
//登录之后的流程
}
5、 欢迎大家点赞和收藏,不明白的问题留言。