EJB 最佳实践:工业强度的 JNDI 优化

程序化广告行业(23/89):深度剖析广告效果评估指标 大家好,我一直希望能和大家一起在技术领域不断探索、共同进步。在之前的文章中,我们了解了程序化广告中腾讯的业务布局和广告效果评估的基础概念,今天让我们进一步深入剖析广告效果评估的各项指标,这对理解程序化广告的运作机制至关重要 阅读详情
Column iconBrett McLaughlin 在这篇 EJB 最佳实践专栏文章中研究了 JNDI 查找,它是几乎所有的 EJB 交互中不可或缺并且常见的部分。遗憾的是,JNDI 操作几乎总是需要性能开销。在本技巧文章中,Brett 向您展示了 home 接口工厂是如何降低您 EJB 应用程序中 JNDI 查找开销的。

每种 EJB 组件(会话、实体和消息驱动的)都有 home 接口。home 接口是 bean 的操作基础;一旦您找到它,就可以使用该 bean 的功能。EJB 应用程序依靠 JNDI 查找来访问其 bean 的 home 接口。因为 EJB 应用程序往往运行多个 bean,并且因为许多组件中经常使用 JNDI 查找,所以应用程序大部分性能开销都花费在这些查找上。

在这篇技巧文章中,我们将研究一些最常用的 JNDI 优化。特别地,我们将向您展示如何将高速缓存和通用助手类组合使用,以创建针对 JNDI 开销的工厂风格的解决方案。

减少上下文实例
清单 1 显示了一段典型的 EJB 代码,它需要多次 JNDI 查找。请花一点时间研究代码,然后我们将对它进行优化以获得更佳性能。

清单 1. 典型的 EJB 查找


public boolean buyItems(PaymentInfo paymentInfo, String storeName,
List items) {
      // Load up the initial context
      Context ctx = new InitialContext();

      // Look up a bean's home interface
      Object obj = ctx.lookup("java:comp/env/ejb/PurchaseHome");
      PurchaseHome purchaseHome =
       (PurchaseHome)PortableRemoteObject.narrow(obj, PurchaseHome.class);
      Purchase purchase = purchaseHome.create(paymentInfo);

      // Work on the bean
      for (Iterator i = items.iterator(); i.hasNext(); ) {
          purchase.addItem((Item)i.next());
      }

      // Look up another bean
      Object obj = ctx.lookup("java:comp/env/ejb/InventoryHome");
      InventoryHome inventoryHome =
       (InventoryHome)PortableRemoteObject.narrow(obj, InventoryHome.class);
      Inventory inventory = inventoryHome.findByStoreName(storeName);

      // Work on the bean
      for (Iterator i = items.iterator(); i.hasNext(); )
          inventory.markAsSold((Item)i.next());
      }

      // Do some other stuff
}

尽管这个示例多少有点刻意,但它确实揭示了使用 JNDI 时的一些最明显的问题。对于初学者,您应该问问自己,新建 InitialContext 对象是否必需。很可能在应用程序代码的其它地方已经装入了这个上下文,而我们又在这里创建了一个新的。高速缓存 InitialContext 实例会立即促使性能提高,如清单 2 所示:

清单 2. 高速缓存 InitialContext 实例


public static Context getInitialContext() {
      if (initialContext == null) {
          initialContext = new InitialContext();
      }

      return initialContext;
}

通过对 getInitialContext() 使用助手类,而不是为每个操作都实例化一个新的 InitialContext,我们将遍布在应用程序中的上下文数量减少为一个。

哦 — 线程化会怎么样?
如果您对此处提出的解决方案的线程化感到担心,那大可不必。两个线程同时进行 getInitialContext() 是绝对有可能的(从而一次创建两个上下文),但只有首次调用该方法时才会发生此类错误。因为问题至多只会发生一次,所以同步是不必要的,实际上,同步引入的复杂性比它所解决的复杂性更多。

优化查找
高速缓存上下文实例这个步骤的方向是正确的,但仅这样做,还不足以完成优化。我们每次调用 lookup() 方法时都会执行一次新查找,并返回 bean 的 home 接口的新实例。至少,JNDI 查找通常是这样编码的。但如果每个 bean 都只有一个 home 接口,并在多个组件上共享这个接口,这样不是更好吗?

我们可以高速缓存每个单独的 bean 引用,而不是反复查找 PurchaseHome 或 InventoryHome 的 home 接口;这是一种解决方案。但我们真正想要的是一种更通用的机制:在 EJB 应用程序中高速缓存 home 接口。

