此内容没有您所选择的语言版本。

4.5. Dynamic Classloading


So far you have used the extension and application classloaders to load all of the classes in the application. The application classpath is set up by the run.sh script using the -cp flag to include the current directory and the client-1.0.0.jar, as shown here:
java -Djava.ext.dirs=`pwd`/lib -cp .:client-1.0.0.jar org.jboss.example.client.Client $1
Copy to Clipboard Toggle word wrap
For convenience the JARs in the lib directory were added to the extension classloader's classpath using the java.ext.dirs system property, rather than listing the full path to each of the JARs after the -cp flag. Because the classloader extension is the parent of the classloader application, the client classes is able to find all of the Microcontainer classes and the Human Resources service classes at run-time.

Note

With Java versions 6 and higher, you can use a wild-card to include all JARs in a directory with the -cp flag: java -cp `pwd`/lib/*:.:client-1.0.0.jar org.jboss.example.client.Client $1
Here, all of the classes in the application will be added to the application classloader's classpath, and the extension classloader's classpath will retain its default value.
What happens if you need to deploy an additional service at run-time? If the new service is packaged in a JAR file, it must be visible to a classloader before any of its classes can be loaded. Because you have already set up the classpath for the application classloader (and extension classloader) on start-up, it is not easy to add the URL of the JAR. The same situation applies if the service classes are contained in a directory structure. Unless the top-level directory is located in the current directory (which is on the application classpath) then the classes will not be found by the application classloader.
If you wish to redeploy an existing service, changing some of its classes, you need to work around security constraints, which forbid an existing classloader from reloading classes.
The goal is to create a new classloader that knows the location of the new service's classes, or that can load new versions of an existing service's classes, in order to deploy the service's beans. JBoss Microcontainer uses the <classloader> element in the deployment descriptor to accomplish this.
The client-cl distribution contains the file listed in the Example 4.5, “Listing of the commandLineClient/target/client-cl Directory” .

Example 4.5. Listing of the commandLineClient/target/client-cl Directory

       |-- client-1.0.0.jar
       |-- jboss-beans.xml
       |-- lib
       |   |-- concurrent-1.3.4.jar
       |   |-- jboss-common-core-2.0.4.GA.jar
       |   |-- jboss-common-core-2.2.1.GA.jar
       |   |-- jboss-common-logging-log4j-2.0.4.GA.jar
       |   |-- jboss-common-logging-spi-2.0.4.GA.jar
       |   |-- jboss-container-2.0.0.Beta6.jar
       |   |-- jboss-dependency-2.0.0.Beta6.jar
       |   |-- jboss-kernel-2.0.0.Beta6.jar
       |   |-- jbossxb-2.0.0.CR4.jar
       |   |-- log4j-1.2.14.jar
       |   `-- xercesImpl-2.7.1.jar
       |-- otherLib
       |   `-- humanResourcesService-1.0.0.jar
       |`-- run.sh
Copy to Clipboard Toggle word wrap
The humanResourcesService.jar file has been moved to a new sub-directory called otherLib. It is no longer available to either the extension or application classloaders whose classpaths are setup in the run.sh script:
java -Djava.ext.dirs=`pwd`/lib -cp .:client-1.0.0.jar org.jboss.example.client.Client $1
Copy to Clipboard Toggle word wrap
To work around this, create a new classloader during the deployment of the service, load it in the service classes, and create instances of the beans. To see how this is done, look at the contents of the jboss-beans.xml file:
<?xml version="1.0" encoding="UTF-8"?>

<deployment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"            
	    xsi:schemaLocation="urn:jboss:bean-deployer:2.0 bean-deployer_2_0.xsd"
	    xmlns="urn:jboss:bean-deployer:2.0">

  <bean name="URL" class="java.net.URL">
    <constructor>
      <parameter>file:/Users/newtonm/jbossmc/microcontainer/trunk/docs/examples/User_Guide/gettingStarted/commandLineClient/target/client-cl.dir/otherLib/humanResourcesService-1.0.0.jar</parameter>
    </constructor>
  </bean>

  <bean name="customCL" class="java.net.URLClassLoader">
    <constructor>
      <parameter>
	<array>
	  <inject bean="URL"/> 
	</array>
      </parameter>
    </constructor>
  </bean>

  <bean name="HRService" class="org.jboss.example.service.HRManager">
    <classloader><inject bean="customCL"/></classloader>
    <!-- <property name="hiringFreeze">true</property>
	 <property name="salaryStrategy"><inject bean="AgeBasedSalary"/></property> -->
  </bean>

  <!-- <bean name="AgeBasedSalary" class="org.jboss.example.service.util.AgeBasedSalaryStrategy">
       <property name="minSalary">1000</property>
       <property name="maxSalary">80000</property>
       </bean>

<bean name="LocationBasedSalary" class="org.jboss.example.service.util.LocationBasedSalaryStrategy">
<property name="minSalary">2000</property>
<property name="maxSalary">90000</property>
</bean> -->

</deployment>
		
		
		
		

Copy to Clipboard Toggle word wrap
  1. First, create an instance of java.net.URL called URL, using parameter injection in the constructor to specify the location of the humanResourcesService.jar file on the local file-system.
  2. Next, create an instance of a URLClassLoader by injecting the URL bean into the constructor as the only element in an array.
  3. Include a <classloader> element in your HRService bean definition and inject the customCL bean. This specifies that the HRManager class needs to be loaded by the customCL classloader.
You need a way to decide which classloader to use for the other beans in the deployment. All beans in the deployment use the current thread's context classloader. In this case the thread that handles deployment is the main thread of the application which has its context classloader set to the application classloader on start-up. If you wish, you can specify a different classloader for the entire deployment using a <classloader> element, as shown in Example 4.6, “Specifying a Different Classloader”.

Example 4.6. Specifying a Different Classloader

<?xml version="1.0" encoding="UTF-8"?>

<deployment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"            
	    xsi:schemaLocation="urn:jboss:bean-deployer:2.0 bean-deployer_2_0.xsd"
	    xmlns="urn:jboss:bean-deployer:2.0">

  <classloader><inject bean="customCL"/></classloader>

  <bean name="URL" class="java.net.URL">
    <constructor>
      <parameter>file:/Users/newtonm/jbossmc/microcontainer/trunk/docs/examples/User_Guide/gettingStarted/commandLineClient/target/client-cl.dir/otherLib/humanResourcesService-1.0.0.jar</parameter>
    </constructor>
  </bean>

  <bean name="customCL" class="java.net.URLClassLoader">
    <constructor>
      <parameter>
	<array>
	  <inject bean="URL"/> 
	</array>
      </parameter>
    </constructor>
  </bean>

  ...

</deployment>
			
			
			
			

Copy to Clipboard Toggle word wrap
This would be necessary to allow for reconfiguration of the service by uncommenting the AgeBasedSalary or LocationBasedSalary beans. Classloaders specified at the bean level override the deployment level classloader. To override the deployment level classloader altogether, and use the default classloader for a bean, use the <null/> value as follows:
<bean name="HRService" class="org.jboss.example.service.HRManager">
  <classloader><null/></classloader>
</bean>
		
		
		
		

Copy to Clipboard Toggle word wrap
If you create a new classloader for your service using the deployment descriptor, you may not be able to access classes loaded by it from the application classloader. In the HRManager example, the client is no longer able to cache a direct reference to the bean instance when using the Microcontainer controller.
To see this behavior, start the client using the run.sh command, then try to deploy the service. A java.lang.NoClassDefFoundError exception is thrown and the application exits.
In this scenario, you must use the bus to access the service indirectly and provide access to any classes shared by the client in the application classpath. In this example, the affected classes are Address, Employee, and SalaryStrategy.
返回顶部
Red Hat logoGithubredditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。 了解我们当前的更新.

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

Theme

© 2025 Red Hat