maven - Grails:为什么在编译期间执行 Config.groovy 文件?

标签 maven grails groovy configuration log4j

来自 the Grails documentationthis题:

For general configuration Grails provides two files:

  1. grails-app/conf/BuildConfig.groovy
  2. grails-app/conf/Config.groovy

Both of them use Groovy's ConfigSlurper syntax. The first, BuildConfig.groovy, is for settings that are used when running Grails commands, such as compile, doc, etc. The second file, Config.groovy, is for settings that are used when your application is running. This means that Config.groovy is packaged with your application, but BuildConfig.groovy is not.



这是关于 log4j 的摘录框架:

Grails uses its common configuration mechanism to provide the settings for the underlying Log4j log system, so all you have to do is add a log4j setting to the file grails-app/conf/Config.groovy.



我有一个包含这两个文件的项目:grails-app/conf/BuildConfig.groovygrails-app/conf/Config.groovy .项目使用log4j实用程序,所以一些设置(包括一个函数)放在 中。 config.groovy 文件。现在,根据我引用的文档,它是正确的文件,因为我想使用日志实用程序来运行应用程序,而不是编译它。

有趣的是,这些设置在我运行 mvn package 时使用在我的项目中 - log4j 中的函数设置被执行。

根据两者the documentationthe question情况不应该是这样。

我知道可以使用 grailsApplication访问这些设置:
def recipient = grailsApplication.config.foo.bar.hello

所以我搜索了我的项目,发现了 grailsApplication 的一些用法。 ,但与 log4j 设置无关。

将 log4j 设置放置在 中的其他可能原因是什么? config.groovy 期间使用的文件 mvn package ?我错过了什么?

更新:当我使用 mvn package 时,上述配置似乎有效第一次构建我的项目。下次跑 mvn package , log4j来自 Config.groovy 的配置文件被使用。如果我删除作业工作区,它会再次正常工作。

最佳答案

有一件重要的事情值得一提。即使 Config.groovy由应用程序在运行时使用,它必须编译为 Java 的 Config.class首先。打包时,应用程序编译器必须访问此文件并将其编译为字节码。看看我粘贴在下面的 list ,它来自我工作区中的一个 Grails 应用程序:

命令:

ls -l target/classes | awk '{print $8}'

输出:
application.properties
BootStrap.class
BootStrap$_closure1.class
BootStrap$_closure2.class
BuildConfig.class
BuildConfig$_run_closure1.class
BuildConfig$_run_closure1_closure2.class
BuildConfig$_run_closure1_closure3.class
BuildConfig$_run_closure1_closure4.class
BuildConfig$_run_closure1_closure5.class
com
Config.class
Config$_run_closure1.class
Config$_run_closure1_closure4.class
Config$_run_closure1_closure4_closure5.class
Config$_run_closure1_closure4_closure5_closure6.class
Config$_run_closure2.class
Config$_run_closure2_closure7.class
Config$_run_closure2_closure8.class
Config$_run_closure3.class
DataSource.class
DataSource$_run_closure1.class
DataSource$_run_closure2.class
DataSource$_run_closure3.class
DataSource$_run_closure3_closure4.class
DataSource$_run_closure3_closure4_closure7.class
DataSource$_run_closure3_closure5.class
DataSource$_run_closure3_closure5_closure8.class
DataSource$_run_closure3_closure6.class
DataSource$_run_closure3_closure6_closure9.class
DataSource$_run_closure3_closure6_closure9_closure10.class
resources.class
resources$_run_closure1.class
UrlMappings.class
UrlMappings$__clinit__closure1.class
UrlMappings$__clinit__closure1_closure2.class
UrlMappings$__clinit__closure1_closure2_closure3.class

你可以看到 Config.groovy文件被编译为 Config.class文件和所有在 Config.groovy 中使用的闭包被编译为 Java 的匿名类(例如 Config$_run_closure1_closure4.class )。这就是为什么如果你把一些执行任何逻辑的代码放到 Config.groovy您必须期望它会被编译和执行,因为已编译的类扩展了 groovy.lang.Script它执行 Groovy 脚本文件的主体。您可以在下面找到 Groovy.class 的内容文件看起来像:

命令:
javap -l  target/classes/Config.class

输出:
Compiled from "Config.groovy"
public class Config extends groovy.lang.Script {
  public static transient boolean __$stMC;

  public static long __timeStamp;

  public static long __timeStamp__239_neverHappen1501076781354;

  public Config();
    LocalVariableTable:
      Start  Length  Slot  Name   Signature
          4       4     0  this   LConfig;

  public Config(groovy.lang.Binding);
    LocalVariableTable:
      Start  Length  Slot  Name   Signature
          4      21     0  this   LConfig;
          4      21     1 context   Lgroovy/lang/Binding;

