Android AOP概述

作者: 2c3d4f7ba0d4 | 来源:发表于2019-07-31 15:39 被阅读10次

    AOP是什么?

    网上很多人在介绍AOP时都这样说:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。个人认为这句话是错误。AOP和OOP一样,是一种程序设计思想,而非技术手段。

    程序设计有六大原则,其中第一原则就是单一职责原则。意思就是一个类只负责一件事情。这与OOP的封装特性相得益彰。在这个条件下,我们的程序会被分散到不同的类、不同的方法中去。这样做的好处是降低了类的复杂性,提高了程序的可维护性。但是同时,它也使代码变得啰嗦了。例如,我们要为方法添加调用日志,那就必须为所有类的所有方法添加日志调用,尽管它们都是相同的。为了解决上述问题,AOP应运而生了。

    AOP旨在将横切关注点与业务主体进行分类,从而提高程序代码的模块化程度。横切关注点是一个抽象的概念,它是指那些在项目中贯穿多个模块的业务。上个例子中日志功能就是一个典型的横切关注点。

    AOP的几种实现方式

    动态代理

    动态代理是一种设计模式。它有以下特征:

    • 我们不需要自己写代理类。
    • 运行期通过接口直接生成代理对象。
    • 运行期间才确定代理哪个对象。

    以下面这个例子为例,我们看一下动态代理的类图结构。

    通常我们的APP都有一部分功能要求用户登录之后才能访问。如修改密码、修改用户名等功能。当用户打算使用这些功能时,我们一般要对用户的登录状态进行判断,只有用户登录了,才能正常使用这些功能。而如果用户未登录,我们的APP要跳转到登录页。就以修改密码为例我们看一下动态代理的类图。


    InvocationHandler是Java JDK提供的动态代理的入口,用来对被代理对象的方法做处理。

    代码如下:

        public static class LoginCheckHandler implements InvocationHandler {
    
            private static <S, T extends S> T proxy(S source, Class<T> tClass) {
                return (T) Proxy.newProxyInstance(Main.class.getClassLoader(), new Class[]{tClass}, new LoginCheckHandler(source));
            }
    
            private Object mSource;
    
            LoginCheckHandler(Object source) {
                this.mSource = source;
            }
    
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                if(!checkLogin()){
                    jumpToLoginActivity();
                    return null;
                }
                return method.invoke(mSource, args);
            }
    
            private boolean checkLogin(){
                System.out.println("用户未登录");
                return false;
            }
    
            private void jumpToLoginActivity(){
                System.out.println("跳转到登录页");
            }
        }
    
        public class Client {
    
            public static void main(String[] args) {
                IUserSetting source = new UserSetting();
                IUserSetting iUserSetting = LoginCheckHandler.proxy(source,IUserSetting.class);
                iUserSetting.changePwd("new Password");
            }
        }
    

    经过这样封装之后,检查登录跳转登录页的逻辑作为横切关注点就和业务主体进行了分离。当有新的需求需要登录检查时,我们只需要通过LoginCheckHandler生成新的代理对象即可。

    APT

    APT(Annotation Processing Tool)是一种编译期注解处理技术。它通过定义注解和处理器来实现编译期生成代码的功能,并且将生成的代码和源代码一起编译成.class文件。通过APT技术,我们将横切关注点封装到注解处理器中,从而实现横切关注点与业务主体的分离。

    AspectJ

    AspectJ就是一种编译器,它在Java编译器的基础上增加了关键字识别和编译方法。因此,AspectJ可以编译Java代码。它还提供了Aspect程序。在编译期间,将开发者编写的Aspect程序织入到目标程序中,扩展目标程序的功能。开发者通过编写AspectJ程序实现AOP功能。

    Transform + Javassist/ASM

    Transform是Android Gradle提供的,可以操作字节码的一种方式。App编译时,源代码首先会被编译成class,然后再被编译成dex。在class编译成dex的过程中,会经过一系列Transform处理。Javassist/ASM是一个能够非常方便操作字节码的库。我们通过它们可以修改编译的.class文件。利用这种方式,我们将横切关注点封装到Transform,来达到与业务主体分离的目的。

    我们可以用来实现什么功能?

    利用AOP可以做一些很有意思的事情。一些知名的开源框架,他们都采用了AOP的思想。例如:ButterKnife、Retrofit、Hugo等。另外,AOP在性能检测和埋点技术上出现了百家争鸣的局面。

    除此之外,借助AOP我们还可以实现以下功能:

    • 通常我们在向服务器请求数据时,会显示一个Loding,等到结果返回后再隐藏它。我们可以通过AOP技术把显示、隐藏Loding的动作和业务主体分离开。

    • 权限管理。给大家推荐一个开源库Aopermission,用AspectJ解决了权限问题。

    相关文章

      网友评论

        本文标题:Android AOP概述

        本文链接:https://www.haomeiwen.com/subject/hxltdctx.html