JBoss是一个非常优秀的J2EE的Application Server,研究  它的源代码有助于我们更好的理解J2EE的各种技术。  本系列拟从四个方面分析Jboss源码:  1.EJB Container实现  2.Transaction实现  3.Persistence Mapping  4.Client到Server端的Invocation
  ------------------------------------------------------------------- 先说第1点:EJB Container实现。  1.1 EJB Pool  我们知道,EJB Container 会维护一个EJB池,  在多个client间共享,避免频繁创建销毁对象的开销。  让我们来看看Jboss实现的Pool:  EJB分EntityBean,MDB,Stateless/Stateful Session Bean,  而Jboss中也对应的有EntityInstancePool,MessageDrivenInstancePool,  StatefulSessionInstancePool,StatelessSessionInstancePool.  让我们先从这4个类的共同基类AbstractInstancePool看起:  class AbstractInstancePool实现了接口InstancePool,该接口有以下几个方法:  EnterpriseContext get() throws Exception;  void free(EnterpriseContext ctx);  void discard(EnterpriseContext ctx);  int getCurrentSize();  public int getMaxSize();  -------------------------------------------------------------------- 先对EnterpriseContext作番说明。EnterpriseContext的作用  就是把具体的EJB instance和它的metadata联系起来。  该类签名为:  public abstract class EnterpriseContext,  有4个子类,EntityEnterpriseContext,MessageDrivenEnterpriseContext,  StatefulSessionEnterpriseContext,StatelessSessionEnterpriseContext。  分别对应4种类型的EJB。  EnterpriseContext中有几个重要的成员变量。  /** The EJB instance */  Object instance;  /** The container using this context */  Container con; //Container这个类是JBoss用来代表对EJB提供Transaction,Security,Pool等服务的类,我们回头还会再说。  /** Only StatelessSession beans have no Id, stateful and entity do */  Object id; 
  /** The transaction associated with the instance */  Transaction transaction; //Transaction,我们下节再说. 
  // Constructors -------------------------------------------------- 
  public EnterpriseContext(Object instance, Container con)  {  this.instance = instance;  this.con = con;  } 
  public Object getInstance()  {  return instance;  }  public Container getContainer() {  return con;  } 
  public void setId(Object id) {  this.id = id;  } 
  public Object getId() {  return id;  } 
  public void setTransaction(Transaction transaction) {  this.transaction = transaction;  } 
  public Transaction getTransaction() {  return transaction;  } 
  /**  * Get the EJBContext object  */  public abstract EJBContext getEJBContext(); //由子类实现 
  //返回javax.ejb.EJBContext,注意这个EJBContext是  EJB规范要求提供给EJB的Context,与JBoss自己实现类EnterpriseContext没有关系。 
  /** The instance is being used. This locks it\'s state */  int locked = 0;  public void lock()  {  locked ++;  } 
  public void unlock() {  locked --;  } 
  public boolean isLocked() {  return locked != 0;  }  //lock这个成员变量表示当前这个EJB instance有没人在用。  //这个变量用来给Reentrance,以及canPassviate用.  /**  * before reusing this context we clear it of previous state called  * by pool.free()  * 从pool里取出来的时候没有关联任何EJB instance和Transaction信息  * 在返还pool的时候把这些信息清掉。  */  public void clear() {  this.id = null;  this.locked = 0;  this.transaction = null;  }  //-------------------------------------------------------------------------------------  protected boolean isContainerManagedTx()  {  BeanMetaData md = (BeanMetaData)con.getBeanMetaData();  return md.isContainerManagedTx();  }  //从关联的container拿出对应的metadata,判断是否CMT.  //注意这里con是Container成员变量,可不是什么连接,连接一般缩写为conn,  //我一开始就搞混了:)  //BeanMetaData这些MetaData的子类都是从xml配置里头读出来的Metadata构造的,  //没什么神秘的.  这个类里头还有两个inner class,EJBContextImpl implements EJBContext,  UserTransactionImpl implements UserTransaction。EJBContextImpl等  讲解过Container再说,UserTransaction等下节再说。 
  现在让我们来看看EnterpriseContext的几个子类:  首先类比一下几个子类的成员变量:  EntityEnterpriseContext:  private EJBObject ejbObject;  private EJBLocalObject ejbLocalObject;  private EntityContext ctx; 
  StatefulSessionEnterpriseContext  private EJBObject ejbObject;  private EJBLocalObject ejbLocalObject;  private SessionContext ctx; 
  StatelessSessionEnterpriseContext  EJBObject ejbObject;  EJBLocalObject ejbLocalObject;  SessionContext ctx; 
  MessageDrivenEnterpriseContext:  private MessageDrivenContext ctx;  看来除了MDB没有对应的EJBObject/EJBLocalObject,其他统统都有:)  学过EJB的人都知道,在语法上EJB instance 是implements  EntityBean/SessionBean/MessageDrivenBean (这3个interface有一个共同的  interface: public interface EnterpriseBean extends Serializable,  EnterpriseBean 是个Marker接口,里头什么都没有,好像Serializable接口一样,只说明  实现它的是个EJB.而EntityBean/SessionBean/MessageDrivenBean 有对应的  void ejbActivate() throws EJBException, RemoteException;  void ejbLoad() throws EJBException, RemoteException;  一些方法需要实现。(虽然常常是空实现:),由容器作了很多事)  至于EJBObject/EJBLocalObject 在语法上都是非直接实现的,代表EJB instance暴露出的Remote/Local 接口。既然这些EJB instance非直接实现这些接口,那么这些接口如何与具体的EJB instance相关联,我们讲到Container类时就知道了。  ---------------------------------------------------------------------------------- 
 
  EnterpriseContext的子类EntityEnterpriseContext的构造函数 public EntityEnterpriseContext(Object instance, Container con)  throws RemoteException  {  super(instance, con);  ctx = new EntityContextImpl(); //这是EJBContextImpl的子类,不急着说:)  ((EntityBean)instance).setEntityContext(ctx);//看看,原来set...Context是在这里调用的//其它instance实现的什么ejbCreate(),EJBLoad,EJBActive()到底是什么时候  调用的呢?接下来我们慢慢找,这可散布在各地呢:)  }  //其他几个子类的构造函数前3行也都如此,是类似的。  对于StatelessSessionEnterpriseContext和MessageDrivenEnterpriseContext,紧接的是 
  Method ejbCreate = instance.getClass().getMethod(\"ejbCreate\", new Class[0]);  ejbCreate.invoke(instance, new Object[0]);  //看看,来了一个ejbCreate:),对于StatelessSessionBean,一上来就ejbCreate()了~  接下来看点简单的:对于EnterpriseContext,  有public abstract void discard() throws RemoteException;  对于MessageDriven...的  public void discard() throws RemoteException  {  ((MessageDrivenBean)instance).ejbRemove();  }  对于StatelessSession的  public void discard() throws RemoteException  {  ((SessionBean)instance).ejbRemove();  }  对于StatefulSession...的  public void discard() throws RemoteException  {  // Do nothing  }  对于Entity....  public void discard() throws RemoteException  {  ((EntityBean)instance).unsetEntityContext();  }  //discard 是在AbstractInstancePool中的  void discard(EnterpriseContext ctx);调用的 
  /**  * Discard an anonymous instance after invocation.  * This is called if the instance should not be reused, perhaps due to some  * exception being thrown from it.  *  * @param ctx The context to discard.  */  public void discard(EnterpriseContext ctx)  {  ctx.discard();  }  AbstractInstancePool还有个free方法:  public void free(EnterpriseContext ctx) {  ctx.clear();//记得ctx只是清掉id,transaction等,返回pool,准备复用么?  //discard是在发生错误的时候,不希望扩大影响,于是discard掉,  //而对应get()的free方法只是把EnterpriseContext返还给pool.  }  ---------------------------------------------------------------------------------- 
  专门对于Stateful....Context有设置EJB instance的函数  /**  * During activation of stateful session beans we replace the instance  * by the one read from the file.  */  public void setInstance(Object instance)  {  this.instance = instance;  ((SessionBean)instance).setSessionContext(ctx);  }  注意在4种...Context中,只有Stateful...Context签名  public class StatefulSessionEnterpriseContext  extends EnterpriseContext  implements Serializable  多了个implements Serializable,(其他都没有),  这是为了支持Activation/Passviation,Passviation的时候  把EJB Instance写到文件中。  在StatefulSessionEnterpriseContext中有这样两个方法  private void writeObject(ObjectOutputStream out)  throws IOException, ClassNotFoundException  {  // do nothing  } 
  private void readObject(ObjectInputStream in)  throws IOException, ClassNotFoundException  {  // do nothing  }  //说明序列化的时候StatefulSessionEnterpriseContext本身不需要  写出什么状态,只有对应的EJB instance才需要写出状态。 
现在来看AbstractInstancePool的源码,由于内容太多  就不详细解释了。  先看Abstract...Pool的create(Object instance)函数热热身~  Abstract...Pool  // Protected -----------------------------------------------------  protected abstract EnterpriseContext create(Object instance)  throws Exception;  对Entity...Pool  protected EnterpriseContext create(Object instance)  throws Exception  {  return new EntityEnterpriseContext(instance, getContainer());  }  其他3种Pool类似。  再回头看Abstract..Pool  /** The pool data structure */  protected EnterpriseContext[] pool;  protected int currentIndex = -1;  /** The maximum number of instances allowed in the pool */  protected int maxSize = 30;  /** The minimum size of the pool */  protected int minSize = 0;  /** determine if we reuse EnterpriseContext objects i.e. if we actually do pooling */  protected boolean reclaim = false;//对于MDB和StatelessSessionBean,这个变量被设为true,// for MDB, we *do* pool // for SLSB, we *do* pool  ok,现在来看pool的重头戏,get()/free(EnterpriseContext ctx)函数  (discard(EnterpriseContext ctx)前面讲过,不再重复)  这几个函数也是Interface InstancePool里头要实现的接口:)  闲话少说,来看代码~~  protected boolean minSizeInitialized = false;  /**  * Get an instance without identity.  * Can be used by finders,create-methods, and activation  *  * @return Context /w instance  * @exception RemoteException  */  public EnterpriseContext get() {  //pool里头有东东就拿出来  synchronized (pool)  {  if (currentIndex > -1)  {  EnterpriseContext ctx = pool[currentIndex];  pool[currentIndex--] = null;  return ctx;  }  }  //initialize a small fixed size of instance at startup.  if (!minSizeInitialized)  {  minSizeInitialized = true;  synchronized (pool)  {  for (int i = 0; i < minSize; i++)  {  pool[++currentIndex] = create(container.createBeanClassInstance());  }  }  }  // Pool is empty, create an instance  return create(container.createBeanClassInstance());  }  /**  * Return an instance after invocation.  *  * Called in 2 cases:  * a) Done with finder method  * b) Just removed  *  * @param ctx  */  public void free(EnterpriseContext ctx) {  ctx.clear();  synchronized (pool)  {  if (currentIndex + 1 < maxSize)  {  pool[++currentIndex] = ctx;  }  }  }  对于Entity...Pool,他overwrite了free  /**  * Return an instance to the free pool. Reset state  *  * 
 Called in 3 cases:  * 
  * 
- Done with finder method 
 * 
 - Removed 
 * 
 - Passivated 
 *  
 *  * @param ctx  */  public void free(EnterpriseContext ctx)  {  // If transaction still present don\\\\\\\\\\\\\\\'t do anything (let the instance be GC)  if (ctx.getTransaction() != null)  {  return ;  }  super.free(ctx);  }  -----------------------------------------------------  而Stateful....Pool的free方法overwrite了Abstract...Pool的,  public synchronized void free(EnterpriseContext ctx)  {  discard(ctx);//干脆就discard掉不用了~  }  剩下的下回再讲,先预告2个类体系:  1.AbstractInstanceCache ,有EntityInstanceCache和StatefulSessionInstanceCache 子类。对于Entity,用它的  PrimaryKey作Cache的Key,对于Stateful,Jboss也会付给  每个instance一个唯一标定的值用来做CacheKey.  Abstract...Cache与Abstract...Pool结合使用,得到好的Performance。  2.public abstract class Container,  有EntityContainer,MessageDrivenContainer,Stateful/StatelessSessionContainer  4个子类,用来提供对EJB instance的transaction/security/pool等服务。  //看看它的成员变量,就能猜个大概  /** This is the TransactionManager */  protected TransactionManager tm;  /** This is the SecurityManager */  protected AuthenticationManager sm;  /** This is the instancepool that is to be used */  protected InstancePool instancePool;  
  
开始讲Container,以前说过Container有4种子类,分别对应4种类型的EJB.  一个Container是所有Container plugins(注1)和metadata(注2)的集散地,the container plugins可以从container拿到metadata和其他container plugins.EJB部署的时候会创建相应的Container.Container基本不做太多事,主要delegate给plugins作事情。  ok,让我们来看看Container的成员变量:  /**  * This is the new metadata. it includes information from both ejb-jar and  * jboss.xml the metadata for the application can be accessed trough  * metaData.getApplicationMetaData()  */  protected BeanMetaData metaData; 
  /** This is the EnterpriseBean class */  protected Class beanClass; 
  /** This is the Home interface class */  protected Class homeInterface; 
  /** This is the Remote interface class */  protected Class remoteInterface; 
  /** The local home interface class */  protected Class localHomeInterface; 
  /** The local inteface class */  protected Class localInterface; 
  /** This is the TransactionManager */  protected TransactionManager tm; 
  /** This is the SecurityManager */  protected AuthenticationManager sm; 
  /** This is the realm mapping */  protected RealmMapping rm; 
  /** This is the bean lock manager that is to be used */  protected BeanLockManager lockManager; 
  /** This is the application that this container is a part of */  protected EjbModule ejbModule;  //ejbModule作为一个单元部署的Module,比如一个ejb-jar就是一个Module,  /*这个 ejb-jar里头可能有多个entitybean,sessionbean,那么对于 每个entitybean,sessionbean  都会有一个对应的container,而这些东东共享一个ejbModule.*/  /**  * Returns a new instance of the bean class or a subclass of the bean class.  * This factory style method is speciffically used by a container to supply  * an implementation of the abstract accessors in EJB2.0, but could be  * usefull in other situations. This method should ALWAYS be used instead  * of getBeanClass().newInstance();  *  * @return the new instance  *  * @see java.lang.Class#newInstance  */  public Object createBeanClassInstance() throws Exception {  return getBeanClass().newInstance();  }  public Class getBeanClass()  {  return beanClass;  } 
  注意EntityContainer overwrite了这个方法:  /**  * Returns a new instance of the bean class or a subclass of the bean class.  * If this is 1.x cmp, simply return a new instance of the bean class.  * If this is 2.x cmp, return a subclass that provides an implementation  * of the abstract accessors.  *  * @see java.lang.Class#newInstance  *  * @return The new instance.  */  public Object createBeanClassInstance() throws Exception {  return persistenceManager.createBeanClassInstance();  }  其中 persistenceManager声明为:  /** This is the persistence manager for this container */  protected EntityPersistenceManager persistenceManager;  //persitenceManager和PersistenceStore我们将在第3部分讲解。  现在先给个大略印象:  BMPPersistenceManager实现  public Object createBeanClassInstance() throws Exception {  return con.getBeanClass().newInstance();  } 
  CMPPersistenceManager实现  EntityPersistenceStore store;  public Object createBeanClassInstance() throws Exception  {  return store.createBeanClassInstance();  }  -------------------------------------------------------------------  ok,接下来看看Container如何处理Client过来的Invocation。  一切精彩尽在下面这个函数  public Object invoke(Invocation mi);  //Invocation代表了Client端过来的调用  //Invocation里头有些成员变量,指明了要调用的Method,  //args,Transaction信息,principle/credential等信息。 
  /** Maps for MarshalledInvocation mapping */  protected Map marshalledInvocationMapping = new HashMap(); 
  public Object invoke(Invocation mi)  throws Exception  {  Thread currentThread = Thread.currentThread();  ClassLoader callerClassLoader = currentThread.getContextClassLoader();  //保存原来的classloader,在finally里恢复 
  Method m = null;  Object type = null; 
  try  {  currentThread.setContextClassLoader(this.classLoader);(注3)  // Check against home, remote, localHome, local, getHome,  // getRemote, getLocalHome, getLocal  type = mi.getType(); 
  if(type == InvocationType.REMOTE ||  type == InvocationType.LOCAL)  {  if (mi instanceof MarshalledInvocation)  {  ((MarshalledInvocation) mi).setMethodMap(  marshalledInvocationMapping);  }  return internalInvoke(mi);  }  else if(type == InvocationType.HOME ||  type == InvocationType.LOCALHOME)  {  if (mi instanceof MarshalledInvocation)  {  ((MarshalledInvocation) mi).setMethodMap(  marshalledInvocationMapping);  return internalInvokeHome(mi);  }  else  {  throw new MBeanException(new IllegalArgumentException(  \\\\\\\"Unknown invocation type: \\\\\\\" + type));  }  }  finally  {  currentThread.setContextClassLoader(callerClassLoader);  }  } 
  ----------------------------------------------------------------  MarshalledInvocation是Invocation的字类,代表可以从  Client传到Server的Invocation  public class Invocation... 
  public class MarshalledInvocation  extends Invocation  implements java.io.Externalizable  而Invocation是在server端的调用链(Interceptor链,注4)  间传递.  -------------------------------------------------------  ok,稍喘口气,接下来看看两个Internal的invoke,  都是abstract,在字类实现  public abstract Object internalInvokeHome(Invocation mi)  throws Exception;  public abstract Object internalInvoke(Invocation mi)  throws Exception;  至于具体实现么,TO BE CONITUE拉:)  ----------------------------------------------------  注1:ContainerPlugin可以放在容器里头的东东。  接口为interface ContainerPlugin :  void setContainer(Container con);  有InstancePool,InstanceCache,EJBProxyFactory/LocalProxyFactory,  EntityPersistenceManager/EntityPersistenceStore等Plugin  注2:metadata描述部署的信息,比如ejb-jar.xml,描述什么东东是  entitybean,什么东东是sessionbean,session的是BMP/CMP等等。  注3: Container的成员变量protected ClassLoader classLoader;  用来load 这个Container里头的类和资源,之所以要专门设一个Container  的classLoader是因为能使EJB re-deployable.(JBoss定期扫描deploy目录,  如果ejb更改就进行redeploy,如果ejb删除就undeploy)  注4: Jboss会建立一个Interceptor 链,Invocation经过链传递。  比如有EntityInterceptor,SecurityInterceptor,TransactionInterceptor,  InvokerInterceptor,一个套一个,每个Interceptor对当前Invocation进行一些处理  ,比如检查权限,事物等等,然后传给下一个Interceptor处理(这是Filter and Pipe模式了,也算是AOP拉~,别人说  JBoss 这个Interceptor实现属于AOP方言特别重:)。  所有的Interceptor都是现  Object invokeHome(Invocation mi) throws Exception;  和Object invoke(Invocation mi) throws Exception;  在自己invoke的最后,  经过所有的Interceptor之后,调用下一个。  看看AbstractInterceptor的缺省实现:  public abstract class AbstractInterceptor  implements Interceptor 
  public Object invokeHome(final Invocation mi) throws Exception {  //do sth.  return getNext().invokeHome(mi);  }  public Object invoke(final Invocation mi) throws Exception {  //do sth.  return getNext().invoke(mi);  }  在经过重重Interceptor之后  最后到达EJB Instance 调用你要的那个方法。
  
其实实现很简单:  public Object internalInvokeHome(Invocation mi) throws Exception  {  return getInterceptor().invokeHome(mi);  } 
  public Object internalInvoke(Invocation mi) throws Exception  {  // Invoke through interceptors  return getInterceptor().invoke(mi);  } 
  public Interceptor getInterceptor()  {  return interceptor;  }  protected Interceptor interceptor;  //这是Container建立的Interceptor链的头一个,从这里调起~  再来看看 void addInterceptor(Interceptor in);这个函数  在Interceptor链最后再挂一个Interceptor  public void addInterceptor(Interceptor in)  {  if (interceptor == null)  {  interceptor = in;  }  else  {  Interceptor current = interceptor;  while (current.getNext() != null)  {  current = current.getNext();  } 
  current.setNext(in);  }  }  ------------------------------------------------------------------------  附带再提一下pool和cache  /** This is the instance cache for this container */  protected InstanceCache instanceCache; 
  /** This is the instancepool that is to be used */  protected InstancePool instancePool;  /** This is the instancepool that is to be used */  protected InstancePool instancePool;  -------------------------------------------------------------  public void setInstanceCache(InstanceCache ic)  {  if (ic == null)  throw new IllegalArgumentException(\\\"Null cache\\\"); 
  this.instanceCache = ic;  ic.setContainer(this);  } 
  public InstanceCache getInstanceCache()  {  return instanceCache;  }  public void setInstancePool(InstancePool ip)  {  if (ip == null)  throw new IllegalArgumentException(\\\"Null pool\\\"); 
  this.instancePool = ip;  ip.setContainer(this);  }  -----------------------------------------------------------------------  ok,现在让我们来看看Container都对EJB Instance暴露出来的  方法都作了些什么,还有如何调用EJB Instance的方法.  这里有重要的2个Map  /**  * These are the mappings between the home interface methods and the  * container methods.  * 所有Home 方法映射都存这里  */  protected Map homeMapping = new HashMap(); 
  /**  * These are the mappings between the remote/local interface methods and the  * bean methods.  * 所有EJBObject方法映射都存这里  */  protected Map beanMapping = new HashMap();  --------------------------------------------------------------------------  class ContainerInterceptor  extends AbstractContainerInterceptor  //AbstractContainerInterceptor基本上什么都不做,不用看  //ContainerInterceptor代表Container setup的Interceptor调用  //链的最后一个,到这里你就会看到他调用了你的EJB Instance的方法  {  public Object invokeHome(Invocation mi) throws Exception  {  // Invoke and handle exceptions  Method miMethod = mi.getMethod();  Method m = (Method) homeMapping.get(miMethod);  if (m.getDeclaringClass().equals(EntityContainer.class))  {  try  {  return m.invoke(EntityContainer.this, new Object[] { mi });  }  catch (Exception e)  {  rethrow(e);  }  }  else // Home method  {  try  {  return m.invoke(((EnterpriseContext) mi.getEnterpriseContext()).getInstance(), mi.getArguments());  }  catch (Exception e)  {  rethrow(e);  }  } 
  // We will never get this far, but the compiler does not know that  throw new org.jboss.util.UnreachableStatementException();  } 
  public Object invoke(Invocation mi) throws Exception  {  // Get method  Method miMethod = mi.getMethod();  Method m = (Method) beanMapping.get(miMethod);  if( m == null )  {  String msg = \\\"Invalid invocation, check your deployment packaging\\\"  +\\\", method=\\\"+miMethod;  throw new EJBException(msg);  } 
  // Select instance to invoke (container or bean)  if (m.getDeclaringClass().equals(EntityContainer.class))  {  // Invoke and handle exceptions  try  {  return m.invoke(EntityContainer.this, new Object[]{ mi });  }  catch (Exception e)  {  rethrow(e);  }  }  else  {  // Invoke and handle exceptions  try  {  return m.invoke(((EnterpriseContext) mi.getEnterpriseContext()).getInstance(), mi.getArguments());  }  catch (Exception e)  {  rethrow(e);  }  } 
  // We will never get this far, but the compiler does not know that  throw new org.jboss.util.UnreachableStatementException();  }  } 
  //可以看到,两个Map作了个映射,Map的Key为  在你想要调用的EJB instance方法,value为实际  实现的方法,可能就是EJB instance本身实现的方法,  或者是容器帮忙实现的(比如CMP 中abstract get/set方法,  只能容器帮忙实现).  从这里也可以看出来,JBoss主要是保存了方法映射来处理  EJBObject/EJBLocalObject 的调用请求,  而其他一些J2EE AS是通过动态生成EJBObject/EJBLocalObject  和你的EJB Instance的字类来实现的(而JBoss就算在CMP2.0  里动态生成了一个东东,那也不是EJB Instance的子类)。 
  
ok,基本弄明白了Container的原理之后,我们来看看  到底Container的一些初始化操作  Container算是一项服务,  JBoss在deploy/undeploy/redeploy时会调用  与Service相关的几个函数:  protected void createService() throws Exception {}  protected void startService() throws Exception {}  protected void stopService() throws Exception {}  protected void destroyService() throws Exception {}  让我们从EntityContainer看起: 
  protected void createService() throws Exception  {  // Associate thread with classloader  ClassLoader oldCl = Thread.currentThread().getContextClassLoader();  Thread.currentThread().setContextClassLoader(getClassLoader()); 
  try  {  // Acquire classes from CL  //从metadata拿到Home/Remote的Class  if (metaData.getHome() != null)  homeInterface = classLoader.loadClass(metaData.getHome());  if (metaData.getRemote() != null)  remoteInterface = classLoader.loadClass(metaData.getRemote()); 
  // Call default init  // 调用Container里头的CreateService,我们回头再看  super.createService(); 
  //建立刚才所说的两个Method映射Map  setupBeanMapping();  setupHomeMapping(); 
  // Map the interfaces to Long  setupMarshalledInvocationMapping(); 
  // Initialize pool  instancePool.create();  // Try to register the instance pool as an MBean  try  {  ObjectName containerName = super.getJmxName();  Hashtable props = containerName.getKeyPropertyList();  props.put(\\\"plugin\\\", \\\"pool\\\");  ObjectName poolName = new ObjectName(containerName.getDomain(), props);  server.registerMBean(instancePool, poolName);  }  catch(Throwable t)  {  log.debug(\\\"Failed to register cache as mbean\\\", t);  } 
  // Init instance cache  instanceCache.create();  // Try to register the instance cache as an MBean  try  {  ObjectName containerName = super.getJmxName();  Hashtable props = containerName.getKeyPropertyList();  props.put(\\\"plugin\\\", \\\"cache\\\");  ObjectName cacheName = new ObjectName(containerName.getDomain(), props);  server.registerMBean(instanceCache, cacheName);  }  catch(Throwable t)  {  log.debug(\\\"Failed to register cache as mbean\\\", t);  } 
 
  for (Iterator it = proxyFactories.keySet().iterator(); it.hasNext(); )  {  String invokerBinding = (String)it.next();  EJBProxyFactory ci = (EJBProxyFactory)proxyFactories.get(invokerBinding);  ci.create();  } 
 
 
  // Init persistence  persistenceManager.create(); 
  // Initialize the interceptor by calling the chain  Interceptor in = interceptor;  while (in != null)  {  in.setContainer(this);  in.create();  in = in.getNext();  }  readOnly = ((EntityMetaData)metaData).isReadOnly();  }  finally  {  // Reset classloader  Thread.currentThread().setContextClassLoader(oldCl);  }  } 
 
 
  protected void startService() throws Exception  {  // Associate thread with classloader  ClassLoader oldCl = Thread.currentThread().getContextClassLoader();  Thread.currentThread().setContextClassLoader(getClassLoader()); 
  try  {  // Call default start  super.startService(); 
  // Start container invokers  for (Iterator it = proxyFactories.keySet().iterator(); it.hasNext(); )  {  String invokerBinding = (String)it.next();  EJBProxyFactory ci = (EJBProxyFactory)proxyFactories.get(invokerBinding);  ci.start();  } 
  // Start instance cache  instanceCache.start(); 
  // Start persistence  persistenceManager.start(); 
  // Start the instance pool  instancePool.start(); 
  // Start all interceptors in the chain  Interceptor in = interceptor;  while (in != null)  {  in.start();  in = in.getNext();  }  }  finally  {  // Reset classloader  Thread.currentThread().setContextClassLoader(oldCl);  }  } 
  protected void stopService() throws Exception  {  // Associate thread with classloader  ClassLoader oldCl = Thread.currentThread().getContextClassLoader();  Thread.currentThread().setContextClassLoader(getClassLoader()); 
  try  {  //Stop items in reverse order from start  //This assures that CachedConnectionInterceptor will get removed  //from in between this and the pm before the pm is stopped.  // Stop all interceptors in the chain  Interceptor in = interceptor;  while (in != null)  {  in.stop();  in = in.getNext();  } 
  // Stop the instance pool  instancePool.stop(); 
 
  // Stop persistence  persistenceManager.stop(); 
  // Stop instance cache  instanceCache.stop(); 
  // Stop container invoker  for (Iterator it = proxyFactories.keySet().iterator(); it.hasNext(); )  {  String invokerBinding = (String)it.next();  EJBProxyFactory ci = (EJBProxyFactory)proxyFactories.get(invokerBinding);  ci.stop();  } 
  // Call default stop  super.stopService();  }  finally  {  // Reset classloader  Thread.currentThread().setContextClassLoader(oldCl);  }  } 
  protected void destroyService() throws Exception  {  // Associate thread with classloader  ClassLoader oldCl = Thread.currentThread().getContextClassLoader();  Thread.currentThread().setContextClassLoader(getClassLoader()); 
  try  {  // Destroy container invoker  for (Iterator it = proxyFactories.keySet().iterator(); it.hasNext(); )  {  String invokerBinding = (String)it.next();  EJBProxyFactory ci = (EJBProxyFactory)proxyFactories.get(invokerBinding);  ci.destroy();  } 
  // Destroy instance cache  instanceCache.destroy();  instanceCache.setContainer(null);  try  {  ObjectName containerName = super.getJmxName();  Hashtable props = containerName.getKeyPropertyList();  props.put(\\\"plugin\\\", \\\"cache\\\");  ObjectName cacheName = new ObjectName(containerName.getDomain(), props);  server.unregisterMBean(cacheName);  }  catch(Throwable ignore)  {  } 
  // Destroy persistence  persistenceManager.destroy();  persistenceManager.setContainer(null); 
  // Destroy the pool  instancePool.destroy();  instancePool.setContainer(null);  try  {  ObjectName containerName = super.getJmxName();  Hashtable props = containerName.getKeyPropertyList();  props.put(\\\"plugin\\\", \\\"pool\\\");  ObjectName poolName = new ObjectName(containerName.getDomain(), props);  server.unregisterMBean(poolName);  }  catch(Throwable ignore)  {  } 
  // Destroy all the interceptors in the chain  Interceptor in = interceptor;  while (in != null)  {  in.destroy();  in.setContainer(null);  in = in.getNext();  } 
  MarshalledInvocation.removeHashes(homeInterface);  MarshalledInvocation.removeHashes(remoteInterface); 
  // Call default destroy  super.destroyService();  }  finally  {  // Reset classloader  Thread.currentThread().setContextClassLoader(oldCl);  }  }  ------------------------------------------------------------  protected void setupBeanMapping() throws Exception  {  try {  if (remoteInterface != null)  {  Method[] m = remoteInterface.getMethods();  setupBeanMappingImpl( m, \\\"javax.ejb.EJBObject\\\" );  }  if (localInterface != null)  {  Method[] m = localInterface.getMethods();  setupBeanMappingImpl( m, \\\"javax.ejb.EJBLocalObject\\\" );  }  }  catch (Exception e)  {  // ditch the half built mappings  homeMapping.clear();  beanMapping.clear(); 
  throw e;  }  } 
  private void setupBeanMappingImpl( Method[] m, String intfName )  throws Exception  {  for (int i = 0; i < m.length; i++)  {  if (!m.getDeclaringClass().getName().equals(intfName))  {  // Implemented by bean  beanMapping.put(m, beanClass.getMethod(m.getName(), m.getParameterTypes()));  }  else  {  // Implemented by container  beanMapping.put(m, getClass().getMethod(m.getName(),  new Class[] { Invocation.class }));  }  }  }  private void setupHomeMappingImpl(Method[] m,  String finderName,  String append)  throws Exception  {  // Adrian Brock: This should go away when we don\\\'t support EJB1x  boolean isEJB1x = metaData.getApplicationMetaData().isEJB1x(); 
  for (int i = 0; i < m.length; i++)  {  String methodName = m.getName();  try  {  try // Try home method  {  String ejbHomeMethodName = \\\"ejbHome\\\" + methodName.substring(0,1).toUpperCase() + methodName.substring(1);  homeMapping.put(m, beanClass.getMethod(ejbHomeMethodName, m.getParameterTypes())); 
  continue;  }  catch (NoSuchMethodException ignore) {} // just go on with other types of methods 
 
  // Implemented by container (in both cases)  if (methodName.startsWith(\\\"find\\\"))  {  homeMapping.put(m, this.getClass().getMethod(finderName, new Class[] { Invocation.class }));  }  else if (methodName.equals(\\\"create\\\") ||  (isEJB1x == false && methodName.startsWith(\\\"create\\\")))  {  homeMapping.put(m, this.getClass().getMethod(\\\"create\\\"+append, new Class[] { Invocation.class }));  beanMapping.put(m, this.getClass().getMethod(\\\"postCreate\\\"+append, new Class[] { Invocation.class }));  }  else  {  homeMapping.put(m, this.getClass().getMethod(methodName+append, new Class[] { Invocation.class }));  }  }  catch (NoSuchMethodException e)  {  throw new NoSuchMethodException(\\\"Could not find matching method for \\\"+m);  }  }  } 
  protected void setupHomeMapping() throws Exception  {  try {  if (homeInterface != null)  {  Method[] m = homeInterface.getMethods();  setupHomeMappingImpl( m, \\\"find\\\", \\\"Home\\\" );  }  if (localHomeInterface != null)  {  Method[] m = localHomeInterface.getMethods();  setupHomeMappingImpl( m, \\\"findLocal\\\", \\\"LocalHome\\\" );  } 
  // Special methods 
  // Get the One on Handle (getEJBObject), get the class  Class handleClass = Class.forName(\\\"javax.ejb.Handle\\\"); 
  // Get the methods (there is only one)  Method[] handleMethods = handleClass.getMethods(); 
  //Just to make sure let\\\'s iterate  for (int j=0; j {  //Get only the one called handle.getEJBObject  if (handleMethods[j].getName().equals(\\\"getEJBObject\\\"))  {  //Map it in the home stuff  homeMapping.put(handleMethods[j],  this.getClass().getMethod(\\\"getEJBObject\\\",  new Class[] {Invocation.class}));  }  }  }  catch (Exception e)  {  // ditch the half built mappings  homeMapping.clear();  beanMapping.clear(); 
  throw e;  }  }  
 
  |