欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

dagger系列之Bazel构建dagger2.29.1解说总经理(根目录下BUILD)分发的任务

程序员文章站 2022-03-09 08:03:24
前言现在我个人存在一种理念,当我感觉一件事情很难的时候(未知,困难等原因)。当你确定去解决它,了解它,分步骤解决它其实也就那么回事,这个时候只要有一个清晰的、持之以恒的思路,感觉也就那样。这个时候的难点在于找思路,摸准思路,确定思路。顺着思路去解决反而变得简单。嗯,有道理,沉思中......

前言

现在我个人存在一种理念,当我感觉一件事情很难的时候(未知,困难等原因)。当你确定去解决它,了解它,分步骤解决它其实也就那么回事,这个时候只要有一个清晰的、持之以恒的思路,感觉也就那样。这个时候的难点在于找思路,摸准思路,确定思路。顺着思路去解决反而变得简单。
嗯,有道理,沉思中
dagger系列之Bazel构建dagger2.29.1解说总经理(根目录下BUILD)分发的任务

上一篇文章
dagger系列(四)之Bazel构建dagger2.29.1解说根目录下BUILD

JSR 330标准注解

JSR-330 是 Java 的依赖注入标准。定义了如下的术语描述依赖注入:

A 类型依赖 B类型(或者说 B 被 A 依赖),则 A类型 称为”依赖(物) dependency”
运行时查找依赖的过程,称为”解析
resolving“依赖 如果找不到依赖的实例,称该依赖是”不能满足的 unsatisfied” 在”依赖注入 dependency
injection”机制中,提供依赖的工具称为”依赖注入器 dependency injector”

javax.injects 包提供了如下5个注解(Inject、Qualifier、Named、Scope、Singleton)和1个接口(Provider)。

1.@Inject

标识某个类中,需要由注入器注入的类成员(被标识的成员称为”可注入的”)。

使用规则
1.可用于注解构造器、字段、方法这些类成员(对成员是静态与否、最好是public的)
2.每个类只能有一个构造器可以被标记可注入;空构造器可以不用@Inject注解。
3.可注入的字段不能为 final 的
4.可注入的方法不能为 abstract 的

注入器的依赖注入顺序:
1.构造器 > 字段 > 方法
2.父类 > 子类
3.一个类的两个可注入字段或其他成员无注入顺序

另外的四个注解对依赖注入进一步进行配置。

2.@Qualifier 和 @Named

其中,@Qualifiery用于创建限定器。限定器是一个自定义的注解,可注解字段或方法的参数,用于限制可注入的依赖的类型。限定器注解必须被 @Qualifier 和 @Retention(RetentionPolicy.RUNTIME) 注解。

// 定义限定器
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface Big {

}

// 使用限定器
@Inject
public void foo(@ Big Bar bar) {
    // some code
}

@Named 就是一个通过 @Qualifier 定义的限定器。

3.@Scope 和 @Singleton

其中,@Scope 用于创建作用域。作用域是一个自定义的注解,可注解构造器,用于要求注入器对注入的实例的创建方式。比如,是每次构造器被调用就创建一个依赖的实例,还是就创建一个依赖的实例然后重用。作用域注解必须被 @Scope 和 @Retention(RetentionPolicy.RUNTIME) 注解。

@ Singleton 就是一个通过 @Scope 定义的作用域。

4.Provider
Provider 作为另一种提供依赖的定义(有一种是 @Inject 注解),其实例提供 T 类型的实例。与 @Inject 注解相比,其还能:

1.返回的实例可以是多个
2.返回的实例可以是延迟返回的
3.返回的实例来自指定作用域内(例如生成了一个Singleton单例类型实例,其他实例都可以引用该实例)

分经理们做了那些事情:

1.生成了dagger_with_compiler.jar,里面的内容是//java/dagger:core;并且给//java/dagger/internal/codegen:component-codegen插件提供依赖

2.生成了producers_with_compiler.jar,里面的内容包括//java/dagger/producers和dagger_with_compiler.jar里面的内容

3.生成了android.jar内容://java/dagger/android,并且给//java/dagger/android/processor:plugin插件提供依赖

4.生成android-support.jar,包含android.jar和//java/dagger/android/support

