`
billy_zh
  • 浏览: 61819 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

JBoss5 部署原理

阅读更多

本文将尝试解答以下几个问题:

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采用了全新的微容器架构,这种设计使得整个系统更为灵活且易于扩展。启动时,JBoss5首先会加载一个名为`ProfileServiceBootstrap`的类,该类...

    jboss热部署配置

    5. **使用工具辅助**:有一些工具可以帮助简化热部署过程,例如JRebel和Red Hat JBoss Developer Studio。这些工具可以实时跟踪代码更改,并自动同步到服务器,极大地提高了开发效率。 6. **批处理工具**:`fast...

    jboss 5 原理 2 classloader

    JBoss 5是一款知名的Java应用服务器,其在类加载(Class Loading)方面有着独特的处理方式...通过理解和掌握JBoss 5的类加载原理,开发者可以更有效地管理和优化应用程序的运行时环境,提高软件的可扩展性和可维护性。

    Jboss 上线部署脚本

    【JBoss 上线部署脚本】是针对JBoss应用服务器的一种自动化管理工具,它整合了一系列命令行操作,用于简化和优化应用的部署流程。在IT运维中,手动执行这些步骤可能会耗时且容易出错,因此,通过编写脚本可以提高...

    Jboss5源代码-官方-第二部分

    在这一部分中,我们将深入探讨JBoss5的源代码,了解其核心组件的工作原理和架构设计。 1. **模块化架构** JBoss5采用了模块化的架构设计,这使得系统更加灵活,易于管理和扩展。每个模块都有明确的职责,如Web服务...

    类似jboss等支持热部署的服务器原理的例子

    本篇文章将深入探讨热部署的原理以及如何在JBOSS服务器上实现这一功能。 首先,我们需要理解热部署的核心概念。热部署是通过监控应用中的类加载器,当检测到新的类文件时,自动替换旧的类,而无需重启服务器。Java...

    J2EE应用服务器Jboss+Tomcat安装攻略

    在Jboss中部署J2EE应用可能不如商业J2EE服务器那样直观,通常需要手动编写XML配置文件,如jboss-service.xml、jboss-web.xml等,这虽然增加了配置的复杂性,但也使开发者能更深入地了解J2EE的架构和工作原理。...

    Jboss5源代码-官方-第一部分

    本部分将深入探讨JBoss 5的源代码,了解其内部工作原理以及如何利用这些知识来优化和扩展应用程序。 JBoss 5源代码的分析可以从以下几个关键模块入手: 1. **核心服务**:JBoss的核心服务包括事务管理、安全管理、...

    JBoss Seam 工作原理、seam和hibernate的范例、RESTFul的seam、seam-gen起步、seam组件、配置组件、jsf,jboss、标签、PDF、注解等等

    JBoss Seam 简介......................................................................................................................................................................... 11 Chapter 1. ...

    Apache安装及jboss部署说明文档

    Apache安装及JBoss部署是企业级应用中常见的技术实践,主要涉及两个核心组件:Apache HTTP Server和JBoss Application Server。Apache作为广泛使用的Web服务器,负责处理HTTP请求,并可以通过连接器与应用服务器进行...

    jboss集成 ehcache 快捷部署缓存

    本资源“jbossehcache缓存快捷部署”提供了集成ehcache到jboss服务器的解决方案,使得缓存服务的部署变得快速而简便。 JBoss是一个开源的应用服务器,它基于Java EE规范,为开发和运行企业级应用提供了平台。...

    MyEclipse+JBoss开发部署jsp和servlet入门源码

    本教程将通过`MyEclipse`集成开发环境(IDE)和`JBoss`应用服务器来阐述如何入门JSP和Servlet的开发与部署。 首先,`MyEclipse`是基于Eclipse的增强版IDE,特别适合Java EE项目的开发,它提供了丰富的代码提示、...

    jboss5原理-1(module).docx

    JBoss Microcontainer项目的核心目标是提供一系列特性,包括反射抽象、虚拟文件系统、简单状态机、透明AOP(Aspect Oriented Programming)集成、新的类加载层、部署框架以及OSGi框架的实现。这个项目的诞生旨在创建...

    解决jboss中启动的优先级的问题

    这意味着在JBoss部署时,会先启动这个EJB耳朵文件中的所有服务,然后再启动包含`jboss-web.xml`的Web应用,确保了正确的启动顺序。 除了`&lt;depends&gt;`元素,JBoss还提供了`&lt;depends-on&gt;`元素,两者略有不同。`...

    jboss 下载(httpwww.jboss.org)

    JBoss 的工作原理涉及多个层次,包括但不限于: 1. MBean 服务器:作为 JBoss 的核心,管理和控制应用程序组件。 2. EJB 容器:处理 EJB 的生命周期管理和事务管理。 3. JNDI(Java Naming and Directory Interface...

    jboss原理-3(vfs).docx

    在JBoss平台中,Virtual File System(VFS)是一个核心组件,它为处理各种资源提供了一个统一的抽象层。...通过理解VFS的工作原理,开发者可以更好地理解和调试在JBoss环境中遇到的问题,优化应用部署和性能。

    jboss-as-web.Final-RECOMPILE.jar.rar

    1. **热部署原理**:在传统的Java应用服务器中,更新部署的Web应用通常需要重启服务器。然而,JBoss AS 7引入了一种新的机制,当检测到应用文件的变化时,会自动重新加载受影响的类,而无需整个应用下线。这主要依赖...

    JBoss MicroContainer分析及应用

    - **5.4.3 MainDeploy**:MainDeploy是JBoss 5中负责处理主部署逻辑的组件。 - **5.4.4 HDScanner**:HDScanner是用于扫描硬盘上的新部署文件并自动进行部署的组件。 ##### 5.5 生命周期控制 在JBoss 5中,服务的...

    jboss-服务器下载

    对于提供的"jboss-5.1.0.GA"这个版本,它是JBoss AS(Application Server)5.1.0的General Availability版本,发布于2009年,包含了对当时Java EE 5规范的支持。下载时,你需要根据你的系统环境(Windows, Linux, ...

    Jboss下开发ejb应用之一会话bean的应用

    本文将围绕“Jboss下开发ejb应用之一会话bean的应用”这一主题,深入探讨如何在Jboss应用服务器上开发和部署会话Bean,以及涉及到的相关工具和源码。 会话Bean是EJB的一种类型,它代表了业务逻辑组件,为客户端提供...

Global site tag (gtag.js) - Google Analytics