本文将尝试解答以下几个问题:
1. JBoss5内核是如何部署的?
2. JBoss5部署体系发生了哪些变化?
3. 部署单元怎么被指定的deployer部署?
4. 热部署是如何实现的?
一、JBoss5内核的部署
JBoss5的内核是重新设计的Microcontainer,定制了一个ProfileServiceBootstrap用于启动Microcontainer。
bootstrap启动后,通过BasicXMLDeployer布署conf/bookstrap-beans.xml
在jboss5中使用XmlBinding组件解析bootstrap-beans.xml,xmlbinding组件通过schema定义文件将对象序列化为xml文件或反之,
通过反序列化得到一个AbstractKernelDeployment对象,它包含了所有Bean组件的元数据AbstractBeanMetaData;
然后通过KernelController安装Bean,并依次调用create, start方法,通过配置文件可以指定create和start方法的名称。
在bootstrap-beans中声明了一个主部署器MainDeployer,它包含一些内置的deployer,和一些StructureDeployer,它们的说明如下:
WARStructure:处理WAR结构;
JARStructure:处理JAR结构,包括zip, ear, jar, rar, war, sar, har, aop, deployer, beans
FileStrucutre:处理File结构,包括-service.xml, -beans.xml, -ds.xml, -aop.xml结尾的文件;
AspectDeployer:解析-aop.xml文件,
BeanDeployer:解析-beans.xml文件,得到KernelDeployment对象;
KernelDeploymentDeployer:将KernelDeployment中的BeanMetaData添加到DeploymentUnit;
BeanMetaDataDeployer:将BeanMetaData安装到Microcontainer中。
SARDeployer:解析-service.xml文件,得到ServiceDeployment对象;
ServiceDeploymentDeployer:将ServiceDeployment中的ServiceMetaData添加到DeploymentUnit;
ServiceDeployer:将ServiceMetaData安装到Microcontainer中,并启动它。
在bootstrap-beans中还声明了三个文件扫描器和一个热部署扫描器
VFSBootstrapScanner:扫描conf/jboss-service.xml;
VFSDeployerScanner:扫描deployers文件夹;
VFSDeploymentScanner:扫描deploy文件夹;
HDScanner:热部署扫描器。
二、JBoss5部署体系的变化
相对于JBoss4的部署体系,JBoss5的部署结构发生的非常大的变化,它完全是一个新的部署体系了。
我们知道在jboss4中,deployer有个accept方法来决定是否能接受部署,在JBoss5中,没用延用这种方式,一个可能的原因是Annotation的大量使用在简化部署描述文件的同时,增加了部署的难度,在很多时候我们的服务组件需要多个Deployer对它进行部署。
举个简单的例子,我们在服务组件上使用了AOP Annotation,那么这时服务组件应该由SARDeployer和AspectDeployer都进行部署。
三、部署流程
这里以部署conf/jboss-service.xml为例来说明部署的过程,
1. 扫描
在bootstrap-beans.xml中声明的VFSBootstrapScannerImpl用于扫描conf/jboss-service.xml并创建DeploymentContext
// VFSBootstrapScannerImpl.add
DeploymentContext deployment = new AbstractDeploymentContext(file);
if( !profile.hasDeployment(deployment.getName(), DeploymentPhase.BOOTSTRAP) )
profile.addDeployment(deployment, DeploymentPhase.BOOTSTRAP);
profile为当前配置实例,与启动jboss时指定的配置是对应的。
2. 装载profile
// ProfileServiceBootstrap.loadProfile
Collection<DeploymentContext> boostraps = profile.getDeployments(DeploymentPhase.BOOTSTRAP);
for (DeploymentContext d : boostraps) {
deployer.addDeploymentContext(d);
if (first == null)
first = d;
}
deployer.process();
这里的deployer为主部署器MainDeployer,
addDeploymentContext方法有两个重要的操作:datermineStructure和addContext
datermineStructure:分析结构;
addContext:创建DeploymentUnit;
3. 开始部署
// MainDeployerImpl.java
public Collection<DeploymentContext> process(ProcessMode mode)
{
for (int i = 0; i < theDeployers.length; ++i)
{
Deployer deployer = theDeployers[i];
for (DeploymentContext context : deployContexts)
{
context.getTransientAttachments().addAttachment(ProcessMode.class, mode);
Set<DeploymentContext> components = context.getComponents();
prepareDeploy(deployer, context, components);
commitDeploy(deployer, context, components);
}
}
}
MainDeployer遍历所有已注册的Deployer,并依次用它们去部署context;
private void commitDeploy(Deployer deployer, DeploymentContext context,
Set<DeploymentContext> components)
{
DeploymentContext[] theComponents = null;
if (components != null && components.isEmpty() == false)
theComponents = components.toArray(new DeploymentContext[components.size()]);
DeploymentUnit unit = context.getDeploymentUnit();
deployer.commitDeploy(unit);
if (theComponents != null)
{
for (int i = 0; i < theComponents.length; ++i)
{
Set<DeploymentContext> componentComponents = theComponents[i].getComponents();
commitDeploy(deployer, theComponents[i], componentComponents);
}
}
}
因为DeploymentContext采用的是父子结构,所以整个部署也采用递归的方式进行部署;
那么如何确定由哪个部署器来进行部署呢?
下面是jboss-service.xml的部署流程
// AspectDeployer.java (.skip.)
public void deploy(DeploymentUnit unit)
{
List<VirtualFile> files = unit.getMetaDataFiles(null, "-aop.xml");
if (isAopArchiveOrFolder(unit)) {
// 部署采用Annotation方式的AOP定义;
deployAnnotations(unit);
}
if (files.size() > 0) {
// 部署采用xml文件的AOP定义;
deployXml(unit, files);
}
}
// BeanDeployer.java (.skip.)
public void deploy(DeploymentUnit unit)
{
// 为"-beans.xml"结尾的文件创建元数据;
createMetaData(unit, null, "-beans.xml");
}
// AbstractParsingDeployer.java
protected void createMetaData(DeploymentUnit unit,
String name, String suffix, String key)
{
// Create it
if (suffix == null)
result = parse(unit, name, result);
else
result = parse(unit, name, suffix, result);
// Add the associated deployer type if there is a result
if( result != null )
unit.getTypes().add(getType());
// Doesn't exist
if (result == null)
return;
// 注册到部署单元中,给后续的部署器使用
unit.addAttachment(key, result, getDeploymentType());
}
// KernelDeploymentDeployer.java (.skip.)
// BeanMetaDataDeployer.java (.skip.)
// AbstractSimpleRealDeployer.java
public void deploy(DeploymentUnit unit)
{
T deployment = unit.getAttachment(getDeploymentType());
if (deployment != null)
{
// Set the deployer type
unit.getTypes().add(getType());
deploy(unit, deployment);
}
}
这里的getDeploymentType()为BeanMetaData.class
// SARDeployer.java (.use.)
public void deploy(DeploymentUnit unit)
{
// 为"-service.xml"结尾的文件创建元数据,与本例的jboss-service.xml是匹配的。
createMetaData(unit, null, "-service.xml");
}
// AbstractParsingDeployer.java
protected void createMetaData(DeploymentUnit unit,
String name, String suffix, String key)
{
// Create it
if (suffix == null)
result = parse(unit, name, result);
else
result = parse(unit, name, suffix, result);
// Add the associated deployer type if there is a result
if( result != null )
unit.getTypes().add(getType());
// Doesn't exist
if (result == null)
return;
// 注册到部署单元中,给后续的部署器使用
unit.addAttachment(key, result, getDeploymentType());
}
protected ServiceDeployment parse(DeploymentUnit unit,
VirtualFile file, Document document)
{
ServiceDeploymentParser parser = new ServiceDeploymentParser(document);
// 创建ServiceDeployment;
ServiceDeployment parsed = parser.parse();
String name = file.toURI().toString();
parsed.setName(name);
List<ServiceDeploymentClassPath> classPaths = parsed.getClassPaths();
if (classPaths != null)
processXMLClasspath(unit.getDeploymentContext(), classPaths);
LoaderRepositoryConfig config = parsed.getLoaderRepositoryConfig();
if (config != null)
unit.addAttachment(LoaderRepositoryConfig.class.getName(), config);
return parsed;
}
// ServiceClassLoaderDeployer.java (.use.)
public void deploy(DeploymentUnit unit)
{
ClassLoaderFactory factory = unit.getAttachment(ClassLoaderFactory.class);
if( factory == null )
factory = this;
unit.createClassLoader(factory);
}
// ServiceDeploymentDeployer.java (.use.)
// AbstractComponentDeployer.java
public void deploy(DeploymentUnit unit)
{
super.deploy(unit);
deployComponents(unit);
}
// AbstractRealDeployer.java
public void deploy(DeploymentUnit unit)
{
Set<? extends T> deployments = unit.getAllMetaData(deploymentType);
for (T deployment : deployments)
visitor.deploy(unit, deployment);
}
这里的deploymentType为ServiceDeployment.class,所以是有值的。
// ServiceDeploymentVisitor.java
public void deploy(DeploymentUnit unit,
ServiceDeployment deployment)
{
List<ServiceMetaData> services = deployment.getServices();
if (services == null)
{
Element config = deployment.getConfig();
// 这里才真正开始解析jboss-service.xml中的mbean元素,
// 每个mbean元素对应一个ServiceMetaData
ServiceMetaDataParser parser = new ServiceMetaDataParser(config);
services = parser.parse();
deployment.setServices(services);
}
if (services == null || services.isEmpty())
return;
// 加入到部署单元中,
// 服务组件也是一个部署单元,与root部署单元是父子关系。
for (ServiceMetaData service : services)
addServiceComponent(unit, service);
}
// AbstractComponentDeployer.java
protected void deployComponents(DeploymentUnit unit)
{
Set<? extends C> components = unit.getAllMetaData(componentType);
for (C component : components)
compVisitor.deploy(unit, component);
}
这里的componentType为ServiceMetaData.class,没有值。
// ServiceDeployer.java (.use.)
// AbstractSimpleRealDeployer.java
public void deploy(DeploymentUnit unit)
{
T deployment = unit.getAttachment(getDeploymentType());
if (deployment != null)
{
// Set the deployer type
unit.getTypes().add(getType());
deploy(unit, deployment);
}
}
// 这里的getDeploymentType()为ServiceMetaData.class;
// ServiceDeployer.java
public void deploy(DeploymentUnit unit, ServiceMetaData deployment)
{
ObjectName name = deployment.getObjectName();
// 查找class loader;
ObjectName loaderName = deployment.getClassLoaderName();
if (loaderName == null)
{
ClassLoader cl = unit.getClassLoader();
if (cl != null && cl instanceof RepositoryClassLoader)
loaderName = ((RepositoryClassLoader) cl).getObjectName();
else
loaderName = defaultClassLoader;
}
// 安装组件;
controller.install(deployment, loaderName);
ServiceContext context = controller.getServiceContext(name);
if (context == null)
throw new IllegalStateException("No context for " + name);
try
{
// 组件创建,调用组件的create方法;
create(context);
try
{
// 组件启动,调用组件的start方法;
start(context);
}
catch (Throwable t)
{
destroy(name);
throw t;
}
}
catch (Throwable t)
{
remove(name);
throw t;
}
}
- 大小: 83.6 KB
分享到:
相关推荐
### JBoss5部署原理详解 #### 一、JBoss5微容器架构与启动流程 JBoss5采用了全新的微容器架构,这种设计使得整个系统更为灵活且易于扩展。启动时,JBoss5首先会加载一个名为`ProfileServiceBootstrap`的类,该类...
5. **使用工具辅助**:有一些工具可以帮助简化热部署过程,例如JRebel和Red Hat JBoss Developer Studio。这些工具可以实时跟踪代码更改,并自动同步到服务器,极大地提高了开发效率。 6. **批处理工具**:`fast...
JBoss 5是一款知名的Java应用服务器,其在类加载(Class Loading)方面有着独特的处理方式...通过理解和掌握JBoss 5的类加载原理,开发者可以更有效地管理和优化应用程序的运行时环境,提高软件的可扩展性和可维护性。
【JBoss 上线部署脚本】是针对JBoss应用服务器的一种自动化管理工具,它整合了一系列命令行操作,用于简化和优化应用的部署流程。在IT运维中,手动执行这些步骤可能会耗时且容易出错,因此,通过编写脚本可以提高...
在这一部分中,我们将深入探讨JBoss5的源代码,了解其核心组件的工作原理和架构设计。 1. **模块化架构** JBoss5采用了模块化的架构设计,这使得系统更加灵活,易于管理和扩展。每个模块都有明确的职责,如Web服务...
本篇文章将深入探讨热部署的原理以及如何在JBOSS服务器上实现这一功能。 首先,我们需要理解热部署的核心概念。热部署是通过监控应用中的类加载器,当检测到新的类文件时,自动替换旧的类,而无需重启服务器。Java...
在Jboss中部署J2EE应用可能不如商业J2EE服务器那样直观,通常需要手动编写XML配置文件,如jboss-service.xml、jboss-web.xml等,这虽然增加了配置的复杂性,但也使开发者能更深入地了解J2EE的架构和工作原理。...
本部分将深入探讨JBoss 5的源代码,了解其内部工作原理以及如何利用这些知识来优化和扩展应用程序。 JBoss 5源代码的分析可以从以下几个关键模块入手: 1. **核心服务**:JBoss的核心服务包括事务管理、安全管理、...
JBoss Seam 简介......................................................................................................................................................................... 11 Chapter 1. ...
Apache安装及JBoss部署是企业级应用中常见的技术实践,主要涉及两个核心组件:Apache HTTP Server和JBoss Application Server。Apache作为广泛使用的Web服务器,负责处理HTTP请求,并可以通过连接器与应用服务器进行...
本资源“jbossehcache缓存快捷部署”提供了集成ehcache到jboss服务器的解决方案,使得缓存服务的部署变得快速而简便。 JBoss是一个开源的应用服务器,它基于Java EE规范,为开发和运行企业级应用提供了平台。...
本教程将通过`MyEclipse`集成开发环境(IDE)和`JBoss`应用服务器来阐述如何入门JSP和Servlet的开发与部署。 首先,`MyEclipse`是基于Eclipse的增强版IDE,特别适合Java EE项目的开发,它提供了丰富的代码提示、...
JBoss Microcontainer项目的核心目标是提供一系列特性,包括反射抽象、虚拟文件系统、简单状态机、透明AOP(Aspect Oriented Programming)集成、新的类加载层、部署框架以及OSGi框架的实现。这个项目的诞生旨在创建...
这意味着在JBoss部署时,会先启动这个EJB耳朵文件中的所有服务,然后再启动包含`jboss-web.xml`的Web应用,确保了正确的启动顺序。 除了`<depends>`元素,JBoss还提供了`<depends-on>`元素,两者略有不同。`...
JBoss 的工作原理涉及多个层次,包括但不限于: 1. MBean 服务器:作为 JBoss 的核心,管理和控制应用程序组件。 2. EJB 容器:处理 EJB 的生命周期管理和事务管理。 3. JNDI(Java Naming and Directory Interface...
在JBoss平台中,Virtual File System(VFS)是一个核心组件,它为处理各种资源提供了一个统一的抽象层。...通过理解VFS的工作原理,开发者可以更好地理解和调试在JBoss环境中遇到的问题,优化应用部署和性能。
1. **热部署原理**:在传统的Java应用服务器中,更新部署的Web应用通常需要重启服务器。然而,JBoss AS 7引入了一种新的机制,当检测到应用文件的变化时,会自动重新加载受影响的类,而无需整个应用下线。这主要依赖...
- **5.4.3 MainDeploy**:MainDeploy是JBoss 5中负责处理主部署逻辑的组件。 - **5.4.4 HDScanner**:HDScanner是用于扫描硬盘上的新部署文件并自动进行部署的组件。 ##### 5.5 生命周期控制 在JBoss 5中,服务的...
对于提供的"jboss-5.1.0.GA"这个版本,它是JBoss AS(Application Server)5.1.0的General Availability版本,发布于2009年,包含了对当时Java EE 5规范的支持。下载时,你需要根据你的系统环境(Windows, Linux, ...
本文将围绕“Jboss下开发ejb应用之一会话bean的应用”这一主题,深入探讨如何在Jboss应用服务器上开发和部署会话Bean,以及涉及到的相关工具和源码。 会话Bean是EJB的一种类型,它代表了业务逻辑组件,为客户端提供...