答案是创建通用助手类,它既可以为应用程序中的每个 bean 获取初始上下文,又可以为它们查找 home 接口。此外,这个类还应该能够为各种应用程序组件管理每个 bean 的上下文。清单 3 中所示的通用助手类将充当 EJB home 接口的工厂:

清单 3. EJB home 接口工厂


package com.ibm.ejb;

import java.util.Map;
import javax.ejb.EJBHome;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class EJBHomeFactory {

      private static EJBHomeFactory;

      private Map homeInterfaces;
      private Context context;

      // This is private, and can't be instantiated directly
      private EJBHomeFactory() throws NamingException {
          homeInterfaces = new HashMap();

          // Get the context for caching purposes
          context = new InitialContext();

          /**
           * In non-J2EE applications, you might need to load up
           *   a properties file and get this context manually. I've
           *   kept this simple for demonstration purposes.
           */
      }

      public static EJBHomeFactory getInstance() throws NamingException {
          // Not completely thread-safe, but good enough 
          // (see note in article)
          if (instance == null) {
              instance = new EJBHomeFactory();
          }
          return instance;
      }

      public EJBHome lookup(String jndiName, Class homeInterfaceClass) 
            throws NamingException {

          // See if we already have this interface cached
          EJBHome homeInterface = (EJBHome)homeInterfaces.get(homeClass);

          // If not, look up with the supplied JNDI name
          if (homeInterface == null) {
              Object obj = context.lookup(jndiName);
              homeInterface =
               (EJBHome)PortableRemoteObject.narrow(obj, homeInterfaceClass);

              // If this is a new ref, save for caching purposes
              homeInterfaces.put(homeInterfaceClass, homeInterface);
          }
          return homeInterface;
      }
}

EJBHomeFactory 类内幕
home 接口工厂的关键在 homeInterfaces 映射中。该映射存储了供使用的每个 bean 的 home 接口;这样,home 接口实例可以反复使用。您还应注意,映射中的关键并不是传递到 lookup() 方法的 JNDI 名称。将同一 home 接口绑定到不同 JNDI 名称是很常见的,但这样做会在您的映射中产生副本。通过依靠类本身,您就可以确保最终不会为同一个 bean 创建多个 home 接口。

将新的 home 接口工厂类插入清单 1 的原始代码,这样将会产生优化的 EJB 查找,如清单 4 所示:

清单 4. 改进的 EJB 查找


public boolean buyItems(PaymentInfo paymentInfo, String storeName,
List items) {

      EJBHomeFactory f = EJBHomeFactory.getInstance();

      PurchaseHome purchaseHome =
          (PurchaseHome)f.lookup("java:comp/env/ejb/PurchaseHome", 
          PurchaseHome.class);
      Purchase purchase = purchaseHome.create(paymentInfo);

      // Work on the bean
      for (Iterator i = items.iterator(); i.hasNext(); ) {
          purchase.addItem((Item)i.next());
      }

      InventoryHome inventoryHome =
          (InventoryHome)f.lookup("java:comp/env/ejb/InventoryHome", 
          InventoryHome.class);
      Inventory inventory = inventoryHome.findByStoreName(storeName);

      // Work on the bean
      for (Iterator i = items.iterator(); i.hasNext(); ) {
          inventory.markAsSold((Item)i.next());
      }

      // Do some other stuff
}

随着时间的推进,除了更清晰之外(至少按我的观点),以上工厂优化的 EJB 查找将执行得更快。您第一次使用这个新类时,将花费所有正常查找开销(假定应用程序的其它部分没有付出过这种开销),但将来的所有 JNDI 查找都将继续使用原先的查找结果。还有必要指出,home 接口工厂不会干扰您容器的bean 管理。容器管理的是 bean 实例,而不是这些 bean 实例的 home 接口。您的容器还将管理实例交换,以及其它您希望它执行的任何优化。

在 EJB 最佳实践的下一篇文章中,我将向您展示如何启用对实体 bean的管理访问,而又不必将它们直接暴露给您应用程序的 Web 层。到那时,我们网上见。

参考资料

  • Sun Microsystems 的 EJB 技术主页是所有与 EJB 技术相关内容的良好参考资料。

  • TheServerSide 提供了许多有关 J2EE 的文章和信息。

  • jGuru EJB fundamentals 教程(developerWorks,2001 年 3 月)提供了 Enterprise JavaBeans 技术的全面介绍,并特别关注了 EJB 组件在分布式计算案例中的作用、体系架构、扩展 API,以及使用 EJB 技术的基础。

  • 访问 developerWorks Java 教程页面以获取其它免费的 EJB 和 J2EE 相关教程列表。

  • 在 developerWorks Java 技术专区您可以找到数百篇有关 Java 编程各个方面的文章。

