Service Locator Pattern

本文介绍了一种ServiceLocator模式,用于抽象和简化JNDI查找过程,减少重复查找次数并缓存EJBHome接口和数据源对象,从而提高应用程序性能。
转自:http://blog.youkuaiyun.com/fitzwilliam/article/details/1539068

How JNDI lookups are accomplished can vary from vendor to vendor. In addition, repeated JNDI lookups can be expensive.
Each time a user needs a service retrieved from JNDI, they must populate the appropriate environment information, make a connection to the JNDI server and then look up the service. What is needed is a single point for creating and retrieving various services from JNDI. This is where the Service Locator pattern is useful. 
The Service Locator pattern abstracts away all JNDI lookups behind a simple-to-use interface. The Service Locator implementation used in this chapter provides methods for retrieving EJBHome interface and JDBC database connections. In addition, this Service Locator minimizes the number of JNDI lookups required by caching EJBHomes interfaces and the DataSource objects used to create JDBC connections the first time a user requests a specific EJB or JDBC connection.
 
The for the Service Locator pattern is shown below:

/*
 * The Service Locator pattern abstracts away the JNDI
 * Logic necessary for retrieving a JDBC Connection or EJBHome
 * interface
 *
 */
public class ServiceLocator {
    private static ServiceLocator serviceLocatorRef = null;
    private static HashMap ejbHomeCache = null;
    private static HashMap dataSourceCache = null;
   
    /*
     * Enumerating the different services avaialbe from the
     * Service Locator
     */
    public static final int COUNTER = 0;
    public static final int TITLEDAO = 1;
    public static final int EDITORDAO = 2;
    public static final int SUBSCRIPTIONDB = 3;
   
    /* The JNDI Names used to lookup a service */
    private static final String COUNTER_JNDINAME="counter/Counter";
    private static final String TITLEDAO_JNDINAME="title/TitleDAO";
    private static final String EDITORDAO_JNDINAME="editor/EditorDAO";
    private static final String SUBSCRIPTIONDB_JNDINAME="java:/subscriptionDS";
   
    /* References to each of the different EJB Home Interfaces */
   private static final Class COUNTERCLASSREF = CounterHome.class;
   private static final Class TITLECLASSREF = TitleDAOHome.class;
   private static final Class EDITORCLASSREF = EditorDAOHome.class;
  
   static {
       serviceLocatorRef = new ServiceLocator();
   }

  
   /* Private Constructor for the ServiceLocator */
   private ServiceLocator(){
       ejbHomeCache = new HashMap();
       dataSourceCache = new HashMap();
   }

  
   /*
    * The ServiceLocator is implemented as a Singleton.  The getInstance()
    * method will return the static reference to the ServiceLocator stored
    * inside of the ServiceLocator Class.
    */
   public static ServiceLocator getInstance(){
       return serviceLocatorRef;
   }

  
   /*
    * The getServiceName will retrieve the JNDI name for a requested
    * service.  The service is indicated by the ServiceId passed into
    * the method.
    */
   static private String getServiceName(int pServiceId) throws ServiceLocatorException{
      
       String serviceName = null;
      
       switch ( pServiceId ) {
        case COUNTER:
            serviceName = COUNTER_JNDINAME;
            break;
        case TITLEDAO:
            serviceName = TITLEDAO_JNDINAME;
            break;
        case EDITORDAO:
            serviceName = EDITORDAO_JNDINAME;
            break;
        case SUBSCRIPTIONDB:
            serviceName = SUBSCRIPTIONDB_JNDINAME;
            break;
        default:
            throw new ServiceLocatorException("Unable to locate the service requested in" +
                    "ServiceLocator.getServiceName() method.  ");
        }
       return serviceName;
   }
  
   /*
    * Returns the EJBHome Class reference for a requested service.
    * If the method can not make a match, it will throw a
    * ServiceLocatorException.
    */
    static private Class getEJBHomeRef(int pServiceId) throws ServiceLocatorException{
        Class homeRef = null;
       
        switch ( pServiceId ) {
            case COUNTER:
                homeRef = COUNTERCLASSREF;
                break;
            case TITLEDAO:
                homeRef = TITLECLASSREF;
                break;
            case EDITORDAO:
                homeRef = EDITORCLASSREF;
                break;
            default:
                throw new ServiceLocatorException("Unable to locate the service requested in" +
                        "ServiceLocator.getEJBHomeRef() method.  ");
        }
        return homeRef;
    }
   
