java最火构建工具Gradle命令行黑魔法

作者:小菜 更新时间:2025-02-07 点击数:
简介:前往java软件专题 毫无疑问,现在Gradle已经成为java世界最火的构建工具,风头已经盖过了冗余的ant,落后的maven。

Gradle是以Groovy

【菜科解读】

前往java软件专题

毫无疑问,现在Gradle已经成为java世界最火的构建工具,风头已经盖过了冗余的ant,落后的maven。

Gradle是以Groovy语言编写的一套构建脚本的DSL,由于Groovy语法的优雅,所以导致Gradle天生就有简洁、可读性强、灵活等特性。

Gradle的命令行功能也非常强大。

本人从maven转到Gradle,深深被gradle强大的命令行功能折服。

通过命令行来实现Gradle的各种特性,就像魔法师在表演魔法一样。

日志输出。

Gradle中的日期有6个层级。

从高到低分别是 ERROR(错误信息)、QUIET(重要信息)、WARNGING(警告信息)、LIFECYCLE(进程信息)、INFO(一般信息)、DEBUG(调试信息)。

在执行gradle task时可以适时的调整信息输出等级,以便更方便的观看执行结果。

比如一个build.gradle有这样一个task

1task hello

加入-q与不加-q的输出结果不同。

1$ gradle hello:hellohello world!BUILD SUCCESSFULTotal time: 3.546 secs$ gradle -q hellohello world!

堆栈跟踪。

如果执行gradle task失败时,如果想得到更详细的错误信息,那么就可以使用-s(或--stacktrace)来输出详细的错误堆栈。

你还可以使用-S(或--full-stacktrace)来输出全部堆栈信息,不过一般不推荐这样做,因为gradle是基于groovy语言,而groovy作为一门动态语言可能会输出与你的错误代码毫不相关的信息。

跳过指定的测试。

如果你在执行build的时候想跳过test task,那么可以使用-x命令。

1$ gradle build -x test:compileJava UP-TO-DATE:processResources UP-TO-DATE:classes UP-TO-DATE:jar UP-TO-DATE:assemble UP-TO-DATE:check:buildBUILD SUCCESSFULTotal time: 3.529 secs

继续执行task而忽略前面失败的task。

默认情况下,如果有某个task失败,后续的task就不会继续执行。

但是有时候我们想运行所有的task来一次性得到所有的构建错误,那么我们可以使用--continue命令。

使用--continue命令后即使遇到某些task失败也不会停止后续task的执行。

但是需要注意的是如果某个task失败了,那么依赖于这个task的其他task依旧不会执行,因为这会带来不安全的因素。

调用task时使用短名或缩写。

如果一个task的名称过程,那么调用时可以只输入部分名称即可调用,无需输入全名。

1task helloWorld

比如调用helloWorld可以通过全名调用、前缀调用或首字母调用。

1$ gradle -q helloWorldhello world!$ gradle -q hellhello world!$ gradle -q hWhello world!

使用指定的gradle文件调用task。

默认情况下,如果你调用gradle task,那么首先会寻找当前目录下的build.gradle文件,以及根据settings.gradle中的配置寻找子项目的build.gradle。

但是有时候我们想指定使用某个gradle文件,那么可以使用-b命令。

比如当前目录有个子目录subproject1,里面有个叫hello.gradle。

subproject1/hello.gradle

1task helloWorld

那么在当前目录可以使用以下命令调用这个task。

1$ gradle -b subproject1/hello.gradle helloWorld:helloWorldhello world!BUILD SUCCESSFULTotal time: 3.752 secs

使用指定的项目目录调用task。

前面已经说过,执行gradle的task默认会在当前目录寻找build.gradle及settings.gradle文件。

如果我们想在任何地方执行某个项目的task,那么可以使用-p来指定使用的项目。

1gradle -q -b learnGradle helloWorld

这条命令是调用learnGradle这个项目下的helloWorld task。

显示task之间的依赖关系。

众所周知,使用gradle tasks可以列出当前所有可被使用的task,但是并没有显示task之间的依赖关系。

我们可以加上--all来显示 task的依赖关系。

1$ gradle tasks --all………………Other tasks-----------task0 task1 task2 task3从上面可以看出task0依赖task1、task2及task3。

查看指定阶段的依赖关系。

使用gradle dependencies可以查看项目中包的依赖关系。

不过是列出了所有阶段的依赖,如果项目中依赖复杂的话看起来有点头痛。

那么可以使用--configuration来查看指定阶段的依赖情况。

