2024年安卓最新AOP实现Android集中式登录架构,2024Android架构面试指南

尾声

对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。 整理的这些架构技术希望对Android开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。

最后想要拿高薪实现技术提升薪水得到质的飞跃。最快捷的方式,就是有人可以带着你一起分析,这样学习起来最为高效,所以为了大家能够顺利进阶中高级、架构师,我特地为大家准备了一套高手学习的源码和框架视频等精品Android架构师教程,保证你学了以后保证薪资上升一个台阶。

  • 思维脑图
  • 性能优化学习笔记


  • 性能优化视频

    当你有了学习线路,学习哪些内容,也知道以后的路怎么走了,理论看多了总要实践的。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

AOP实现集中式登录
  • aspectj环境搭建

首先,我们导入AspectJ的jar包,AspectJ的jar网上一搜就有,也可以直接去我demo里面拿,LoginArchitecture AOP实现集中式登录 github链接点我。demo里jar包导入: 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
好了,导入jar后还需要在app.gradle配置如下:

buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath ‘org.aspectj:aspectjtools:1.8.8’
classpath ‘org.aspectj:aspectjweaver:1.8.8’
}
}

然后在文件末尾添加如下代码:

import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main
//标注1
final def log = project.logger
final def variants = project.android.applicationVariants

variants.all { variant ->
//标注2
if (!variant.buildType.isDebuggable()) {
log.debug(“Skipping non-debuggable build type ‘${variant.buildType.name}’.”)
return;
}
//标注3
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);
//标注4
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;
}
}
}
}

关于上面这一大片代码就是对aspectj的配置,先看标注1,获取log打印工具和构建配置,然后标注2判断是否debug,如果打release把return去掉就可以,标注3处意思是使aspectj配置生效,标注4就是为了在编译时打印信息如警告、error等等,这些东西在网上也有很多,大家如果不理解,可以去搜索一下,这里不再详细解释。

  • 切面代码编写

好了,配置完上面的内容之后,我们就开始编写代码了,首先,定义一个注解LoginFilter,用来注解方法,以便在编译期被编译器检测到需要做切面的方法。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface LoginFilter {

int userDefine() default 0;

}

大家看到我在注解里加了个userDefine,就是为了给用户提供自定义实现,如根据userDifine值不同做不同的登录处理。

然后,编写LoginSDK文件用于初始化和接收登录事件,代码如下:

public class LoginSDK {

public void init(Context context, ILogin iLogin) {
applicationContext = context.getApplicationContext();
LoginAssistant.getInstance().setApplicationContext(context);
LoginAssistant.getInstance().setiLogin(iLogin);
}

//…

}

然后,新建LoginFilterAspect.java文件用来处理加入LoginFilter注解的方法,对这些方法做统一的切面处理。

@Aspect
public class LoginFilterAspect {
private static final String TAG = “LoginFilterAspect”;

@Pointcut(“execution(@com.xsm.loginarchitecture.lib_login.annotation.LoginFilter * *(…))”)
public void loginFilter() {}

@Around(“loginFilter()”)
public void aroundLoginPoint(ProceedingJoinPoint joinPoint) throws Throwable {
//标注1
ILogin iLogin = LoginAssistant.getInstance().getiLogin();
if (iLogin == null) {
throw new NoInitException(“LoginSDK 没有初始化!”);
}

//标注2
Signature signature = joinPoint.getSignature();
if (!(signature instanceof MethodSignature)) {
throw new AnnotationException(“LoginFilter 注解只能用于方法上”);
}
MethodSignature methodSignature = (MethodSignature) signature;
LoginFilter loginFilter = methodSignature.getMethod().getAnnotation(LoginFilter.class);
if (loginFilter == null) {
return;
}

Context param = LoginAssistant.getInstance().getApplicationContext();
//标注3
if (iLogin.isLogin(param)) {
joinPoint.proceed();
} else {
iLogin.login(param, loginFilter.userDefine());
}
}
}

代码并不多,我们来一一解释。首先看loginFilter方法,这个方法上加入@Pointcut注解,并指定了LoginFilter注解的路径,@Pointcut注解包括aroundLoginPoint()方法上的@Around注解等都是AspectJ定义的API。@Pointcut注解代表切入点,具体就是指哪些方法需要被执行"AOP"。execution()里指定了LoginFilter注解的路径,即加入LoginFilter注解的方法就是需要处理的切面。@Around注解表示这个方法执行时机的前后都可以做切面处理,常用到的还有@Before、@After等等。@Before即方法执行前做处理,@After反之。
好了,aroundLoginPoint(ProceedingJoinPoint joinPoint)方法就是对切面的具体实现了,这里ProceedingJoinPoint参数意为环绕通知,这个类里面可以获取到方法的签名等各种信息。

标注1

首先看标注1处,我们先获取用户实现的ILogin类,如果没有调用init()设置初始化就抛出异常。

标注2

标注2处先得到方法的签名methodSignature,然后得到@LoginFilter注解,如果注解为空,就不再往下走。

标注3

然后看标注3,调用iLogin的isLogin()方法判断是否登录,这个isLogin是留给使用者自己实现的,如果登录,就会继续执行方法体调用方法直到完成,如果没有登录,调用ilogin的login方法,并把userDefine传过去,login方法是用户自己实现的。

好了,切面代码的处理介绍完了,这个时候我们build一下项目,会在项目下\build\intermediates\classes\debug文件夹生成经过AspectJ编译器编译后的.class文件,我们看下上面例子1中的方法skip(View v)方法,编译成class文件的方法体变成了如下这样:

@LoginFilter
public void onClick(View view) {
JoinPoint var3 = Factory.makeJP(ajc t j p 0 , t h i s , t h i s , v i e w ) ; s k i p a r o u n d B o d y 1 tjp_0, this, this, view); skip_aroundBody1 tjp0,this,this,view);skiparoundBody1advice(this, view, var3, LoginFilterAspect.aspectOf(), (ProceedingJoinPoint)var3);
}
可以看到我们的点击事件方法已经被植入了一些代码,而原来startActivity(new Intent(this, SecondActivity.class));也不见了,实际上这里是把我们方法的执行给封装了,这里会在运行期,目标类加载后,为接口动态生成代理类,将切面织入到代理类中,从而实现对方法进行统一的处理。注:这里面有个小插曲,就是我在演示的时候
另外,评论中有同学提出单点登录机制处理麻烦,于是我在LoginSDK中加入后台token验证失效统一接入入口,我贴出用法:
LoginSDK.getInstance().serverTokenInvalidation(TOKEN_INVALIDATION);

最后

由于题目很多整理答案的工作量太大,所以仅限于提供知识点,详细的很多问题和参考答案我都整理成了 PDF文件

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值