    /*
     * The getEJBHome method will return an EJBHome interface for a
     * requested service.  If it can not find the requested EJB, it will
     * throw a ServiceLocatorException.
     *
     * The getEJBHome interface caches a requested EJBHome so that the first
     * time an EJB is requested, a home interface will be retrieved but then
     * be placed into a cache.
     */
    public EJBHome getEJBHome(int pServiceId) throws ServiceLocatorException{
        //Tring to find the JNDI Name for the requested service
        String serviceName = getServiceName(pServiceId);
        EJBHome ejbHome = null;
       
        try {
            //checking to see if I can find the EJBHome interface in cache
            if ( ejbHomeCache.containsKey(serviceName) ) {
                ejbHome = ( EJBHome ) ejbHomeCache.get(serviceName);
                return ejbHome;
            } else {
                //If I could not find the EJBHome interface in the cache, look it
                //up and the cache it.
                Context ctx = new InitialContext();
                Object jndiRef = ctx.lookup(serviceName);
               
                Object portableObj = PortableRemoteObject.narrow(jndiRef, getEJBHomeRef(pServiceId));
               
                ejbHome = ( EJBHome ) portableObj;
               
                ejbHomeCache.put(serviceName, ejbHome);
                return ejbHome;
            }
        } catch ( NamingException e ) {
            throw new ServiceLocatorException("Naming exception error in ServiceLocator.getEJBHome()", e);
        } catch (Exception e) {
            throw new ServiceLocatorException("General exception in ServcieLocator.getEJBHome", e);
        }
    }
   
    /*
     * The getDBConn() method will create a JDBC connection for the
     * requested database.  It too uses a caching algorithm to minimize
     * the number of JNDI hits that it must perform.
     */
    public Connection getDBConn(int pServiceId) throws ServiceLocatorException{
        //Getting the JNDI Service Name
        String serviceName = getServiceName(pServiceId);
        Connection conn = null;
       
        try {
            //Checking to see if the requested DataSource is in the Cache
            if ( dataSourceCache.containsKey(serviceName) ) {
                DataSource ds = ( DataSource ) dataSourceCache.get(serviceName);
                conn = ds.getConnection();
                return conn;
            } else {
                //The DataSource was not in the cache.  Retrieve it from JNDI
                //and put it in the cache.
                Context ctx = new InitialContext();
                DataSource newDataSource = ( DataSource ) ctx.lookup(serviceName);
                dataSourceCache.put(serviceName, newDataSource);
                conn = newDataSource.getConnection();
                return conn;
            }
        } catch ( SQLException e ) {
            throw new ServiceLocatorException("A SOL error has occured in ServiceLocator.getDBConn()", e);
        } catch ( NamingException e ) {
            throw new ServiceLocatorException("A JNDI Naming exception has occured in ServiceLocator.getDBConn()", e);
        } catch (Exception e) {
            throw new ServiceLocatorException("An exception has occured in ServiceLocator.getDBConn()", e);
        }
    }

 

Implementing the ServiceLocator as a Singleton pattern is extremely efficient because the class is heavily used and does not need to maintain instance information.
The use of non-final static methods in the ServiceLocator is actually in violation of the EJB specification (see section 21.4.2). However, we can get away with this because we are not dependant on our cache being consistent across Java Virtual Machine, which is the reason that the restriction exists. You must also verify that your factory classes can be used by multiple threads concurrently without synchronization; this issue is not addressed in this specification. These two issues make our solution perform better but also make it slightly less portable. We could trade some performance back for portability by doing the caching in the bean instance instead.
 
From: 
J2EE Design Patterns Applied, Wrox
by Craig A.Berry, John Carnell, Matjaz B.Juric, Meeraj Moidoo Kunnumpurath, Nadia Nashi, Sasha Romano

一、 内容概要 本资源提供了一个完整的“金属板材压弯成型”非线性仿真案例,基于ABAQUS/Explicit或Standard求解器完成。案例精确模拟了模具(凸模、凹模)与金属板材之间的接触、压合过程,直至板材发生塑性弯曲成型。 模型特点:包含完整的模具-工件装配体,定义了刚体约束、通用接触(或面面接触)及摩擦系数。 材料定义:金属板材采用弹塑性材料模型,定义了完整的屈服强度、塑性应变等真实应力-应变数据。 关键结果:提供了成型过程中的板材应力(Mises应力)、塑性应变(PE)、厚度变化​ 云图,以及模具受力(接触力)曲线,完整再现了压弯工艺的力学状态。 二、 适用人群 CAE工程师/工艺工程师:从事钣金冲压、模具设计、金属成型工艺分析与优化的专业人员。 高校师生:学习ABAQUS非线性分析、金属塑性成形理论,或从事相关课题研究的硕士/博士生。 结构设计工程师:需要评估钣金件可制造性(DFM)或预测成型回弹的设计人员。 三、 使用场景及目标 学习目标: 掌握在ABAQUS中设置金属塑性成形仿真的全流程,包括材料定义、复杂接触设置、边界条件与载荷步。 学习如何调试和分析大变形、非线性接触问题的收敛性技巧。 理解如何通过仿真预测成型缺陷(如减薄、破裂、回弹),并与理论或实验进行对比验证。 应用价值:本案例的建模方法与分析思路可直接应用于汽车覆盖件、电器外壳、结构件等钣金产品的冲压工艺开发与模具设计优化,减少试模成本。 四、 其他说明 资源包内包含参数化的INP文件、CAE模型文件、材料数据参考及一份简要的操作要点说明文档。INP文件便于用户直接修改关键参数(如压边力、摩擦系数、行程)进行自主研究。 建议使用ABAQUS 2022或更高版本打开。显式动力学分析(如用Explicit)对计算资源有一定要求。 本案例为教学与工程参考目的提供,用户可基于此框架进行拓展,应用于V型弯曲
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值