1$ gradle -q dependencies------------------------------------------------------------Root project------------------------------------------------------------archives - Configuration for archive artifacts.No dependenciescompile - Compile classpath for source set 'main'.No dependenciesdefault - Configuration for default artifacts.No dependenciesruntime - Runtime classpath for source set 'main'.No dependenciestestCompile - Compile classpath for source set 'test'.\--- junit:junit:4.11 \--- org.hamcrest:hamcrest-core:1.3testRuntime - Runtime classpath for source set 'test'.\--- junit:junit:4.11 \--- org.hamcrest:hamcrest-core:1.3

使用gradle -q dependencies --configuration testCompile可以只查看testComiple的依赖。

1$ gradle -q dependencies --configuration testCompile------------------------------------------------------------Root project------------------------------------------------------------testCompile - Compile classpath for source set 'test'.\--- junit:junit:4.11 \--- org.hamcrest:hamcrest-core:1.3

查看指定dependency的依赖情况。

假如我想查看项目中有没有引入junit,那些阶段引入了junit,那么可以使用dependecyInsight来查看。

1$ gradle dependencyInsight --dependency junit --configuration testCompile:dependencyInsightjunit:junit:4.11\--- testCompile

注意dependencyInsight默认只会查看compile阶段的依赖,如果要查看其他阶段可以使用--configuration来指定。

使用--profile命令行可以产生build运行时间的报告。

该报告存储在build/report/profile目录,名称为build运行的时间。

1$ gradle build --profile:compileJava UP-TO-DATE:processResources UP-TO-DATE:classes UP-TO-DATE:jar UP-TO-DATE:assemble UP-TO-DATE:compileTestJava UP-TO-DATE:processTestResources UP-TO-DATE:testClasses UP-TO-DATE:test UP-TO-DATE:check UP-TO-DATE:build UP-TO-DATEBUILD SUCCESSFULTotal time: 3.726 secs

然后在build/report/profile目录下可以看到build的report。

这个报表非常有用,尤其是在在缩短build时间时可以快速定位那些耗时长的task。

试运行build。

如果你想知道某个task执行时那些task会被一起执行,但是你又不想真正的执行这些task,可以使用-m来试运行。

1$ gradle -m build:compileJava SKIPPED:processResources SKIPPED:classes SKIPPED:jar SKIPPED:assemble SKIPPED:compileTestJava SKIPPED:processTestResources SKIPPED:testClasses SKIPPED:test SKIPPED:check SKIPPED:build SKIPPEDBUILD SUCCESSFULTotal time: 3.53 secs

这样我们可以一目了然的看到那些task被执行了,又不需要花太多的时间。

Gradle的图形界面。

其实Gradle自带一个图形界面来让习惯gui操作的人来操作Gradle。

打开方式很简单。

1$ gradle --gui

这样就会弹出一个gui界面。

通过这个gui界面可以很方面的执行gradle的各种命令,还可以将常用的命令保存为favorites。

该gui的配置信息默认被存储在当前项目的gradle-app.setting文件中。

注意使用gradle --gui会阻塞当前终端,可以使用gradle --gui&来实现后台运行。

重新编译Gradle脚本。

第一次运行Gradle命令,会在项目更目录下生成一个.gradle目录来存放编译后的脚本。

只有当构建脚本发生修改时采用重新编译。

我们可以使用--recompile-scripts来强行重新编译。

java,最火,构建,工具,Gradle,命令行,黑,魔法,
                                   

javascript面向对象包装类Class的类库解析

javascript是个入门门槛很低的语言,甚至一个从来没有接触过javascript的技术人员,几小时内就可以写出一个简单有用的程序代码。

但是如果因此你就下结论:javascript是门简单的语言。

那你就大错特错了。

想写出高性能的代码,同样需要具备一个高级程序员的基本素养。

一个java或者c++程序员,不一定能写出高性能的javascript代码,但更容易写出高性能的javascript代码。

javascript的简单是基于它“胸襟广阔”的包容性。

它声明时,不需要指定类型,甚至可以任意的转换类型。

它面向对象,却没有类(Class)的限制。

它是一门崇尚自由又非常严谨的语言,如果你是一个自由主义者,那么,拥抱javascript吧!面向对象编程 (OOP) 是一种流行的编程方法。

但javascript的OOP,较之JAVA、c++有很大的同,主要体现它的继承方式不同。

javascript是基于原型PROTOTYPE继承的。

所有对象都是基于原型链,最终追述到Object对象。

这里不想讨论过多的关于javascript的继承方式和其它语言的继承方式的不同之处。

主要讨论如何封装javascript的Class,以便更好的管理和维护基础代码,减少重复代码,以及更好的模块化编程。

