类加载器 jboss_JBoss AS 7类加载说明

类加载器 jboss_JBoss AS 7类加载说明

类载入是基于JBoss模块的。必须**显示的定义模块依赖。**部署也是模块化的,假设没有显示的定义类依赖则不能访问应用server jar中的类。

在部署过程中,一些由应用server定义的模块依赖会自己主动装配。比如,假设部署一个Java EE 应用,将自己主动加入Java EE API依赖,这也成为隐式模块依赖。对于其它的类,必须在MANIFEST.MF文件的”Dependencies:”或”Class-Path:”项,或在jboss-deployment-structure.xml文件里定义显示的模块依赖。

  1. 系统依赖– easy自己主动将载入的模块依赖。包含Java EE API

  2. 用户依赖– 在jboss-deployment-structure.xml(ear的META-INF内。war的META-INF或WEB-INF内)或Dependencies:项内配置的依赖。

  3. 本地资源– 公布文件夹下的类文件,如war包下的WEB-INF/classes或WEB-INF/lib

  4. 部署间依赖– 在ear内的其它部署依赖。包含ear lib文件夹内的类。或其它ejb内的类

所部署的任何应用程序实际上都是模块。一些疑问:

分配给已部署应用程序的模块名称是什么?

AS如何处理模块之间的依赖关系?

了解模块名称

打包为顶级归档文件(例如WAR,JAR和SAR)的应用程序将获得以下模块名称:

deployment.[archive name]
// 部署一个名为WebExample1.war的Web应用程序作为模块名称:
deployment.WebExample1.war

另一方面,在包含嵌套模块的应用程序(例如EAR归档文件)上,将使用以下分类为每个单个归档文件分配模块名称:

deployment.[ear archive name].[sub deployment archive name]
// 因此,如果将相同的Web应用程序包含在存档EnterpriseApp.ear中 ,则将使用以下名称进行部署:
deployment.EnterpriseApp.ear.WebExample1.war

查找隔离级别

配置应用程序服务中,部署一个使用log4j Api的应用程序,将log4j库添加到WEB-INF / lib文件夹中。 该应用程序的部署很顺利,省去了一个问题:为什么需要添加已经作为模块包含在应用程序服务器(AS模块)中的库?(jboss自带的log4j在…modules \ org \ apache \ log4j \ main路径下)

一般规则是,在JBoss AS 7上,每个已部署的应用程序模块都与其他模块隔离开来。默认情况下,它在AS模块上不可见,而AS模块在应用程序上也不可见,但是,使用AS模块非常容易:将依赖项添加到所需模块中,AS就会使用它。AS模块会自动添加依赖项,或者它们需要由用户发出信号:

  • JBOSS核心模块库(即Enterprise类)被视为隐式依赖项,因此当部署者检测到它们的使用时,它们会自动添加到应用程序中
  • 用户需要在应用程序的MANIFEST文件或自定义的JBoss部署文件jboss-deployment-structure.xm l中明确声明其他模块库

隐式依赖:

指出应用程序通常使用的Api依赖项可能很麻烦。 因此,AS会自动添加它们。 当应用服务器检测到某些该模块的典型注释或配置文件时,将添加一些注释或配置文件。 例如,添加beans.xml文件会触发自动焊接依赖关系。

  • 如果应用程序使用了任何核心模块,那么无需指定任何依赖项,因为应用程序服务器能够自动链接该模块。

  • 显式依赖项不能由隐式依赖项限定的模块需要由用户声明

示例:

未将log4j库作为隐式依赖项提及,因此不得不将log4j JAR与应用程序打包在一起。 但是,可以指示部署者使用log4j库,该库捆绑在应用程序服务器分发中。 实现它的最简单且推荐的方法是在META-INF / MANIFEST.MF中包括Dependencies:[module]声明。 在这样的情况下,要使应用程序依赖于JBOSS自带的log4j,只需在清单文件中包含以下代码:

//Dependencies: <package-name>
Dependencies: org.apache.log4j // 单个依赖项
or
Dependencies: org.apache.log4j, org.apache.velocity  // 多个依赖项
// 模块名称并不总是与库的软件包名称匹配, 实际的模块名称由module元素的name属性在module.xml文件中指定
// 甚至可以通过添加export关键字将一个应用程序模块使用的依赖项导出到其他应用程序

设置全局模块

该选项与用于加载公共库的旧AS方法有点类似,曾经将它们放置在文件夹JBOSS_HOME / common / lib中。 如果在standalone.xml / domain.xml中定义了名为global-modules的部分,则将使该模块可被其他AS模块访问。可以选择使用以下部分来代替声明对log4j的依赖关系:

<subsystem xmlns="urn:jboss:domain:ee:1.0">
  <global-modules>
    <module name="org.apache.log4j" />
  </global-modules>
</subsystem>

尽管通常不建议使用这种方法,但是由于回到了单片应用服务器的概念,因此它仍然可以带来一些好处。 例如,如果要迁移一些较旧的应用程序,并且不希望或者根本无法将依赖关系指定到存档中。

进阶部署策略

以上知识足以配置多种应用程序。 如果使用的是复杂的归档文件配置,例如具有多个模块和依赖项的EAR归档文件,那么在单个文件中定义类加载策略将很有用。

配置文件jboss-deployment-structure.xml可以做到这一点。 使用此文件的优点有很多:

  • 可以在一个文件中定义所有应用程序模块的依赖关系
  • 可以通过包含/排除所有或部分模块来使用更精细的方式加载模块类
  • 可以为打包在企业归档中的应用程序定义类加载隔离策略