5.shaded_android_processor.jar和shaded_grpc_server_processor.jar干啥的,咱也不知道啊,咱也不敢问啊,到了再去看

6.生成了user-docs.jar,里面是Dagger依赖注入API文档信息(这个有点意思,回头我给个小案例可以对比当前的API)

那下面的工作基本上就围绕这些分经理工作了。

分经理之生成target:dagger_with_compiler过程

1.生成com.google.dagger:dagger
这里注意一点,生成的目标名称是dagger_with_compiler,但是并不一定就是dagger_with_compiler.jar(默认是这个),
根目录BUILD中的代码:

java_library(
    name = "dagger_with_compiler",
    exported_plugins = ["//java/dagger/internal/codegen:component-codegen"],
    exports = ["//java/dagger:core"],
)

首先找到java/dagger目录,再找到BUILD,打开找core:

java_library(
    name = "core",
    srcs = glob(["**/*.java"]),
    javacopts = SOURCE_7_TARGET_7 + DOCLINT_HTML_AND_SYNTAX,
    tags = ["maven_coordinates=com.google.dagger:dagger:" + POM_VERSION],
    exports = ["@google_bazel_common//third_party/java/jsr330_inject"],
    deps = [
        "@google_bazel_common//third_party/java/jsr330_inject",
    ],
)

srcs = glob(["**/*.java"]):当前目录下构建java库

javacopts = SOURCE_7_TARGET_7 + DOCLINT_HTML_AND_SYNTAX:
在根目录//:build_defs.bzl里找SOURCE_7_TARGET_7 和DOCLINT_HTML_AND_SYNTAX,POM_VERSION版本信息
这里主要是生成文档时用到

这里生成了目标core,这个也是dagger核心类,生成的引用名称为com.google.dagger:dagger:POM_VERSION,我们以dagger:2.29.1为例,看下图:
dagger系列之Bazel构建dagger2.29.1解说总经理(根目录下BUILD)分发的任务
如上图,版本号另存于META-INF文件夹下;dagger目录下文件夹internal,文件夹multibindings以及其他所有java文件,(下载dagger源码),可以查看也只有文件夹internal,文件夹multibindings目录下没有BUILD(两个文件夹里面的java文件是dagger目录下java文件的引用)

exports和deps:表示依赖于jsr330标准注解

load("//tools:maven.bzl", "pom_file")

pom_file(
    name = "pom",
    artifact_id = "dagger",
    artifact_name = "Dagger",
    targets = [":core"],
)

上面这段代码调用了tools目录下maven.bzl的pro_file,用于生成maven的pom.xml文件,如下图所示包含了groupId,artifactId等信息,核心代码 targets = [":core"]

dagger系列之Bazel构建dagger2.29.1解说总经理(根目录下BUILD)分发的任务
生成一堆java文档,目前还没看出来具体用法,目前还没有该步骤的实践

filegroup(
    name = "javadoc-srcs",
    srcs = glob(["**/*"]),
)

javadoc_library(
    name = "core-javadoc",
    srcs = [":javadoc-srcs"],
    exclude_packages = ["dagger.internal"],
    root_packages = ["dagger"],
    deps = ["@google_bazel_common//third_party/java/jsr330_inject"],
)

2.exported_plugins = ["//java/dagger/internal/codegen:component-codegen"],执行插件

该插件依赖于上面的com.google.dagger:dagger。找到java/dagger/internal/codegen的BUILD文件,再找到插件component-codegen,如下是代码,

java_plugin(
    name = "component-codegen",
    generates_api = 1,
    output_licenses = ["unencumbered"],
    processor_class = "dagger.internal.codegen.ComponentProcessor",
    tags = [
        "annotation=dagger.Component;" +
        "genclass=${package}.Dagger${outerclasses}${classname}",
        "annotation=dagger.producers.ProductionComponent;" +
        "genclass=${package}.Dagger${outerclasses}${classname}",
    ],
    deps = [":processor"],
)

总结

涉及bazel部分就这么多,反正给自己看的(有人不小心看到了也无所谓,对说的不对给予纠正,对不不了解bazel肯定可以很好的对dagger进行bazel构建部分的理解),不做深入或者太多探讨,有这些对Dagger理解足以!!!下面我就分析dagger源码了

本文地址:https://blog.csdn.net/foshengtang/article/details/109240797