下面是几个github上找到的比较好的Class封装类库: 一、MY-CLASS项目地址:https://github.com/jiem/my-class先看基本用法:a、新建一个类(function() { // 新建类 var Person = my.Class({ // 添加静态方法 STATIC: { AGE_OF_MAJORITY: 18 // 构造函数 constructor: function(name, age) { this.name = name; this.age = age; // 实例方法 sayHello: function() { console.log(‘Hello from ‘ + this.name + ‘!‘); // 实例方法 drinkAlcohol: function() { this.age b、继承一个类(function() { //Dreamer 继承 Person var Dreamer = my.Class(Person, { // 构造方法 constructor: function(name, age, dream) { Dreamer.Super.call(this, name, age); this.dream = dream; // 实例方法 sayHello: function() { superSayHello.call(this); console.log(‘I dream of ‘ + this.dream + ‘!‘); // 实例方法 wakeUp: function() { console.log(‘Wake up!‘); // Super访问父类 var superSayHello = Dreamer.Super.prototype.sayHello; // 暴露给全局命名空间 myLib.Dreamer = Dreamer;})();var sylvester = new myLib.Dreamer(‘Sylvester‘, 30, ‘eating Tweety‘);sylvester.sayHello(); //log "Hello from Sylvester! I dream of eating Tweety!"sylvester.wakeUp(); //log "Wake up!"c、给类添加新方法// 给myLib.Dreamer添加新方法my.extendClass(myLib.Dreamer, { // 添加静态方法 STATIC : { s_dongSomeThing : function(){ console.log("do some thing!"); // 添加实例方法 touchTheSky: function() { console.log(‘Touching the sky‘); // 添加实例方法 reachTheStars: function() { console.log(‘She is so pretty!‘);});d、实现一个类的方法// 声明一个新类myLib.ImaginaryTraveler = my.Class({ travel: function() { console.log(‘Traveling on a carpet!‘); }, crossOceans: function() { console.log(‘Saying hi to Moby Dick!‘); }(function() { //Dreamer 继承 Person 实现 ImaginaryTraveler的方法 var Dreamer = my.Class(Person, ImaginaryTraveler, { // 构造方法 constructor: function(name, age, dream) { Dreamer.Super.call(this, name, age); this.dream = dream; // ... // 暴露给全局命名空间 myLib.Dreamer = Dreamer;})();var aladdin = new Dreamer(‘Aladdin‘);aladdin instanceof Person; //truealaddin instanceof ImaginaryTraveler; //falsealaddin.travel();aladdin.wakeUp();aladdin.sayHello();如果怕忘记new操作符var Person = my.Class({ //you can now call the constructor with or without new constructor: function(name, city) { if (!(this instanceof Person)) return new Person(name, city); this.name = name; this.city = citye;});下面看一下my.class的源代码解析:my.Class实现思路基本是这样的,如果只有一个参数,那么声明的是一个基础类,这个参数是用来声明新类的方法和属以及构造函数。

它不是继承而来,但它可以被继承。

继承的思路,就是如果有两个参数,第一个参数做为父类被继承,第二参数用来声明新类的方法和属性以及构造函数,它同样可以被继承。

如果有三个以上参数那么,除出第一个参数做为继承的父类,最后一个参数用声明新类的方法和属性以及构造函数。

中间的参数是用类来扩展新类的方法。

当然也可以通过my.extendClass扩展新方法。

