首页 文章 精选 留言 我的

精选列表

搜索[优化],共10000篇文章
优秀的个人博客,低调大师

RHEL 8.2 Beta 版发布:增强用户体验,优化监控和性能

作为Red Hat Enterprise Linux 8.2维护版本更新的Beta版本于昨天正式发布。 即将发布的RHEL 8.2将包含6个月的安全更新和错误修复,承诺通过为RHEL新用户和现有用户提供RHEL订阅方式来增强用户体验。这样,用户就不需要在安装更新之后执行YUM更新来确认订阅。RHEL 8.2 Beta版本允许IT管理员和企业运营团队更轻松地从RHEL 6/7进行升级,从而更好地控制其红帽企业Linux产品生命周期。 Red Hat表示:“另外,可以在安装过程中启用Red Hat Insights,这是Red Hat的主动管理分析服务,有助于使RHEL系统保持高水平运行。此功能在安装完成后立即提供Insights监视。” RHEL 8.2 Beta还引入Performance Co-Pilot(PCP)5.02,这项工具能为Microsoft SQL Server 2019带来新的收集代理,从而改善系统的整体监控和性能,并与eBPF(Extended Berkeley Packet Filter)进行了更深入的整合。 RHEL 8.2 Beta还为开发人员添加了一些新的受支持的工具,包括GCC Toolset 9.1,Python 3.8和Maven 3.6,所有这些工具都可以通过Red Hat Enterprise Linux 8中的Application Streams获得。 更多消息请查看发布说明。 稿源:cnBeta

优秀的个人博客,低调大师

开发效率优化之自动化构建系统Gradle(二)上篇

阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680 本篇文章将以下两个内容来介绍自动化构建系统Gradle: gradle 与 android gradle 插件的关系 Gradle Transform API 的基本使用 一、gradle 与 android gradle 插件的关系 1.1名词解释: 1.1.1,Gradle Gradle是一种构建工具,它使用一种基于Groovy的特定领域语言(DSL)来构建项目。不仅仅用于android 工程的构建。 1.1.2,Android Plugin for Gradle 这就是为了编译android 工程而开发的插件。下面就是申明Android Gradle 插件的位置。(build.gradle) buildscript { ... dependencies { classpath 'com.android.tools.build:gradle:2.2.0' } } 1.2 gradle 与 android gradle 1.2.1,gradle 各版本源码地址 http://services.gradle.org/distributions/ 1.2.2, google 官网 gradle 插件 与 gradle 版本对照地址 https://developer.android.google.cn/studio/releases/gradle-plugin#updating-plugin 1.2.3,gradle 版本与google gradle 插件版本的区别 在gradle wrapper.properties 中写的是 gradle 版本。 distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip 在build.gradle 中依赖的是 gradle插件版本。 dependencies { //[this is the android gradle plugin version] classpath 'com.android.tools.build:gradle:3.1.0' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } 二、Gradle Transform API 的基本使用 2.1什么是Transform 官方API文档: http://google.github.io/android-gradle-dsl/javadoc/2.1/com/android/build/api/transform/Transform.html 我们编译Android项目时,如果我们想拿到编译时产生的Class文件,并在生成Dex之前做一些处理,我们可以通过编写一个Transform来接收这些输入(编译产生的Class文件),并向已经产生的输入中添加一些东西。 我们可以通过Gradle插件来注册我们编写的Transform。注册后的Transform会被Gradle包装成一个Gradle Task,这个TransForm Task会在java compile Task执行完毕后运行。 对于编写Transform的API, 我们可以通过引入下面这个依赖来使用: compile 'com.android.tools.build:gradle:2.3.3' //版本应该在 2.x以上 先大致看一下Transform的执行流程图: 2.2 Transform的使用场景 一般我们使用Transform会有下面两种场景 我们需要对编译class文件做自定义的处理。 我们需要读取编译产生的class文件,做一些其他事情,但是不需要修改它。 接下来我们就来看一下这些Transform API吧 : 2.3 Transform API学习 我们编写一个自定义的transform需要继承Transform,它是一个抽象类, 我们这里先看一下Transform的抽象方法: public abstract class Transform { public abstract String getName(); public abstract Set<ContentType> getInputTypes(); public abstract Set<? super Scope> getScopes(); public abstract boolean isIncremental(); // 是否支持增量编译 } getName()就是指定自定义的Transform的名字。 2.4 输入的类型 Set<ContentType> getInputTypes()是指明你自定义的这个Transform处理的输入类型,输入类型共有以下几种: enum DefaultContentType implements ContentType { /** * The content is compiled Java code. This can be in a Jar file or in a folder. If * in a folder, it is expected to in sub-folders matching package names. */ CLASSES(0x01), /** * The content is standard Java resources. */ RESOURCES(0x02); } 即分为class文件或者java资源。class文件来自于jar或者文件夹。资源就是标准的java资源。 2.5 输入文件所属的范围 Scope getScopes()用来指明自定的Transform的输入文件所属的范围, 这是因为gradle是支持多工程编译的。总共有以下几种: /** * This indicates what the content represents, so that Transforms can apply to only part(s) * of the classes or resources that the build manipulates. */ enum Scope implements ScopeType { /** Only the project content */ PROJECT(0x01), //只是当前工程的代码 /** Only the project's local dependencies (local jars) */ PROJECT_LOCAL_DEPS(0x02), // 工程的本地jar /** Only the sub-projects. */ SUB_PROJECTS(0x04), // 只包含子工工程 /** Only the sub-projects's local dependencies (local jars). */ SUB_PROJECTS_LOCAL_DEPS(0x08), /** Only the external libraries */ EXTERNAL_LIBRARIES(0x10), /** Code that is being tested by the current variant, including dependencies */ TESTED_CODE(0x20), /** Local or remote dependencies that are provided-only */ PROVIDED_ONLY(0x40); } 对于getScopes()的返回,其实TransformManager已经为我们定义了一些,比如: public static final Set<Scope> SCOPE_FULL_PROJECT = Sets.immutableEnumSet( Scope.PROJECT, Scope.PROJECT_LOCAL_DEPS, Scope.SUB_PROJECTS, Scope.SUB_PROJECTS_LOCAL_DEPS, Scope.EXTERNAL_LIBRARIES); 如果一个Transform不想处理任何输入,只是想查看输入的内容,那么只需在getScopes()返回一个空集合,在getReferencedScopes()返回想要接收的范围。 public Set<? super Scope> getReferencedScopes() { return ImmutableSet.of(); } 2.6 transform() 它是Transform的关键方法: public void transform(@NonNull TransformInvocation transformInvocation) {} 它是一个空实现,input的内容将会打包成一个TransformInvocation对象,因为我们要想使用input,我们需要详细了解一下TransformInvocation参数。 2.7 TransformInvocation 我们看一下这个类相关的API: public interface TransformInvocation { Collection<TransformInput> getInputs(); // 输入作为 TransformInput 返回 TransformOutputProvider getOutputProvider(); //TransformOutputProvider 可以用来创建输出内容 boolean isIncremental(); } public interface TransformInput { Collection<JarInput> getJarInputs(); Collection<DirectoryInput> getDirectoryInputs(); } public interface JarInput extends QualifiedContent { File getFile(); //jar文件 Set<ContentType> getContentTypes(); // 是class还是resource Set<? super Scope> getScopes(); //属于Scope: } DirectoryInput与JarInput定义基本相同。 public interface TransformOutputProvider { //根据 name、ContentType、QualifiedContent.Scope返回对应的文件( jar / directory) File getContentLocation(String name, Set<QualifiedContent.ContentType> types, Set<? super QualifiedContent.Scope> scopes, Format format); } 即我们可以通过TransformInvocation来获取输入,同时也获得了输出的功能。举个例子, public void transform(TransformInvocation invocation) { for (TransformInput input : invocation.getInputs()) { input.getJarInputs().parallelStream().forEach(jarInput -> { File src = jarInput.getFile(); JarFile jarFile = new JarFile(file); Enumeration<JarEntry> entries = jarFile.entries(); while (entries.hasMoreElements()) { JarEntry entry = entries.nextElement(); //处理 } } } 上面这段代码就是获取jar的输入,然后遍历每一个jar做一些自定义的处理。 我们在做完自定义的处理后,如果想自己输出一些东西怎么办? 比如一个class文件,就可以通过TransformOutputProvider来完成。比如下面这段代码: File dest = invocation.getOutputProvider().getContentLocation("susion", TransformManager.CONTENT_CLASS, ImmutableSet.of(QualifiedContent.Scope.PROJECT), Format.DIRECTORY; 这段代码就是在本工程(ImmutableSet.of(QualifiedContent.Scope.PROJECT))下产生一个目录(Format.DIRECTORY), 目录的名字是(susion),里面的内容是TransformManager.CONTENT_CLASS。 创建这个文件夹后,我们就可以向其中写入一些内容,比如class文件。 2.8 注册Transform 我们在了解transform api后,我们可以编写一个自定义的Transform。但是我们编写的这个Transform,如何在构建过程中生效呢?我们需要注册它 在自定义插件中注册它,然后在build.gradle中apply就可以了。 //MyCustomPlgin.groovy public class MyCustomPlgin implements Plugin<Project> { @Override public void apply(Project project) { project.getExtensions().findByType(BaseExtension.class) .registerTransform(new MyCustomTransform()); } } 其实如果你包含了你编写的transform库,我们也可以直接在build.gradle中注册: //在build.gradle中也是可以直接编写 groovy代码的。 project.extensions.findByType(BaseExtension.class).registerTransform(new MyCustomTransform()); 参考:https://www.jianshu.com/p/031b62d02607https://my.oschina.net/u/592116/blog/1851743 阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680 结束语 希望读到这的您能转发分享和关注一下我,以后还会持续分享阿里P7 Android高级架构进阶知识点及解析,您的支持就是我最大的动力!!

优秀的个人博客,低调大师

开发效率优化之自动化构建系统Gradle(二)下篇

