每个bean可能会有很多方法,一般我们通过一个delegate来调用sessionbean中的方法,而非直接调用sessionbean,delegate中只是简单的对每个相对应的sessionbean的public方法的简单封装,在调用的时候省去了每次对home的查找和ejb对象的create,但是可能我们的bean会有很多方法,如果每个bean都写这样一个delegate,这样工作量就会很大,而且也不便于以后系统的移植,比如说,原来使用ejb实现,现在要改用jdo直接操作数据库,而通过运用java的reflect技术,就能较好地实现这些要求。首先,定义了一个FacadeDelegate的抽象类,用来实现对sessionbean的home的查找,代码如下: 
import javax.ejb.*; 
import testejb.util.common.*; 
import testejb.util.resource.*; 
  
public abstract class FacadeDelegate{ 
  private static String type = Resource.RemoteType; 
  public FacadeDelegate() { 
  } 
  public EJBHome getHome(String jindiName,Class className) 
  { 
    EJBHome home = null; 
    ServerLocatorAdapter adapter = ServerLocatorAdapter.getInstance(); 
    try 
    { 
      home = (EJBHome)adapter.getHome(type, jindiName, className); 
    } 
    catch(Exception e) 
    { 
      System.err.println(e.getMessage() + jindiName + className.toString()); 
    } 
    return home; 
  } 
  
} 
其中ServerLocatorAdapter是一个用来根据是local还是remote调用ejb对象而通过不同的方法查找home的类,如果type为local则调用LocalServerLocate中的方法,如果type为remote则调用RemoteServerLocate中的方法,获得home。代码如下: 
import java.util.*; 
import java.lang.reflect.*; 
  
import testejb.util.resource.*; 
  
public class ServerLocatorAdapter { 
  private Map cache;//用来缓存home 
  private static ServerLocatorAdapter me; 
  public static ServerLocatorAdapter getInstance() 
  { 
    if(me == null) 
      me = new ServerLocatorAdapter(); 
    return me; 
  } 
  
  //取得home 
public Object getHome(String type,String jndiHomeName,Class className) throws Exception 
  { 
    Object home = null; 
    if(cache.containsKey(jndiHomeName)) 
      return cache.get(jndiHomeName); 
    if(Resource.LocalType.equals(type)) 
    { 
      home = getLocalHome(jndiHomeName,className); 
      cache.put(jndiHomeName,home); 
      return home; 
    } 
    if(Resource.RemoteType.equals(type)) 
    { 
      home = getRemoteHome(jndiHomeName,className); 
      cache.put(jndiHomeName,home); 
      return home; 
    } 
  
    return home; 
  } 
  //取得local home 
  private Object getLocalHome(String jndiHomeName,Class className) throws Exception 
  { 
Class myClass = Class.forName(Resource.LocalClass); 
// Resource. LocalClass =”testejb.util.common. LocalServerLocator 
Method method = myClass.getMethod(Resource.LocalConstractMethod,null); 
// Resource. LocalConstractMethod =” getInstance” 
    LocalServerLocator local = null; 
    local = (LocalServerLocator)method.invoke(myClass,null); 
    return local.getLocalHome(jndiHomeName,className); 
  
  
} 
//取得remote home 
  private Object getRemoteHome(String jndiHomeName,Class className) throws Exception 
  { 
Class myClass = Class.forName(Resource.RemoteClass);  
// Resource.RemoteClass =”testejb.util.common.RemoteServerLocator” 
Method method = myClass.getMethod(Resource.RemoteConstractMethod,null); 
// Resource.RemoteConstractMethod=” getInstance” 
    RemoteServerLocator remote = null; 
    remote = (RemoteServerLocator)method.invoke(myClass,null); 
    return remote.getHome(jndiHomeName,className); 
  
  } 
  private ServerLocatorAdapter() { 
    // 为cache提供线程安全的保证 
    cache = Collections.synchronizedMap(new HashMap()); 
  } 
  
} 
其中Resource为资源类,其中通过对配置文件的读取,取得一些指定的配置信息。 
RemoteServerLocator和LocalServerLocator是两个根据不同的调用方式取得home借口的具体实现类,代码如下: 
LocalServerLocator: 
import javax.naming.*; 
import javax.rmi.PortableRemoteObject; 
import java.util.*; 
import javax.ejb.*; 
  
  
public class LocalServerLocator { 
  