同时,类库为commonJS和浏览环境都提供了支持!/*globals define:true, window:true, module:true*/(function () { // Namespace object var my = {}; // 保证AMD分模块可用 if (typeof define !== ‘undefined‘) define([], function () { return my; else if (typeof window !== ‘undefined‘) // 保证客户端可用 window.my = my; else // 保证后台可用 module.exports = my; //============================================================================ // @method my.Class // @params body:Object // @params SuperClass:function, ImplementClasses:function..., body:Object // @return function my.Class = function () { var len = arguments.length; var body = arguments[len - 1]; // 最后一个参数是指定本身的方法 var SuperClass = len > 1 ? arguments[0] : null; // 第一个参数是指继承的方法,实例和静态部分均继承 var hasImplementClasses = len > 2; // 如果有第三个参数,那么第二个就是implementClass,这里其实只继承实例对象 var Class, SuperClassEmpty; // 保证构造方法 if (body.constructor === Object) { Class = function() {}; } else { Class = body.constructor; // 保证后面不覆盖constructor delete body.constructor; // 处理superClass部分 if (SuperClass) { // 中间件实现实例属性的继承 SuperClassEmpty = function() {}; SuperClassEmpty.prototype = SuperClass.prototype; Class.prototype = new SuperClassEmpty(); // 原型继承,解除引用 Class.prototype.constructor = Class; // 保证constructor Class.Super = SuperClass; // 父对象访问接口 // 静态方法继承,重载superClass方法 extend(Class, SuperClass, false); // 处理ImplementClass部分,其实只继承实例属性部分,除SuperClass #arguments[0]# 和 body #arguments[length-1]# if (hasImplementClasses) for (var i = 1; i 1234在本页阅读全文 本文导航 第1页: 首页 第2页: KLASS 第3页: 简单实现 第4页: mootools类库的Class javascript,面向,对象,包装,类,Class,的,

.Net4.0用表达式树构建委托改善反射性能

最近搞一个系统时由于在比较关键地方用到反射了,所以要关注了一下反射的性能问题。

.Net4.0反射性能改善看老赵的文章,老赵得到的结果是这样的:00:00:00.0125539 (Directly invoke)00:00:04.5349626 (Reflection invoke)00:00:00.0322555 (Dynamic executor)而我把代码搞下来自己运行得到这样的结果:00:00:00.0009710 (Directly invoke)00:00:00.4142893 (Reflection invoke)00:00:00.0194501 (Dynamic executor)这里不是说机器性能造成绝对的时间,而是差距比例完全不一样,想了一阵想起了老赵当时应该是基于.Net3.5,果断把程序的目标框架切换到.Net3.5,结果如下:00:00:00.0018801 (Directly invoke)00:00:02.4288876 (Reflection invoke)00:00:00.0141537 (Dynamic executor)三者的差距仍然有些不一样,老赵那边的直接调用与动态执行同一数量级的结果还是没有。

但发现了另一些信息。

反射和直接调用方法.Net4.0比.Net3.5有非常大的改善,特别是反射,性能提升了好几倍。

反而构建表达式树动态调用的方式性能比.Net3.5差了一点。

但是相对反射还是有差距,按照这个比例,写写表达式树还是值得的。

改善老赵的DynamicMethodExecutor老赵的那篇的文章的思路是使用DynamicMethodExecutor来构造一个万能的委托Func其中第一个参数是实例对象,第二是参数列表,第三是返回值。

.Net4.0的表达式树要比3.5的先进一点,经过一番改造发现是不需要这么一个万能委托的,直接用Expression.Lambda.Compile()编译出来的Delegate强制转换为强类型的委托来得更加简单。

全部代码一个方法即可,精简了许多。

/// /// 动态构造委托/// 方法元数据/// 委托public static Delegate BuildDynamicDelegate(MethodInfo methodInfo) if (methodInfo == null) throw new ArgumentNullException("methodInfo"); var paramExpressions = methodInfo.GetParameters().Select((p, i) => var name = "param" + (i + 1).ToString(CultureInfo.InvariantCulture); return Expression.Parameter(p.ParameterType, name); }).ToList(); MethodCallExpression callExpression; if (methodInfo.IsStatic) //Call(params....) callExpression = Expression.Call(methodInfo, paramExpressions); else var instanceExpression = Expression.Parameter(methodInfo.ReflectedType, "instance"); //insatnce.Call(params….) callExpression = Expression.Call(instanceExpression, methodInfo, paramExpressions); paramExpressions.Insert(0, instanceExpression); var lambdaExpression = Expression.Lambda(callExpression, paramExpressions); return lambdaExpression.Compile();}使用时转换为强类型的委托即可:var action = (Action)BuildDynamicDelegate(methodInfo);var func = (Func)BuildDynamicDelegate(methodInfo);老赵那个委托都是object,使用时的类型转换,还有装箱,拆箱都会有一定的性能损失,而强类型就没有这个问题。

首先在老赵的那篇文章上一个方法改为两个方法,然后测试:public void Call1(object o1, object o2, object o3) { }public void Call2(int o1, int o2, int o3) { }private static void DynamicExecutor_ObjectType() var executor = new DynamicMethodExecutor(Call1MethodInfo); var watch1 = new Stopwatch(); watch1.Start(); for (var i = 0; i 构建委托动态赋值既然有动态调用方法,同样也可以动态赋值,而且据我的经验,根据PropertyInfo的SetValue去反射设属性值用得比反射调用方法更加频繁。

所以同样需要有方法来动态构建委托改善性能。

幸好,.Net4.0提供了支持,.Net4.0新增了Expression.Assign来表示一个赋值表达式。

有了它,构建起来比方法的更加简单:private static Action BuildSetPropertyAction(PropertyInfo propertyInfo) var instanceParam = Expression.Parameter(typeof(TInstance), "instance"); var valueParam = Expression.Parameter(typeof(TProperty), "value"); //instance.Property var propertyProperty = Expression.Property(instanceParam, propertyInfo); //instance.Property = value var assignExpression = Expression.Assign(propertyProperty, valueParam); var lambdaExpression = Expression.Lambda 下一篇:

加入收藏
               

java最火构建工具Gradle命令行黑魔法

点击下载文档

格式为doc格式

  • 账号登录
社交账号登录