11/10号文档资料已全面更新!;《【阿里P7】移动互联网架构师进阶教程+BAT面试题》,可点击下方链接直接打开:【阿里P7】移动互联网架构师进阶高级教程+BAT面试题本篇文章将继续从自定义 Gradle 插件开发来介绍自动化构建系统Gradle: Gradle 插件简介 Gradle 插件是一个能够将 Gradle 的构建逻辑(build logic)和构建任务(build task)打包到一起,以便在多个项目的构建脚本(build.gradle)中应用(apply)的工具。 例如,build.gradle 构建脚本文件内 apply plugin: 'java' 、apply plugin: 'com.android.application' 中的 java、com.android.application 就是官方提供的 Gradle 插件,通过应用这些插件,可以丰富项目的构建任务与构建逻辑。 除官方提供的插件外,Gradle 还允许开发者定义自己的 Gradle 插件。开发者可以根据实际需求定义自己的构建逻辑和构建任务,将其打包为 Gradle 插件,从而在多个项目的构建脚本中复用。此外,还可以将自定义的 Gradle 插件发布到 plugin portal或其他仓库中,更为方便的分享给他人使用。 Gradle 插件对编程语言没有太多限制,只要是能够被编译为 JVM 字节码的编程语言,都能用来编写 Gradle 插件。Gradle-API 的被设计为对 Groovy、Java、Koltin 友好的,通常情况下,使用 Java 或 Kotlin 这类静态类型语言实现的 Gradle 插件的性能要比使用 Groovy 实现的相同常见的性能更好。 [](http://geek5nan.github.io/2019/09/07/Developing-Gradle-Plugin-1/#开始之前 "开始之前")开始之前 Gradle 作为一个普通的构建工具,本身并不依赖任何可视化 GUI 工具。为简化步骤,本文将采用命令行方式来完成自定义 Gradle 插件的演示。在开始之前,需先将 gradle 命令添加到系统环境变量中。 若读者在 IDEA / Android Studio 使用过 gradle ,则可在当前用户目录下找到 gradle 命令,具体路径如下 Mac:/Users/当前用户名/.gradle/wrapper/dists/gradle版本/沙盒路径/gradle版本/bin Win:C:\Users\当前用户名\.gradle\wrapper\dists\gradle版本\沙盒路径\gradle版本\bin 若读者的电脑中尚未安装 gradle,则可在 Gradle 官方 下载安装。 以笔者使用的环境为例,gradle 命令所在目录为 ~/.gradle/wrapper/dists/gradle-5.4.1-all/3221gyojl5jsh0helicew7rwx/gradle-5.4.1/bin 将 gradle 命令所在目录添加到环境变量中 Mac:在 ~/.bashrc 中添加 export PATH=~/.gradle/wrapper/dists/gradle-5.4.1-all/3221gyojl5jsh0helicew7rwx/gradle-5.4.1/bin:$PATH Win:在系统环境变量中添加 C:\Users\用户名\.gradle\wrapper\dists\gradle-5.4.1-all\805usxkvhgx6e1wbo8o64g0tx\gradle-5.6.1\bin [](http://geek5nan.github.io/2019/09/07/Developing-Gradle-Plugin-1/#牛刀小试 "牛刀小试")牛刀小试 在命令行中输入 gradle --version 得到如下输出则表示 gradle 环境设置成功 ------------------------------------------------------------ Gradle 5.4.1 ------------------------------------------------------------ Build time: 2019-04-26 08:14:42 UTC Revision: 261d171646b36a6a28d5a19a69676cd098a4c19d Kotlin: 1.3.21 Groovy: 2.5.4 Ant: Apache Ant(TM) version 1.9.13 compiled on July 10 2018 JVM: 1.8.0_171 (Oracle Corporation 25.171-b11) OS: Mac OS X 10.14.6 x86_64 [](http://geek5nan.github.io/2019/09/07/Developing-Gradle-Plugin-1/#自定义-Gradle-插件 "自定义 Gradle 插件")自定义 Gradle 插件 自定义 gradle 插件可以在以下三个地方创建,分别是: 构建脚本内 buildSrc 模块内 单独项目 [](http://geek5nan.github.io/2019/09/07/Developing-Gradle-Plugin-1/#构建脚本内建方式 "构建脚本内建方式")构建脚本内建方式 在 build.gradle 内直接创建 Gradle 插件 优点: build.gradle 中创建的插件将被自动编译并包含在 classpath 中,使用时无需在构建脚本内指定 classpath 缺点: 此插件仅在当前构建脚本中有效,对外部文件不可见,无法在当前构建脚本以外的其他地方复用此插件 示例 [](http://geek5nan.github.io/2019/09/07/Developing-Gradle-Plugin-1/#1-创建-BuildInDemo-目录 "1.创建 BuildInDemo 目录")1. 创建 BuildInDemo 目录 mkdir BuildInDemo [](http://geek5nan.github.io/2019/09/07/Developing-Gradle-Plugin-1/#2-在BuildInDemo目录内中新建-build-gradle-文件 "2.在BuildInDemo目录内中新建 build.gradle 文件")2. 在 BuildInDemo 目录内中新建 build.gradle 文件 cd BuildInDemo touch build.gradle 使用 tree 命令查看创建后的目录结构,如下所示 BuildInDemo . └── build.gradle 0 directories, 1 file [](http://geek5nan.github.io/2019/09/07/Developing-Gradle-Plugin-1/#3-在-BuildInDemo-build-gradle-内创建并应用-Gradle-插件,代码如下 "3.在 BuildInDemo/build.gradle 内创建并应用 Gradle 插件,代码如下")3. 在 BuildInDemo/build.gradle 内创建并应用 Gradle 插件,代码如下 // 1. 创建插件 BuildInPlugin class BuildInPlugin implements Plugin<Project> { // 2. 应用插件时执行此函数 @Override void apply(Project target) { println("hello form build-in plugin") } } //3. 应用插件 apply plugin: BuildInPlugin // 2\. 应用插件时执行此函数 @Override void apply(Project target) { println("hello form build-in plugin") } } //3\. 应用插件 apply plugin: BuildInPlugin [](http://geek5nan.github.io/2019/09/07/Developing-Gradle-Plugin-1/#4-构建此-build-gradle-文件 "4.构建此 build.gradle 文件")4. 构建此 build.gradle 文件 gradle build Gradle 构建时将执行 build.gradle 中的代码,当执行到 apply plugin: BuildInPlugin 时,将会调用 BuildInPlugin 的实例方法 apply(Project p)。因此在构建过程中,可以看到如下输出,其中第 2 行即为上一步自定义插件中打印的内容,表明插件应用成功 > Configure project : hello form build-in plugin > Task :buildEnvironment ------------------------------------------------------------ Root project ------------------------------------------------------------ classpath No dependencies A web-based, searchable dependency report is available by adding the --scan option. BUILD SUCCESSFUL in 0s 1 actionable task: 1 executed [](http://geek5nan.github.io/2019/09/07/Developing-Gradle-Plugin-1/#buildSrc-模块方式 "buildSrc 模块方式")buildSrc 模块方式 rootProject/buildSrc 文件夹是 Gradle 的预留目录,用来存放当前项目私有 Gradle 插件的源代码与构建脚本 优点: 项目构建时,Gradle 会自动编译项目目录下的 buildSrc 文件夹下的构建脚本和源码,并将其添加到项目构建脚本的 classpath 中,因此在使用 buildSrc 中创建的插件时,无需再手动指定 classpath buildSrc 文件夹中构建脚本和 Gradle 插件同一项目均可见,因此同一项目中的其他模块也可以使用 buildSrc 中创建的插件 缺点: 此处创建的插件对外部项目不可见,无法在其他项目中复用 示例 [](http://geek5nan.github.io/2019/09/07/Developing-Gradle-Plugin-1/#1-创建-PluginBuildSrcDemo-项目模块 "1. 创建 PluginBuildSrcDemo 项目模块")1. 创建 PluginBuildSrcDemo 项目模块 创建 PluginBuildSrcDemo 目录,并在该目录下创建 build.gradle 文件 mkdir PluginBuildSrcDemo && cd PluginBuildSrcDemo && touch build.gradle [](http://geek5nan.github.io/2019/09/07/Developing-Gradle-Plugin-1/#2-创建-buildSrc-子模块 "2. 创建 buildSrc 子模块")2. 创建 buildSrc 子模块 [](http://geek5nan.github.io/2019/09/07/Developing-Gradle-Plugin-1/#2-1-在-PluginBuildSrcDemo-目录下创建buildSrc目录 "2.1 在 PluginBuildSrcDemo 目录下创建buildSrc目录")2.1 在 PluginBuildSrcDemo 目录下创建 buildSrc 目录 mkdir buildSrc [](http://geek5nan.github.io/2019/09/07/Developing-Gradle-Plugin-1/#2-2-在-PluginBuildSrcDemo-buildSrc-目录下创建-buildSrc-子模块的构建脚本文件-build-gradle "2.2 在 PluginBuildSrcDemo/buildSrc 目录下创建 buildSrc 子模块的构建脚本文件 build.gradle")2.2 在 PluginBuildSrcDemo/buildSrc 目录下创建 buildSrc 子模块的构建脚本文件 build.gradle cd buildSrc touch build.gradle PluginBuildSrcDemo/buildSrc/build.gradle 的内容如下 // 使用 plugins 块语法应用插件 plugins { // 应用 kotlin 插件 id 'org.jetbrains.kotlin.jvm' version '1.3.50' } dependencies { // 仅在编译时使用 Grdale-API 依赖 compileOnly gradleApi() // 在插件源码中添加 kotlin 标准库依赖 implementation 'org.jetbrains.kotlin:kotlin-stdlib' } [](http://geek5nan.github.io/2019/09/07/Developing-Gradle-Plugin-1/#2-3-创建-buildSrc-模块的源码目录 "2.3 创建 buildSrc 模块的源码目录")2.3 创建 buildSrc 模块的源码目录 cd PluginBuildSrcDemo/buildSrc mkdir -p /src/main/kotlin/com/example/plugin [](http://geek5nan.github.io/2019/09/07/Developing-Gradle-Plugin-1/#2-4-创建插件文件PluginBuildSrc-kt "2.4 创建插件文件PluginBuildSrc.kt")2.4 创建插件文件 PluginBuildSrc.kt cd PluginBuildSrcDemo/buildSrc/src/main/kotlin/com/example/plugin touch PluginBuildSrc.kt PluginBuildSrc.kt 的代码如下 package com.example.plugin import org.gradle.api.Plugin import org.gradle.api.Project class PluginBuildSrc : Plugin<Project> { override fun apply(target: Project) { println("hello from buildSrc plugin") } } [](http://geek5nan.github.io/2019/09/07/Developing-Gradle-Plugin-1/#2-5-声明-Gradle-插件的-ID-与实现类 "2.5 声明 Gradle 插件的 ID 与实现类")2.5 声明 Gradle 插件的 ID 与实现类 此步骤是可选的:若使用插件 ID 形式应用自定义插件,则必须进行此步骤;若使用插件实现类的形式应用自定义插件,则可跳过此步骤。 完成此步骤的方式有两种,任选其一即可 [](http://geek5nan.github.io/2019/09/07/Developing-Gradle-Plugin-1/#方式1-META-INF-方式 "方式1. META-INF 方式")方式 1. META-INF 方式 创建 PluginBuildSrcDemo/buildSrc/src/main/resources/META-INF/gradle-plugins 目录 cd PluginBuildSrcDemo/buildSrc mkdir -p src/main/resources/META-INF/gradle-plugins 在 gradle-plugins 目录下创建 com.example.plugin.properties 属性文件,红色部分表示插件的 ID cd src/main/resources/META-INF/gradle-plugins touch com.example.plugin.properties 属性文件的内容如下,表示插件 ID 为 com.example.plugin 的插件所对应的实现类为 com.example.plugin.PluginBuildSrc implementations-class=com.example.plugin.PluginBuildSrc [](http://geek5nan.github.io/2019/09/07/Developing-Gradle-Plugin-1/#方式2-java-gradle-plugin-插件方式 "方式2. java-gradle-plugin 插件方式")方式 2. java-gradle-plugin 插件方式 java-gradle-plugin 是一个用于开发 Gradle 插件的辅助插件,它内置了很多辅助功能: 为宿主模块添加 gradlePlugin 配置块,可在此处配置插件的 ID 和实现类 为宿主模块添加 complile gradleApi() 依赖 etc… 此处我们主要使用 gradlePlugin 配置块代替 META-INF 目录下的属性文件。java-gradle-plugin 的使用方式非常简单,只需在 PluginBuildSrcDemo/buildSrc/build.gradle 构建脚本文件中简单配置即可,如下所示。 plugins { id 'org.jetbrains.kotlin.jvm' version '1.3.50' + //1. 应用 java-gradle-plugin 插件 + id 'java-gradle-plugin' } dependencies { - compileOnly gradleApi() // java-gradle-plugin 插件已为宿主添加 gradleApi 依赖,此行可移除 implementation 'org.jetbrains.kotlin:kotlin-stdlib' } + //2. 添加 gradlePlugin 配置块信息 + gradlePlugin { + plugins{ + // 此处的 tag 可以为任意名称 + tag1{ + id = 'com.example.plugin.buildsrc' //自定义插件的 ID + implementationClass = 'com.example.plugin.PluginBuildSrc' //自定义插件的实现类 + } + } + } 此时在 PluginBuildSrcDemo 目录下使用 tree 命令,可以看到当前的目录结构如下 PluginBuildSrcDemo . ├── build.gradle ├── buildSrc │ ├── build.gradle │ └── src │ └── main │ └── kotlin │ └── com │ └── example │ └── plugin │ └── PluginBuildSrc.kt 7 directories, 3 files [](http://geek5nan.github.io/2019/09/07/Developing-Gradle-Plugin-1/#3-在-PruginBuildSrcDemo-项目模块中应用-buildSrc-中声明的-Gradle-插件 "3. 在 PruginBuildSrcDemo 项目模块中应用 buildSrc 中声明的 Gradle 插件")3. 在 PruginBuildSrcDemo 项目模块中应用 buildSrc 中声明的 Gradle 插件 在 PluginBuildSrcDemo/build.gradle 构建脚本文件中添加如下代码 //apply plugin: '插件 ID' apply plugin: 'com.example.plugin' //apply plugin: 实现类 //apply plugin: com.example.plugin.PluginBuildSrc 应用插件时,指定插件 ID 或指定插件的实现类都可以,但指定插件 ID 的形式更为简短及灵活,在实际开发中也更为常见。 在 PluginBuildSrcDemo 目录下执行 gradle build 命令进行构建,可看到如下输出 > Configure project : hello from buildSrc plugin > Task :buildEnvironment ------------------------------------------------------------ Root project ------------------------------------------------------------ classpath No dependencies A web-based, searchable dependency report is available by adding the --scan option. BUILD SUCCESSFUL in 3s 1 actionable task: 1 executed 其中第 2 行是我们在 buildSrc 模块中定义的 Gradle 插件所打印日志,表明 buildSrc 模块 中的自定义插件在根项目中已生效。 [](http://geek5nan.github.io/2019/09/07/Developing-Gradle-Plugin-1/#4-创建-SubModule-子模块 "4. 创建 SubModule 子模块")4. 创建 SubModule 子模块 buildSrc 模块中定义的插件可以在同一项目的任意模块的构建脚本中使用,接下来便演示在 SubModule 子模块中的应用。 [](http://geek5nan.github.io/2019/09/07/Developing-Gradle-Plugin-1/#4-1-创建-SubModule-目录与构建脚本 "4.1 创建 SubModule 目录与构建脚本")4.1 创建 SubModule 目录与构建脚本 // 1. 在 PluginBuildSrcDemo 目录下创建 SubModule 目录 cd PluginBuildSrcDemo && mkdir SubModule // 2. 在 SubModule 目录下新建 gradle 构建脚本 cd SubModule touch build.gralde PluginBuildSrcDemo/SubModule/build.gradle 的内容如下 apply plugin: 'com.example.plugin' [](http://geek5nan.github.io/2019/09/07/Developing-Gradle-Plugin-1/#4-2-将-SubModule-模块关联到-PluginBuildSrcDemo-项目中 "4.2 将 SubModule 模块关联到 PluginBuildSrcDemo 项目中")4.2 将 SubModule 模块关联到 PluginBuildSrcDemo 项目中 在 PluginBuildSrcDemo 目录下新建 settings.gradle 文件,内容如下 // 将SubModule 子模块添加到 PluginBuildSrcDemo 项目模块中 include ':SubModule' 此时在 PluginBuildSrcDemo 目录下使用 tree 命令,可以看到项目当前的目录结构如下 PluginBuildSrcDemo . ├── SubModule │ └── build.gradle ├── build.gradle ├── buildSrc │ ├── build.gradle │ └── src │ └── main │ └── kotlin │ └── com │ └── example │ └── plugin │ └── PluginBuildSrc.kt └── settings.gradle [](http://geek5nan.github.io/2019/09/07/Developing-Gradle-Plugin-1/#5-在-SubModule-模块执行构建命令 "5. 在 SubModule 模块执行构建命令")5. 在 SubModule 模块执行构建命令 cd PluginBuildSrcDemo/SubModule gradle build 得到如下输出 > Configure project :SubModule hello from buildSrc plugin > Task :SubModule:buildEnvironment ------------------------------------------------------------ Project :SubModule ------------------------------------------------------------ classpath No dependencies A web-based, searchable dependency report is available by adding the --scan option. BUILD SUCCESSFUL in 0s 1 actionable task: 1 executed [](http://geek5nan.github.io/2019/09/07/Developing-Gradle-Plugin-1/#独立项目方式 "独立项目方式")独立项目方式 采用 buildSrc 模块方式时,Gradle 会妥善处理 buildSrc 模块的构建脚本与源码,并将其添加到当前项目的 classpath 中。但 buildSrc 方式的插件只能在项目内共享与复用,若要在其他项目中使用该插件,还需要再进行下列操作 将插件发布到 maven 仓库(任意仓库) 在需要应用该插件的构建脚本中的 repository 部分添加该插件所在的 maven 仓库 在需要应用该插件的构建脚本中的 classpath 部分添加该插件对应的 maven 坐标 (group : id : version) 因为是在其他项目中使用该项目 buildSrc 模块 中的自定义 Gradle 插件,所以 Gradle 的 buildSrc 保留目录优势不再。如果将模块名由 buildSrc 修改为其他名称,则可将其称为独立的 Gradle 插件模块。 在本小节中,我们主要学习 gradle 插件的发布与使用。 [](http://geek5nan.github.io/2019/09/07/Developing-Gradle-Plugin-1/#1-创建-gradle-插件项目 "1. 创建 gradle 插件项目")1. 创建 gradle 插件项目 与 buildSrc 方式相同,先创建构建脚本与自定义插件类 mkdir StandaloneDemo cd StandaloneDemo touch build.gradle mkdir src/main/kotlin/com/example/plugin touch src/main/kotlin/com/example/plugin/StandalonePlugin.kt StandaloneDemo/build.gradle 的内容如下 plugins { id 'org.jetbrains.kotlin.jvm' version '1.3.50' id 'java-gradle-plugin' } gradlePlugin{ plugins{ sometag{ id = 'com.example.plugin' implementationClass = 'com.example.plugin.StandalonePlugin' } } } StandaloneDemo/src/main/kotlin/com/example/plugin/StandalonePlugin.kt 的内容如下 package com.example.plugin import org.gradle.api.Plugin import org.gradle.api.Project class StandalonePlugin : Plugin<Project> { override fun apply(target: Project) { println("hello from standalone plugin") } } [](http://geek5nan.github.io/2019/09/07/Developing-Gradle-Plugin-1/#2-将-gradle-插件发布到-maven-仓库 "2. 将 gradle 插件发布到 maven 仓库")2. 将 gradle 插件发布到 maven 仓库 [](http://geek5nan.github.io/2019/09/07/Developing-Gradle-Plugin-1/#2-1-在StandaloneDemo-build-gradle-文件中配置发布信息 "2.1 在StandaloneDemo/build.gradle 文件中配置发布信息")2.1 在 StandaloneDemo/build.gradle 文件中配置发布信息 使用 maven-publish 插件将自定义插件发布到本地 maven 仓库中,如下所示 plugins { id 'org.jetbrains.kotlin.jvm' version '1.3.50' id 'java-gradle-plugin' + //1. 应用 maven-publish 插件 + id 'maven-publish' } gradlePlugin{ plugins{ sometag{ id = 'com.example.plugin' implementationClass = 'com.example.plugin.StandalonePlugin' } } } +//2. 设置发布相关配置 +publishing { + publications { + //3. 将插件发布到 maven 仓库 + maven(MavenPublication) { + //4. 设置插件的 maven 坐标 + groupId 'com.example'//组织 ID + artifactId 'plugin' //制品 ID + version 'snapshot' //制品版本 + from components.kotlin + } + } + //5. 设置发布仓库 + repositories { + // 6. 发布到本地 maven 仓库 + mavenLocal() + } +} [](http://geek5nan.github.io/2019/09/07/Developing-Gradle-Plugin-1/#2-2-使用-publishMavenPublicationToMavenLocal-任务将插件发布到本地仓库 "2.2 使用 publishMavenPublicationToMavenLocal 任务将插件发布到本地仓库")2.2 使用 publishMavenPublicationToMavenLocal 任务将插件发布到本地仓库 cd StandaloneDemo gradle publishMavenPublicationToMavenLocal 执行以上命令后,gradle 会把 StandaloneDemo 中的代码编译打包后发布到本地 maven 仓库中,本地 maven 仓库通常存放于当前用户目录下,具体路径为 Mac: ~/.m2/repository Win:C:\Users\当前用户名\.m2\repository 我们可以在此目录下看到刚刚发布的插件,如下图所示 [](http://geek5nan.github.io/2019/09/07/Developing-Gradle-Plugin-1/#3-在其他项目中使用本地-maven-仓库中的-gradle-插件 "3. 在其他项目中使用本地 maven 仓库中的 gradle 插件")3. 在其他项目中使用本地 maven 仓库中的 gradle 插件 [](http://geek5nan.github.io/2019/09/07/Developing-Gradle-Plugin-1/#3-1-新建-OtherProject项目 "3.1 新建 OtherProject项目")3.1 新建 OtherProject 项目 mkdir OtherProject cd OtherProject touch build.gradle build.gradle 的文件内容如下,相比 buildSrc 方式,应用时多了 11 行的 buildscript 相关的配置信息。 +buildscript { + repositories { + //1. 为当前构建脚本添加插件所在的 maven 仓库,本例中为 maven 本地仓库 + mavenLocal() + } + dependencies { + //2. 为当前构建脚本添加如下依赖 + //`com.exaple`、`plugin`、`snapshot` 是在上一步中设置的 maven 三维坐标 + classpath 'com.example:plugin:snapshot' + } +} //3. 应用独立插件项目中的自定义插件 // apply plugin: '插件 ID' apply plugin: 'com.example.plugin' [](http://geek5nan.github.io/2019/09/07/Developing-Gradle-Plugin-1/#3-2-构建-OtherProject-项目 "3.2 构建 OtherProject 项目")3.2 构建 OtherProject 项目 cd OtherProject gradle build 输入以上命令,得到如下输出 > Configure project : hello from standalone plugin > Task :buildEnvironment ------------------------------------------------------------ Root project ------------------------------------------------------------ classpath \--- com.example:plugin:snapshot A web-based, searchable dependency report is available by adding the --scan option. BUILD SUCCESSFUL in 0s 1 actionable task: 1 executed [](http://geek5nan.github.io/2019/09/07/Developing-Gradle-Plugin-1/#小结 "小结")小结 本文演示了 gradle 插件的三种创建方式,相关代码已上传至 github 中,点此即可查看。行文匆忙难免疏忽,如有遗漏还请斧正。 本文作者: Geek5Nan 本文链接: http://geek5nan.github.io/2019/09/07/Developing-Gradle-Plugin-1/") 最后 我们今年整理了一份阿里P7级别的Android架构师全套学习资料,特别适合有3-5年以上经验的小伙伴深入学习提升。 主要包括腾讯,以及字节跳动,华为,小米,等一线互联网公司主流架构技术。如果你有需要,尽管拿走好了。 以下为我整理的资料免费分享;【阿里P7】Android高级教程+BAT面试题 1.Android高级技术脑图 2.P7级Android高级架构视频教程 3.Android核心高级技术PDF文档+BAT大厂面试真题解析 4.Android思维脑图(技能树) 1.Android高级技术脑图; 查漏补缺,体系化深入学习提升 2.【Android高级架构视频教程】; 全套部分展示; java与Android内核进阶专题视频与源码 阿里P7级全套高级学习视频; 3.Android核心高级技术PDF文档,BAT大厂面试真题解析 4.Android思维脑图(技能树) 免费分享 【阿里P7】移动互联网架构师进阶高级教程+BAT面试题 为什么免费分享? 我的目的是让更多需要的Android开发朋友能够提升自己的技术水平无论是Android,还是qq,微信,360等,想在互联网上最大程度推广,就必须免费!如果我的学习资料对你有帮助,点个赞,谢谢!

优秀的个人博客,低调大师

综合代理 sps 多项优化

Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5代理服务器,支持正向代理、反向代理、透明代理、内网穿透、TCP/UDP端口映射、SSH中转、TLS加密传输、协议转换、DNS防污染智能代理、前置CDN/Nginx反代、代理连接重定向。 更新内容: sps:增加了 --hosts 参数,格式是:domain@IP,domain@IP。 更新了内置证书。 另外预告一下,可以运行在Linux,Windows,macOS,arm上的全功能proxy管理面板即将发布,先睹为快: 特点: 链式代理,程序本身可以作为一级代理,如果设置了上级代理那么可以作为二级代理,乃至N级代理. 通讯加密,如果程序不是一级代理,而且上级代理也是本程序,那么可以加密和上级代理之间的通讯,采用底层tls高强度加密,安全无特征. 智能HTTP,SOCKS5代理,会自动判断访问的网站是否屏蔽,如果被屏蔽那么就会使用上级代理(前提是配置了上级代理)访问网站;如果访问的网站没有被屏蔽,为了加速访问,代理会直接访问网站,不使用上级代理. 域名黑白名单,更加自由的控制网站的访问方式。 跨平台性,无论你是widows,linux,还是mac,甚至是树莓派,都可以很好的运行proxy. 多协议支持,支持HTTP(S),TCP,UDP,Websocket,SOCKS5代理. TCP/UDP端口转发. 支持内网穿透,协议支持TCP和UDP. SSH中转,HTTP(S),SOCKS5代理支持SSH中转,上级Linux服务器不需要任何服务端,本地一个proxy即可开心上网. KCP协议支持,HTTP(S),SOCKS5代理支持KCP协议传输数据,降低延迟,提升浏览体验. 集成外部API,HTTP(S),SOCKS5代理认证功能可以与外部HTTP API集成,可以方便的通过外部系统控制代理用户. 反向代理,支持直接把域名解析到proxy监听的ip,然后proxy就会帮你代理访问需要访问的HTTP(S)网站. 透明HTTP(S)代理,配合iptables,在网关直接把出去的80,443方向的流量转发到proxy,就能实现无感知的智能路由器代理. 协议转换,可以把已经存在的HTTP(S)或SOCKS5或SS代理转换为一个端口同时支持HTTP(S)和SOCKS5和SS代理,转换后的SOCKS5和SS代理如果上级是SOCKS5代理,那么支持UDP功能,同时支持强大的级联认证功能。 自定义底层加密传输,http(s)\sps\socks代理在tcp之上可以通过tls标准加密以及kcp协议加密tcp数据,除此之外还支持在tls和kcp之后进行自定义加密,也就是说自定义加密和tls|kcp是可以联合使用的,内部采用AES256加密,使用的时候只需要自己定义一个密码即可。 底层压缩高效传输,http(s)\sps\socks代理在tcp之上可以通过自定义加密和tls标准加密以及kcp协议加密tcp数据,在加密之后还可以对数据进行压缩,也就是说压缩功能和自定义加密和tls|kcp是可以联合使用的。 安全的DNS代理,可以通过本地的proxy提供的DNS代理服务器与上级代理加密通讯实现安全防污染的DNS查询。 负载均衡,高可用,HTTP(S)\SOCKS5\SPS代理支持上级负载均衡和高可用,多个上级重复-P参数即可. 指定出口IP,HTTP(S)\SOCKS5\SPS代理支持客户端用入口IP连接过来的,就用入口IP作为出口IP访问目标网站的功能。如果入口IP是内网IP,出口IP不会使用入口IP 支持限速,HTTP(S)\SOCKS5\SPS代理支持限速. SOCKS5代理支持级联认证. 证书参数使用base64数据,默认情况下-C,-K参数是crt证书和key文件的路径,如果是base64://开头,那么就认为后面的数据是base64编码的,会解码后使用. 下载地址: Gitee GAYHUB

优秀的个人博客,低调大师

蚂蚁金服服务注册中心 SOFARegistry 解析 | 服务发现优化之路

SOFAStackScalableOpenFinancialArchitecture Stack 是蚂蚁金服自主研发的金融级分布式架构,包含了构建金融级云原生架构所需的各个组件,是在金融场景里锤炼出来的最佳实践。 SOFARegistry 是蚂蚁金服开源的具有承载海量服务注册和订阅能力的、高可用的服务注册中心,最早源自于淘宝的初版 ConfigServer,在支付宝/蚂蚁金服的业务发展驱动下,近十年间已经演进至第五代。 本文为《剖析 | SOFARegistry 框架》第二篇,本篇作者尚彧,是 SOFARegistry 开源负责人。《剖析 | SOFARegistry 框架》系列由 SOFA 团队和源码爱好者们出品,项目代号:SOFA:RegistryLab/,文末附共建列表,欢迎领取共建~ GitHub 地址:https://

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册