jboss-deployment-structure.xml 用法

1、设置单个模块依赖性

归档文件的MANIFEST文件中的Dependencies属性可以激活log4j依赖关系。 jboss-deployment-structure.xml文件可以达到相同的效果

文件jboss-deployment-structure.xml需要放置在EAR的META-INF文件夹中。内容如下:

<jboss-deployment-structure>
  <sub-deployment name="WebApp.war">
    <dependencies>
      <module name="org.apache.log4j" />
    </dependencies>
  </sub-deployment>
</jboss-deployment-structure>

文件jboss-deployment-structure并非专用于EAR。 实际上,也可以通过将其放置在存档的WEB-INF文件夹中,将其部署在WebApp应用程序中。 但是,它仅适用于顶级归档。 因此,如果将jboss-deployment-structure.xml放在WAR的WEB-INF文件夹中,并且将WAR打包在EAR档案中,则将忽略jboss-deployment-structure.xml。

该文件的相关部分是sub-deployment元素,该元素引用Web应用程序(包括其中的依赖项)。 预期的结果是应用程序服务器(AS)将触发对log4j Api的依赖关系,因此我们的Web应用程序将看到该依赖关系。

2、排除服务器自动依赖项

当满足某些条件时,应用程序服务器能够自动触发某些依赖关系。 例如,如果部署JSF应用程序(包含faces-config.xml文件),那么将自动添加JSF 2.1 Api实现

这可能并不总是所需的选项,因为要为该模块提供另一个发行版实现。 可以使用jboss-deployment-structure.xml中的排除部分轻松实现:

<jboss-deployment-structure>
  <deployment>
    <exclusions>
      <module name="javax.faces.api" />
      <module name="com.sun.jsf-impl" />
    </exclusions> 
    <dependencies>
      <module name="javax.faces.api" slot="1.2"/> 
      <module name="com.sun.jsf-impl" slot="1.2"/>
    </dependencies> 
  </deployment>
</jboss-deployment-structure>

注意,在“依赖项”部分中,添加了备用JSF 1.2实现,的应用程序将使用该实现。 实际上,此JSF实现随slot属性指定的文件夹下的应用程序服务器分发以及javax.faces.api模块路径一起提供。 在例子中,这对应于JBOSS_HOME / modules / javax / faces / api / 1.2文件夹。

3、隔离子部署

类加载器如何解决此冲突? 加载用于避免已加载类之间的任何冲突的类时,应用程序服务器类加载器具有优先级列表。

  1. 系统依赖

  2. 用户依赖

  3. 本地资源

  4. 部署间依赖

位于WEB-INF文件夹中的EJB库将“隐藏” EJB.jar顶级部署的实现。 无论这是否是容器中所需的操作,仍然可以覆盖它:

<jboss-deployment-structure> 
  <ear-subdeployments-isolated>false</ear-subdeployments-isolated> 
  <sub-deployment name="WebApp.war">
    <dependencies>
      <module name="deployment.App.ear.EJB.jar" />   
    </dependencies>
  </sub-deployment>
</jboss-deployment-structure>

在此示例中,向EJB.jar添加了一个依赖关系,该依赖关系位于存档的根目录下,它将覆盖Web应用程序中打包的实现。

注意, ear-subdeployments-isolated元素位于文件顶部。 通过设置EAR隔离级别,将能够指示子部署模块是否彼此可见。

此属性的默认值为false ,这意味着子部署模块将能够看到彼此。 如果将隔离设置为true,则每个模块将由不同的类加载器接收,因此,在示例中,Web应用程序将无法找到EJB.jarUtility.jar库中包含的类。

如果要使部署保持隔离状态,但允许其中一些可见,则可以选择以下几种方法:

  • 将库移至EAR / lib文件夹,以便将其作为单独的模块使用
  • 使用依赖关系或调用应用程序的MANIFEST.MF文件中的类路径指定依赖关系

使用类路径声明来解决依赖关系:

用JBoss的方法解决模块之间的依赖关系,建议将其作为首选。 尽管如此,还应该考虑Java引用EAR文件中包含的一个或多个库的可移植方式。

可以使用模块的MANIFEST.MF文件中的Class-Path属性来完成此操作,该属性需要引用其他应用程序无法看到的其他库(考虑到前面的示例,带有隔离集的部署单元为true

例如,假设需要从Web应用程序中引用Utility.jar应用程序,然后只需将以下内容添加到META-INF / MANIFEST.MF中:

  • 清单版本:1.0
  • 类路径:Utility.jar

可以在类路径中包含多个库,并以逗号分隔它们,这与使用JBoss的Dependencies属性的方式几乎相同。 与Dependencies属性不同的是,Class-Path属性指向引用依赖库的实际JAR文件名(而不是模块名)。

在类路径方法和JBoss的Dependencies方法之间进行选择取决于应用程序的结构:

  • JBoss的Dependencies方法:

    • 可以使用到更多的选项,尤其是将Dependencies导出到其他部署的能力
    • 引用模块的能力,这些模块实际上并未打包在应用程序中。 例如,如何向服务器分发中的log4j Api添加依赖项。
  • 类路径方法:应用程序的可移植性强, 如果将全便携式解决方案作为优先事项,则可以考虑切换到Class-Path清单属性。

翻译自: https://www.javacodegeeks.com/2012/09/jboss-as-7-classloading-explained.html

案例参考:

https://www.bbsmax.com/A/l1dy6aG6ze/ - 用户依赖、本地资源的使用

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值