  private Context ic; 
  private Map cache;//缓存home 
  private static LocalServerLocator me; 
  
  public static LocalServerLocator getInstance() 
  { 
    if(me == null) 
    { 
      try 
      { 
        me = new LocalServerLocator(); 
      } 
      catch(Exception e) 
      { 
        System.err.println(e.getCause()); 
        System.err.println(e.getMessage()); 
      } 
  
    } 
    return me; 
  } 
  
  public EJBLocalHome getLocalHome(String jndiHomeName, Class className) throws Exception { 
        EJBLocalHome home = null; 
        try { 
            if (cache.containsKey(jndiHomeName)) { 
                home = (EJBLocalHome) cache.get(jndiHomeName); 
            } else { 
                Object objref = ic.lookup(jndiHomeName); 
                home = (EJBLocalHome) objref; 
                cache.put(jndiHomeName, home); 
            } 
        } catch (NamingException ne) { 
            System.err.println(jndiHomeName); 
            throw ne; 
        } catch (Exception e) { 
            throw e; 
        } 
        return home; 
    } 
  
  
  private LocalServerLocator() throws Exception{ 
    try 
    { 
      ic = new InitialContext(); 
      // 为cache提供线程安全的保证 
      cache = Collections.synchronizedMap(new HashMap()); 
    } 
    catch(NamingException ne) 
    { 
      throw ne; 
    } 
    catch(Exception e) 
    { 
      throw e; 
    } 
  
  
  } 
  
} 
  
RemoteServerLocator 
import javax.naming.*; 
import javax.rmi.PortableRemoteObject; 
import java.util.*; 
import javax.ejb.*; 
  
  
public class RemoteServerLocator{ 
  private Context ic; 
  private Map cache; 
  private static RemoteServerLocator me; 
  
  public static RemoteServerLocator getInstance() 
  { 
    if(me == null) 
    { 
      try 
      { 
        me = new RemoteServerLocator(); 
      } 
      catch(Exception e) 
      { 
        System.err.println(e.getMessage()); 
      } 
    } 
    return me; 
  } 
  
  public EJBHome getHome(String jndiHomeName, Class className) throws Exception { 
        EJBHome home = null; 
        try { 
            if (cache.containsKey(jndiHomeName)) { 
                home = (EJBHome) cache.get(jndiHomeName); 
            } else { 
                Object objref = ic.lookup(jndiHomeName); 
                Object obj = PortableRemoteObject.narrow(objref, className); 
                home = (EJBHome) obj; 
                cache.put(jndiHomeName, home); 
            } 
        } catch (NamingException ne) { 
            System.err.println(jndiHomeName); 
            throw ne; 
        } catch (Exception e) { 
            throw e; 
        } 
        return home; 
    } 
  
  private RemoteServerLocator() throws Exception{ 
    try { 
            ic = getInitialContext(); 
            // 为cache提供线程安全的保证 
            cache = Collections.synchronizedMap(new HashMap()); 
        } catch (NamingException ne) { 
            throw ne; 
        } catch (Exception e) { 
            throw e; 
        } 
  
  } 
  
  private javax.naming.Context getInitialContext() throws NamingException { 
        java.util.Hashtable JNDIParm = new java.util.Hashtable(); 
        JNDIParm.put(Context.PROVIDER_URL, "your server address"); 
        JNDIParm.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory"); 
        return new InitialContext(JNDIParm); 
    } 
  
} 
  
对上面这些调用机制有个了解之后,下面就是来具体的实现动态委派了,再此定义了一个FacadeDelegateImp类,继承了FacadeDelegate类。先看一下代码,然后对此作解释,这样比较清楚一些 
import testejb.delegate.common.*; 
import javax.ejb.*; 
import java.lang.reflect.*; 
import java.util.*; 
  
  
public class FacadeDelegateImp extends FacadeDelegate { 
  private static FacadeDelegateImp me; 
  private Map cache; 
  private HashMap methodMap; 
  private Object object; 
  
