AspectJ是一种严格意义上的AOP插件,因为它提供了完整的面向切面编程的注解,让使用者可以在不关心字节码原理的基础上完成代码的织入。
AspectJ实现代码织入有两种方式
- 自定编写.ajc文件
- 使用AspectJ提供的注解
两者最终都是通过ajc编译器完成代码的织入
常用语法
常用语法 | 使用 | 例子 |
---|---|---|
Join Point | 连接点,表示可织入代码的点 | Field get读取属性 Field set写入属性等 |
PointCut | 具体的切入点 | 比如调用Animal的fly方法 @Pointcut(“call(* xx.Animal.fly(…))”) |
Advice | 代码织入位置 | @ before 切入点前织入 @After 切入点后织入 |
增加登录校验
依赖参考
https://github.com/HujiangTechnology/gradle_plugin_android_aspectjx
这是一个仿照hugo的android的aspectj库。
1.新建注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface LoginCheck {
}
2.增加切面处理
@Aspect
public class LoginCheckAspect {
/**
* 切面处理的点
* * * (..) 可以处理所有的方法
*/
@Pointcut("execution(@com.xx.LoginCheck * * (..))")
public void LoginCheck() {
}
/**
* 处理切面
*/
@Around("LoginCheck()")
public void aroundLoginCheck(final ProceedingJoinPoint joinPoint) throws Throwable {
LoginCheckManager.log("aroundLoginCheck");
Signature signature = joinPoint.getSignature();
if (!(signature instanceof MemberSignature)) {
throw new RuntimeException("该注解仅用于方法");
}
if (signature == null) {
return;
}
MethodSignature methodSignature = (MethodSignature) signature;
if (methodSignature.getMethod() == null) {
return;
}
LoginCheck loginCheck = methodSignature.getMethod().getAnnotation(LoginCheck.class);
if (loginCheck == null) {
return;
}
if (!isLogin()) {
jump2Login();
} else {
joinPoint.proceed();
}
}
}
3.为需要登录判断的方法增加注解
@LoginCheck
public static void jump2SomePage() {
// xxx
}
需要注意的是,如果项目配置了混淆,需要增加混淆配置
-keepclassmembers class * {
@com.xx.LoginCheck <methods>;
}
如果内部类的方法,此混淆不支持,比如给View设置OnClick,如果给OnClick增加了注解,依旧会被混淆,所以需要配置@keep防止混淆
view.setOnClickListener(new OnClickListener() {
@Keep
@LoginCheck
@Override
public void onClick(View v) {
}
})