【问题标题】:Override class in library used in web project覆盖 Web 项目中使用的库中的类
【发布时间】:2018-02-18 23:54:29
【问题描述】:

我想修补我在战争项目中使用的库的 java 类。

我已经用具有相同规范名称的新类覆盖了该类,但在 Web 应用程序中,仍然首先加载原始类。如何控制类加载顺序?

我从这篇文章开始,并阅读了 JAR Hell: Override class in java

并使用此处找到的 maven 示例: http://owenou.com/2010/07/20/patching-with-class-shadowing-and-maven.html

基本上是一个辅助项目,它依赖于一个带有覆盖类和原始库的新修补 jar,以及一个 MANIFEST.MF,这些库在类路径中以正确的顺序排列。所以其他项目可以使用这个辅助项目。

这在独立应用程序中运行良好,但在 Web 项目中,原始 jar 仍然首先加载。

有什么帮助吗?

【问题讨论】:

    标签: java overriding classloader war


    【解决方案1】:

    我遇到了完全相同的问题,这就是我为使其正常工作所做的工作。 我的项目包含一个“ThatProject”库,其中包含一个导致错误的 ServiceFactory.java 类。

    <dependencies>
        <dependency>
            <groupId>com.example.ThatGroup</groupId>
            <artifactId>ThatProject</artifactId>
            <version>${ThatProject.version}</version>
        </dependency>
    </dependencies>
    

    在我自己的项目中,我创建了一个相同的类来隐藏“ThatProject”之一(路径必须匹配)。 → src\main\java\com\example\ThatGroup\ThatProject\ServiceFactory.java

    在我的 pom.xml 中,我使用了 maven-shade-plugin 插件,如下所示。 请注意我是如何从“ThatProject”库中排除原始 ServiceFactory.java 的。

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${maven-compiler-plugin.version}</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                </configuration>
            </plugin>
            <!-- Include all dependencies in JAR -->
            <plugin>
              <artifactId>maven-shade-plugin</artifactId>
              <version>2.2</version>
              <executions>
                <execution>
                  <id>shade</id>
                  <goals>
                    <goal>shade</goal>
                  </goals>
                  <phase>package</phase>
                  <configuration>
                    <createDependencyReducedPom>false</createDependencyReducedPom>
                    <filters>
                      <filter>
                        <artifact>com.example.ThatGroup:ThatClient</artifact>
                        <excludes>
                          <exclude>com/example/ThatGroup/ThatProject/ServiceFactory.class</exclude>
                        </excludes>
                      </filter>
                    </filters>
                  </configuration>
                </execution>
              </executions>
            </plugin>
        </plugins>
    </build>
    

    就是这样,它终于对我有用了。在我的例子中,我将项目的所有文件都包含在 pom.xml 的这个配置中(包括我的 ServiceFactory.java 的影子版本)。 如前所述,原来的 ServiceFactory.java 在 maven 构建期间被排除在外。

    希望这会有所帮助!

    【讨论】:

      【解决方案2】:

      一个肮脏的解决方案是从包含您不喜欢加载的版本的 jar 中删除该类。

      另一种解决方案是重新排序类路径,以便您的版本在旧版本之前。来自java documentation

      规范顺序

      您指定多个类路径条目的顺序是 重要的。 Java 解释器将在 目录按照它们在类路径变量中出现的顺序排列。在 在上面的例子中,Java 解释器会首先寻找需要的 目录 C:\java\MyClasses 中的类。只有当它没有找到 该目录中具有正确名称的类将解释器查找 在 C:\java\OtherClasses 目录中。

      请注意,这两种解决方案都非常肮脏,未来对代码的修改可能会破坏您的功能(例如更改类路径或更新 jar)。

      最好的方法是以下之一:

      • 扩展类并仅使用新类
      • 在新类中实现相同的接口并使用它

      【讨论】:

      • 嗯,它是一个实用程序类,用于不受我控制的外部 jar,我无法扩展该类。我已经将类直接替换到 jar 中,但正如你所说,这不是很正确。类路径重新排序在 Web 项目中完全不起作用。
      【解决方案3】:

      如果你控制应用程序客户端,你可以尝试在运行时玩jar:

      查看此加载 How to load a jar file at runtime

      如果您还想卸载: Dynamic loading and unloading of jar

      或者,您可以尝试在您的网络应用程序中启动,在 "boot" ,这是先例。然后你就可以确定你得到了什么课程。

      【讨论】:

        猜你喜欢
        • 2011-09-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-23
        • 1970-01-01
        • 2012-01-11
        • 1970-01-01
        • 2012-12-13
        相关资源
        最近更新 更多