  public static FacadeDelegateImp getInstance() 
  { 
    if(me == null) 
      me = new FacadeDelegateImp(); 
    return me; 
} 
//init方法是在调用invoke之前对要调用的sessionbean进行初始化 
  public void init(String jindiName, String className) { 
    EJBHome home = null; 
    if(cache.containsKey(jindiName)) 
      home = (EJBHome)cache.get(jindiName); 
    else 
    { 
      try 
      { 
        home = super.getHome(jindiName, Class.forName(className));//调用父类的的方法取得home 
      } 
      catch(Exception e) 
      { 
        System.err.println(e.getMessage()); 
      } 
      cache.put(jindiName,className); 
    } 
    try 
    { 
      object = home.getClass().getMethod("create", null).invoke(home, null);//调用home的//create方法,取得ejbObject 
      methodMap = new HashMap(); 
//将ejbObject中所有的方法存入methodMap中 
      Method[] aryMethod = object.getClass().getMethods(); 
      if(aryMethod != null && aryMethod.length > 0) 
      { 
        for (int i = 0; i < aryMethod.length; i++) { 
          methodMap.put(aryMethod[i].getName(), aryMethod[i]); 
        } 
      } 
    } 
    catch(Exception e) 
    { 
      System.err.println(e.getMessage()); 
    } 
  } 
  //此init方法是对一般java类初始化 
  public void init(String className,Object[] args) 
  { 
    boolean flage = false; 
    if(cache.get(className) != null) 
      object = cache.get(className); 
    else 
    { 
      try { 
        Class myClass = Class.forName(className); 
        if (args != null && args.length > 0) { 
          Class[] type = new Class[args.length]; 
          for (int i = 0; i < type.length; i++) { 
            type[i] = args[i].getClass(); 
          } 
          Constructor constructor = myClass.getConstructor(type); 
          object = constructor.newInstance(args); 
          cache.put(className, object); 
        } 
        else { 
          object = myClass.newInstance(); 
          cache.put(className, object); 
        } 
      } 
      catch (Exception e) { 
        System.err.println(e.getMessage()); 
      } 
    } 
    Method[] methods = object.getClass().getMethods(); 
    methodMap = new HashMap(); 
    for(int i = 0; i< methods.length; i++) 
      methodMap.put(methods[i].getName(),methods[i]); 
  } 
  
  public Object invoke(String method, Object[] args,String jindiName, String className) 
  { 
    if("init".equals(method)) 
    { 
      this.init(jindiName, className); 
      return null; 
    } 
    if(methodMap == null) 
      this.init(jindiName, className); 
    Method tmpMethod = (Method)methodMap.get(method); 
    if(tmpMethod != null) 
    { 
      try 
      { 
        return tmpMethod.invoke(object, args); 
      } 
      catch(Exception e) 
      { 
        System.err.println(e.getMessage()); 
      } 
    } 
    return null; 
  } 
  
  public Object invoke(String method, Object[] args, String className) 
  { 
    if("init".equals(method)) 
    { 
      this.init(className,args); 
      return null; 
    } 
    if(methodMap == null) 
      System.err.println("not init"); 
    Method tmpMethod = (Method)methodMap.get(method); 
    if(tmpMethod != null) 
    { 
      try 
      { 
        return tmpMethod.invoke(object, args); 
      } 
      catch(Exception e) 
      { 
        System.err.println(e.getMessage()); 
      } 
    } 
    return null; 
  } 
  
  
  
  private FacadeDelegateImp() { 
    cache = Collections.synchronizedMap(new HashMap()); 
  } 
  
  
} 
参考文章:EJB 最佳实践:动态委派 作者:O'Reilly and Associates 
这是本人第一次再此发表技术性文章,对ejb也是了解不深,如有什么不对处,还请各位高手指教。  
 
  |