关于作者
Brett McLaughlin 的照片Brett McLaughlin 从 Logo 时代(还记得那个小三角形么?)就开始从事计算机工作了。他现在专门研究用 Java 和 Java 相关技术构建应用程序基础结构。过去几年他一直在 Nextel Communications 和 Allegiance Telecom, Inc. 致力于实现这些基础结构。Brett是 Java Apache 项目 Turbine 的共同创始人之一,该项目用 Java servlet 为 Web 应用程序开发构建可重用的组件体系架构。他还是 EJBoss 项目(一个开放源码的 EJB 应用程序服务器)和 Cocoon(一个开放源码的 XML Web 发布引擎)的参与者之一。

Arduino、ESP32驱动BMP390L数字大气压传感器(压力传感器) BMP390L是一款博世新研发的工业级专用数字气压传感器,具有极高的温度稳定性、低漂移、低功耗。 阅读详情

相关推荐

IDEA 2023.2.3全平台安装指南:Mac/Windows/Linux一键激活(附最新补丁获取)

本文提供IDEA 2023.2.3在Mac、Windows和Linux三大平台的一键安装与激活指南,包含最新补丁获取方法。详细讲解各系统安装流程、性能调优设置及高效开发技巧,帮助开发者快速配置并提升工作效率。

weixin_28832121的博客 397

[转载]EJB 最佳实践: 工业强度的 JNDI 优化

EJB 最佳实践: 工业强度的 JNDI 优化Brett McLaughlin 在这篇 EJB 最佳实践专栏文章中研究了 JNDI 查找,它是几乎所有的 EJB 交互中不可或缺并且常见的部分。遗憾的是,JNDI 操作几乎总是需...

congji3817的博客 163

OPC与AI智能体集成实战:一人公司的技术栈构建与避坑指南

1. 先搞清楚“一人公司”和“AI工具”到底在解决什么问题 最近看到不少关于“裸辞搞OPC一人公司”和“AI时代骗局”的讨论,结合搜索热词里高频出现的 openclaw 、 AI编程 、 OPC ,我觉得有必要把这里面的水搅一搅,说点实在的。 首先得拆开看。标题里混了三个东西: 一人公司 、 OPC/OpenClaw 、 AI培训 。它们被放在一起讨论“骗局”,但本质上解决的是不同层面的问题。 一人公司 ,或者说个人工作室、独立开发者模式,核心是 用最小化团队(甚至一个人)去承接项目、开发产品或提供服务 。

weixin_29038345的博客 320

JNDI的优化

代码很简单,将Home缓存到cache中,以后每次从cache中取出。更进一步 EJBLocalObject也可以缓存,这样大大增加EJB处理速度。Service Locator如下:package com.jdon.servicelocator.web;import java.util.HashMap;import java.util.Map;import java.util.Collect

Concentrating on Architectures 1000

ULN2003驱动28BYJ-48步进电机详解(附:51 32代码讲解)

本文介绍了28BYJ-48步进电机的驱动原理以及注意事项,并展示了极简 32 51驱动代码

qq_41818650的博客 1万+

读书笔记|智能运维系统落地方案

对于互联网公司来说,系统复杂化导致的人工运维成本激增已经是普遍现象,采用智能运维是行之有效的应对策略。智能运维的核心思想是利用算法来处理海量运维数据,积累运维经验,从而代替人工思考判断,以自动化的过程实现风险的预防、发现、定位和处理。而智能运维系统是其中的重中之重,但建设企业应用智能运维系统,不是应用运维部独立规划设计就可以完成的,它需要业务、产品、开发、基础设施运维多部门协同才能顺利实施。 那么,作为运维人员,您是否了解智能运维系统的架构?如果参与规划建设智能运维系统,该怎么着手呢?下面我们立足实际需求

xiaoshuaca的博客 681

Tomcat优化,JNDI,连接池,数据源

什么是JNDI JNDI的简单应用 什么是连接池技术 连接池 性能 连接池技术与传统数据库连接的比较 连接池技术工作原理 为什么使用连接池 传统数据库连接方式的不足 企业级开发需要稳健和高效的数据访问层 数据源 数据源DataSource 访问数据源 什么是JNDI?JNDI:访问命名以及目录的。(Java命名和目录接口) 是一组在Java应用中访问命名和目录服务的API 通过名称将资源与

