AutoService源码解析

本文详细解析了AutoService的工作原理,它是一个用于自动注册注解处理器的库。通过示例展示了如何使用AutoService,以及其在编译过程中的作用。文章深入探讨了Java编译器的注解处理阶段,解释了AutoService如何在编译期间生成配置文件,以实现在运行时自动加载接口的所有实现类。总结部分强调了AutoService在组件化技术中的重要性,并预告了后续关于组件化gradle的相关内容。
摘要由CSDN通过智能技术生成

在JDK 1.5之后,java提供了对注解的支持,这些注解与普通代码一样,在运行期间发挥作用。在JDK 1.6中实现了JSR-269规范,提供了一组插入式注解处理器的标准API在编译期间对注解进行处理,可以看作是一组编译器的插件,可以读取/修改/添加抽象语法树中的任意元素。

Android模块开发之APT技术介绍了自定义注解处理器的一些知识,自定义注解处理器注册才能被Java虚拟机调用,在上面的博客第四小节中用的方法是手动注册,这比较违反程序员懒的特点,在里面也提到了自动注册的方法,就是AutoService,今天这篇博客就是来扒一扒谷歌提供的这个开源库。

先通过一个栗子看下AutoService怎么用的。

1.使用

定义一个简单的接口:

public interface Display {
    String display();
}

有两个Module A和B分别实现了这个接口,然后在app Module中调用这两个实现类, 比较低级的办法就是在app Module中直接依赖这两个模块,然后就可以调用实现类了。这有两个坏处,一个是app Module直接强依赖A和B两个Module,另外如果开发中拿不到依赖的模块呢,有可能模块是第三方的,这个时候强依赖这种方式就行不通了。

看下AutoService是怎么实现的,先看下包结构,interfaces只简单包含上面的Display接口,modulea和moduleb实现这个接口,app统一加载所有这个接口的实现类。

 

 

看下modulea和moduleb实现,方法实现里面简单返回一个字符串,主要是上面的@AutoService(Display.class)注解,注解值是接口的名称,也就是implements实现的类接口名称。

// modulea
import com.google.auto.service.AutoService;

@AutoService(Display.class)
public class ADisplay implements Display{
    @Override
    public String display() {
        return "A Display";
    }
}

// moduleb
@AutoService(Display.class)
public class BDisplay implements Display {
    @Override
    public String display() {
        return "B Display";
    }
}

再看下app Module里面的怎么调用上面的ADispaly和BDisplay,加载原理就是通过ServiceLoader去加载,可以得到接口Display的所有实现类,在我们这个栗子中就是上面的ADisplayBDisplay两个实现者。DisplayFactory通过getDisplay可以拿到所有的实现类。

import com.example.juexingzhe.interfaces.Display;

import java.util.Iterator;
import java.util.ServiceLoader;

public class DisplayFactory {
    private static DisplayFactory mDisplayFactory;

    private Iterator<Display> mIterator;

    private DisplayFactory() {
        ServiceLoader<Display> loader = ServiceLoader.load(Display.class);
        mIterator = loader.iterator();
    }

    public static DisplayFactory getSingleton() {
        if (null == mDisplayFactory) {
            synchronized (DisplayFactory.class) {
                if (null == mDisplayFactory) {
                    mDisplayFactory = new DisplayFactory();
                }
            }
        }
        return mDisplayFactory;
    }

    public Display getDisplay() {
        return mIterator.next();
    }

    public boolean hasNextDisplay() {
        return mIterator.hasNext();
    }
}

使用就是这么几个步骤,比较简单,下面看下AutoService实现原理。

2.实现原理

首先先简单介绍下Javac的编译过程,大致可以分为3个过程:

  • 解析与填充符号表
  • 插入式注解处理器的注解处理过程
  • 分析与字节码生成过程

看下一个图片,图片来源深入理解Java虚拟机,首先会进行词法和语法分析,词法分析将源代码的字符流转变为Token集合,关键字/变量名/字面量/运算符读可以成为Token,词法分析过程由com.sun.tools.javac.parserScanner类实现;

语法分析是根据Token序列构造抽象语法树的过程,抽象语法树AST是一种用来描述程序代码语法结构的树形表示,语法树的每一个节点读代表着程序代码中的一个语法结构,例如包/类型/修饰符/运算符/接口/返回值/代码注释等,在javac的源码中,语法分析

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值