  public static void main(java.lang.String...);
    LocalVariableTable:
      Start  Length  Slot  Name   Signature
          0      19     0  args   [Ljava/lang/String;

  public java.lang.Object run();
    LineNumberTable:
      line 14: 4
      line 17: 43
      line 18: 126
      line 24: 194
      line 26: 233
      line 30: 296
      line 31: 323
      line 38: 376
      line 42: 419
      line 45: 453
      line 63: 473
      line 65: 507
      line 68: 550
      line 70: 595
      line 72: 631
      line 74: 679
      line 77: 724
      line 80: 777
      line 84: 822
      line 86: 867
      line 88: 912
      line 99: 932
    LocalVariableTable:
      Start  Length  Slot  Name   Signature
          0     964     0  this   LConfig;

  public java.lang.Object this$dist$invoke$3(java.lang.String, java.lang.Object);
    LocalVariableTable:
      Start  Length  Slot  Name   Signature
          0      68     0  this   LConfig;
          0      68     1  name   Ljava/lang/String;
          0      68     2  args   Ljava/lang/Object;

  public void this$dist$set$3(java.lang.String, java.lang.Object);
    LocalVariableTable:
      Start  Length  Slot  Name   Signature
          0      53     0  this   LConfig;
          0      53     1  name   Ljava/lang/String;
          0      53     2 value   Ljava/lang/Object;

  public java.lang.Object this$dist$get$3(java.lang.String);
    LocalVariableTable:
      Start  Length  Slot  Name   Signature
          0      46     0  this   LConfig;
          0      46     1  name   Ljava/lang/String;

  protected groovy.lang.MetaClass $getStaticMetaClass();

  public static void __$swapInit();

  static {};

  public int super$1$hashCode();

  public void super$3$printf(java.lang.String, java.lang.Object);

  public void super$3$printf(java.lang.String, java.lang.Object[]);

  public void super$3$setProperty(java.lang.String, java.lang.Object);

  public boolean super$1$equals(java.lang.Object);

  public void super$1$finalize();

  public groovy.lang.Binding super$3$getBinding();

  public void super$3$print(java.lang.Object);

  public void super$3$setBinding(groovy.lang.Binding);

  public java.lang.Object super$3$evaluate(java.io.File);

  public java.lang.String super$1$toString();

  public java.lang.Object super$3$evaluate(java.lang.String);

  public void super$2$setMetaClass(groovy.lang.MetaClass);

  public void super$1$notify();

  public java.lang.Object super$3$invokeMethod(java.lang.String, java.lang.Object);

  public java.lang.Object super$1$clone();

  public void super$1$wait(long, int);

  public void super$1$wait(long);

  public void super$1$wait();

  public groovy.lang.MetaClass super$2$getMetaClass();

  public java.lang.Class super$1$getClass();

  public void super$3$run(java.io.File, java.lang.String[]);

  public void super$3$println(java.lang.Object);

  public void super$1$notifyAll();

  public java.lang.Object super$3$getProperty(java.lang.String);

  public void super$3$println();

  static java.lang.Class class$(java.lang.String);
}

更新

现在明白为什么Config.groovy执行我们需要深入研究 grails package 时会发生什么正在被执行。运行 grails package命令使 _GrailsPackage.groovy来自 grails-core 的脚本正在执行。 packageApp目标电话GrailsProjectPackager.packageApplication()
https://github.com/grails/grails-core/blob/2.4.x/grails-scripts/src/main/scripts/_GrailsPackage.groovy#L48

此方法调用 createConfig()辅助类:

https://github.com/grails/grails-core/blob/2.4.x/grails-project-api/src/main/groovy/org/codehaus/groovy/grails/project/packaging/GrailsProjectPackager.groovy#L274

createConfig()方法实现我们可以找到ConfigSlurper.parse(script)执行:

https://github.com/grails/grails-core/blob/2.4.x/grails-project-api/src/main/groovy/org/codehaus/groovy/grails/project/packaging/GrailsProjectPackager.groovy#L345

这是一个解析脚本并最终调用 script.run() 的 Groovy 类。在解析的脚本上。使用调试器很容易找到 - 请查看我的视频,我在此特定示例中展示了如何执行此操作:https://www.youtube.com/watch?v=s2PN6TjFjUI

我希望它有帮助。

关于maven - Grails:为什么在编译期间执行 Config.groovy 文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46279525/

相关文章:

grails - 无法在GGTS中配置Grails 3.0.4,使用GVM安装了Grails

Grails 域约束定义

grails - 如何在Grails中检索LDAP数据?

exception - Groovy catch 语句奇怪的行为

gradle - 使用Tar Task为Gradle中的每个文件夹创建tar.gz

java - Spring 3 + Tomcat 6 : Form validation exception - java. lang.NoSuchMethodError : javax. el.ExpressionFactory.newInstance()Ljavax/el/ExpressionFactory;

java - cucumber .runtime.CucumberException : Couldn't load plugin class: io. qameta.allure.cucumberjvm.AllureCucumberJvm

java - Spring Boot 应用程序未在外部 Tomcat 中启动(在 Tomcat 8.5 和 10 中均尝试过)

postgresql - postgres 的 Flyway 迁移挂起并发创建索引

math - 在 Groovy 除法中显示小数