爱是与世界平行 1133

Docker 磁盘占用过多问题处理过程记录

Docker 磁盘爆满问题处理

MR.骑士道 3554

利用 JNDI 方式远程获取数据源

有时候数据库的密码并不能让所有人知道,为此我们可以提供JNDI访问方式,让编码者来获取,一: 针对JBoss服务器,客户端获取方式如下: public class Test { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method s...

shang222的专栏 1690

华为防火墙——本地Portal认证

配置IP地址、路由、Nat策略使得内网主机可以访问公网服务器对网段不进行认证,对网段进行portal认证。

m0_49864110的博客 3259

ETAS工具导入DBC生成Com协议栈

ETAS工具导入DBC主要也是生成arxml用的,ETAS推荐使用Cobra导入,本文介绍导入过程及注意事项不管是导入DBC还是arxml,本质上都是为了生成对应的com协议栈,目的是为了减少重复的工作量,所以,前期定义好收发的矩阵很重要,一般导入一次之后,后面就可以按变更点手动更改了。

赞的博客 1711

EJB 最佳实践: 工业强度的 JNDI 优化

每种 EJB 组件(会话、实体和消息驱动的)都有 home 接口。home 接口是 bean 的操作基础;一旦您找到它,就可以使用该 bean 的功能。EJB 应用程序依靠 JNDI 查找来访问其 bean 的 home 接口。因为 EJB 应用程序往往运行多个 bean,并且因为许多组件中经常使用 JNDI 查找,所以应用程序大部分性能开销都花费在这些查找上。在这篇技巧文章中,我们将研究一些

leehom_zlj的专栏 429

[Dify] 如何构建一个带评分功能的 Dify AI 教练系统

本文介绍如何利用Dify开源平台构建具备自动评分功能的AI教练系统。系统通过Prompt设计AI教练角色,使用OpenAPI定义评分工具接口,结合工作流编排实现提问、回答收集、评分和反馈的全流程。文章详细讲解了从AI教练身份设定、多维度评分标准设计到前端可视化展示的实现方法,并提供了可扩展建议,适用于语言训练、面试模拟等多种场景。该系统展示了Dify平台在构建智能化评估应用方面的优势,实现零代码开发专业AI教练解决方案。

技术小甜甜:传播可落地技术,帮助个人和企业降低解决真实场景问题的成本 333

EJB 最佳实践--工业强度的 JNDI 优化

 Brett McLaughlin 在这篇 EJB 最佳实践专栏文章中研究了 JNDI 查找,它是几乎所有的 EJB 交互中不可或缺并且常见的部分。遗憾的是,JNDI 操作几乎总是需要性能开销。在本技巧文章中,Brett 向您展示了 home 接口工厂是如何降低您 EJB 应用程序中 JNDI 查找开销的。每种 EJB 组件(会话、实体和消息驱动的)都有 home 接口。home 

kinglino520的专栏 325

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

EJB的HOME接口的高速缓存

公司的platform产品中用到了基于EJB的工作流,而platform每次调用工作流时,都是通过JNDI对home接口进行lookup,这个动作是很耗性能的,而以前竟然没有进行缓存,汗ing........,刚刚看到了Brett McLaughlin写的一篇EJB 最佳实践:工业强度的 JNDI 优化>> 于是赶紧改写了一个home接口的工厂类:EJBHomeFactory.java 

1729

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

很有帮助 最佳实践

 http://www.ibm.com/developerworks/cn/java/j-ejb-col/   验证助手类   构建更好的异常处理框   改进远程对象设计   用值对象加速您的 RMI 事务   工业强度的 JNDI 优化   实体 bean 保护   动态委派   数据验证出现在什么地方最合适 ...

Hedes 168

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

小心new InitialContext()

最近因为工作需要开始学习Ejb3,遇到了一个让我很郁闷的事情,做一下小小的总结——小心new InitialContext()。   在做客户端的时候,发现连接服务器,搜索数据库,然后返回结果集。每一次执行的时候,第一次总要花更多的时间,之后每一次操作时间就要快很多了。期间找了很多方法,都行不通。一开始以为是Ejb服务器建立服务消耗时间,后来觉得不对,因为Jboss启动的时候,已经将服务启动了...

蓝天上,白云飘;茶碗中,加瓦游 996

java 组件技术

Java SE 中的技术: JavaBeans Component Architecture 是一个为 Java 平台定义可重用软件组件的框架,可以在图形化构建工具中设计这些组件。 Java Foundation Classes(Swing)(JFC)是一套 Java 类库,支持为基于 Java 的客户机应用程序构建 GUI 和图形化功能。(参见教程 “Swing 入门”;“使用

bj_scholar的专栏 828

EJB客户端应用通过JNDI调用远程EJB的方法详解

EJB服务开发完毕后,可以打包为*.jar,并部署到应用服务器,如JBoss AS 7或WildFlly AS 10,供EJB客户端程序调用。 EJB客户端程序是调用服务器上部署的EJB方法的应用。从运行环境的不同,可以将EJB客户端程序分为两大类: 独立应用的客户端(如单元测试程序)部署到JBoss AS7 server的客户端(客户端服务器上的程序调用另一个EJB服务器上的EJB方

成长的足迹 7146

EJB3.0远程超时问题

背景:客户端和EJB服务分别在不同的机器上            URL配置:props.setProperty("java.naming.provider.url", "192.168.2.2:1099"); 错误信息: Could not obtain connection to any of these urls: 192.168.2.2:1099 and discovery fa

冰狼的专栏 875

InnoDB 内存结构总览:Change Buffer、AHI 与 Log Buffer

本文系统梳理InnoDB内存结构中的ChangeBuffer、Adaptive Hash Index(AHI)与LogBuffer。ChangeBuffer缓存二级索引页不在内存时的变更,减少随机IO,仅在页加载时合并;聚簇索引修改立即执行,因数据本身不可延后。AHI基于高频等值查询自动构建哈希索引,加速定位,仅支持等值操作。LogBuffer为redo log内存缓冲,配合磁盘日志实现崩溃恢复。三者均服务于性能优化,其中ChangeBuffer与AHI共享BufferPool空间,而LogBuffer独立

bksczm的博客 282

Spring AI + GPT-5.5 + Ollama 配置教程:Base URL、超时与流式调用

由于不同 Spring AI、Spring Boot 小版本之间仍可能存在差异,创建项目时应检查 Spring Initializr、Spring AI BOM 和官方兼容矩阵,不要直接复制旧教程中的 Starter 名称和版本号。多人项目最好隔离不同客户端,并在脱敏前提下记录最终 URL、状态码、请求耗时、请求 ID 和模型 ID。Spring AI 接入模型 API,至少要同时确认 Starter、Base URL、请求路径、API Key、模型 ID、连接超时、读取超时和流式客户端这 8 项。

2601_95893075的博客 232

V8 机制、手写核心函数与 TypeScript 类型体操

或固定初始化(如数组先定长、对象先给全字段)保持类型与形状稳定;这些都比"换框架"更基础。只能处理纯数据(丢函数、Date、RegExp、循环引用报错)。生产级深拷贝要处理:原始值短路、循环引用、V8(Chrome / Node 的 JS 引擎)不是"解释一行跑一行"那么简单,它用。图:V8 执行流程——解释执行 + 热点优化,优化失败会 Deopt 回退。JS 内存自动管理,但"自动"不等于"不会漏"。是"固定间隔最多执行一次"。手写 Promise 是"懂异步"的试金石。是"停下后才执行最后一次",

qq_38468358的博客 346

Java EE 进阶:8.MyBatis 操作数据库(入门)(第一弹)

Java EE 进阶:8.MyBatis 操作数据库(入门)(第一弹)

要努力去发光,而不是被照亮~ 126

Spring Boot 数据源与 MyBatis(-Plus) 自定义配置详解

本文详解 Spring Boot 中单数据源环境下 HikariCP 与 MyBatis-Plus 的自定义配置。通过手动声明 SqlSessionFactory,实现下划线转驼峰、日志输出、一级缓存策略等精细化控制。结合 HikariCP 核心参数调优(如最大连接数、连接生命周期),确保高性能与稳定性。适用于仅需访问单一数据库的场景,避免多数据源复杂性,兼顾性能与可维护性。

BADAO_LIUMANG_QIZHI的博客 196

LeetCode Hot 100 二叉树专题(二)3 题(Java)

本篇文章共 3 题:543. 二叉树的直径、102. 二叉树的层序遍历、108. 将有序数组转换为二叉搜索树。 每道题都统一按「① 题目分析 & 解题思路 → ② 常见解法(附代码)及讲解 → ③ 知识点总结」的顺序组织;代码使用 Java 编写,节点定义沿用 LeetCode 默认的 TreeNode。

2401_88612756的博客 365
上一篇: 通过JavaMail访问Hotmail邮箱
下一篇: 使用struts+spring+hibernate 组装web应用
hlplusplus
博客等级 码龄22年 0粉丝 27原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值