<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    kapok

    垃圾桶,嘿嘿,我藏的這么深你們還能找到啊,真牛!

      BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      455 隨筆 :: 0 文章 :: 76 評(píng)論 :: 0 Trackbacks
    http://blog.csdn.net/stripbolt/archive/2004/10/24/149705.aspx

    JBoss是一個(gè)非常優(yōu)秀的J2EE的Application Server,研究
    它的源代碼有助于我們更好的理解J2EE的各種技術(shù)。
    本系列擬從四個(gè)方面分析Jboss源碼:
    1.EJB Container實(shí)現(xiàn)
    2.Transaction實(shí)現(xiàn)
    3.Persistence Mapping
    4.Client到Server端的Invocation

    -------------------------------------------------------------------
    先說(shuō)第1點(diǎn):EJB Container實(shí)現(xiàn)。
    1.1 EJB Pool
    我們知道,EJB Container 會(huì)維護(hù)一個(gè)EJB池,
    在多個(gè)client間共享,避免頻繁創(chuàng)建銷毀對(duì)象的開銷。
    讓我們來(lái)看看Jboss實(shí)現(xiàn)的Pool:
    EJB分EntityBean,MDB,Stateless/Stateful Session Bean,
    而Jboss中也對(duì)應(yīng)的有EntityInstancePool,MessageDrivenInstancePool,
    StatefulSessionInstancePool,StatelessSessionInstancePool.
    讓我們先從這4個(gè)類的共同基類AbstractInstancePool看起:
    class AbstractInstancePool實(shí)現(xiàn)了接口InstancePool,該接口有以下幾個(gè)方法:
    EnterpriseContext get() throws Exception;
    void free(EnterpriseContext ctx);
    void discard(EnterpriseContext ctx);
    int getCurrentSize();
    public int getMaxSize();
    --------------------------------------------------------------------
    先對(duì)EnterpriseContext作番說(shuō)明。EnterpriseContext的作用
    就是把具體的EJB instance和它的metadata聯(lián)系起來(lái)。
    該類簽名為:
    public abstract class EnterpriseContext,
    有4個(gè)子類,EntityEnterpriseContext,MessageDrivenEnterpriseContext,
    StatefulSessionEnterpriseContext,StatelessSessionEnterpriseContext。
    分別對(duì)應(yīng)4種類型的EJB。
    EnterpriseContext中有幾個(gè)重要的成員變量。
    /** The EJB instance */
    Object instance;
    /** The container using this context */
    Container con; //Container這個(gè)類是JBoss用來(lái)代表對(duì)EJB提供Transaction,Security,Pool等服務(wù)的類,我們回頭還會(huì)再說(shuō)。
    /** Only StatelessSession beans have no Id, stateful and entity do */
    Object id;

    /** The transaction associated with the instance */
    Transaction transaction; //Transaction,我們下節(jié)再說(shuō).

    // 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(); //由子類實(shí)現(xiàn)

    //返回javax.ejb.EJBContext,注意這個(gè)EJBContext是
    EJB規(guī)范要求提供給EJB的Context,與JBoss自己實(shí)現(xiàn)類EnterpriseContext沒(méi)有關(guān)系。

    /** 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這個(gè)成員變量表示當(dāng)前這個(gè)EJB instance有沒(méi)人在用。
    //這個(gè)變量用來(lái)給Reentrance,以及canPassviate用.
    /**
    * before reusing this context we clear it of previous state called
    * by pool.free()
    * 從pool里取出來(lái)的時(shí)候沒(méi)有關(guān)聯(lián)任何EJB instance和Transaction信息
    * 在返還pool的時(shí)候把這些信息清掉。
    */
    public void clear() {
    this.id = null;
    this.locked = 0;
    this.transaction = null;
    }
    //-------------------------------------------------------------------------------------
    protected boolean isContainerManagedTx()
    {
    BeanMetaData md = (BeanMetaData)con.getBeanMetaData();
    return md.isContainerManagedTx();
    }
    //從關(guān)聯(lián)的container拿出對(duì)應(yīng)的metadata,判斷是否CMT.
    //注意這里con是Container成員變量,可不是什么連接,連接一般縮寫為conn,
    //我一開始就搞混了:)
    //BeanMetaData這些MetaData的子類都是從xml配置里頭讀出來(lái)的Metadata構(gòu)造的,
    //沒(méi)什么神秘的.
    這個(gè)類里頭還有兩個(gè)inner class,EJBContextImpl implements EJBContext,
    UserTransactionImpl implements UserTransaction。EJBContextImpl等
    講解過(guò)Container再說(shuō),UserTransaction等下節(jié)再說(shuō)。

    現(xiàn)在讓我們來(lái)看看EnterpriseContext的幾個(gè)子類:
    首先類比一下幾個(gè)子類的成員變量:
    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;
    看來(lái)除了MDB沒(méi)有對(duì)應(yīng)的EJBObject/EJBLocalObject,其他統(tǒng)統(tǒng)都有:)
    學(xué)過(guò)EJB的人都知道,在語(yǔ)法上EJB instance 是implements
    EntityBean/SessionBean/MessageDrivenBean (這3個(gè)interface有一個(gè)共同的
    interface: public interface EnterpriseBean extends Serializable,
    EnterpriseBean 是個(gè)Marker接口,里頭什么都沒(méi)有,好像Serializable接口一樣,只說(shuō)明
    實(shí)現(xiàn)它的是個(gè)EJB.而EntityBean/SessionBean/MessageDrivenBean 有對(duì)應(yīng)的
    void ejbActivate() throws EJBException, RemoteException;
    void ejbLoad() throws EJBException, RemoteException;
    一些方法需要實(shí)現(xiàn)。(雖然常常是空實(shí)現(xiàn):),由容器作了很多事)
    至于EJBObject/EJBLocalObject 在語(yǔ)法上都是非直接實(shí)現(xiàn)的,代表EJB instance暴露出的Remote/Local 接口。既然這些EJB instance非直接實(shí)現(xiàn)這些接口,那么這些接口如何與具體的EJB instance相關(guān)聯(lián),我們講到Container類時(shí)就知道了。
    ----------------------------------------------------------------------------------


    EnterpriseContext的子類EntityEnterpriseContext的構(gòu)造函數(shù)
    public EntityEnterpriseContext(Object instance, Container con)
    throws RemoteException
    {
    super(instance, con);
    ctx = new EntityContextImpl(); //這是EJBContextImpl的子類,不急著說(shuō):)
    ((EntityBean)instance).setEntityContext(ctx);//看看,原來(lái)set...Context是在這里調(diào)用的//其它instance實(shí)現(xiàn)的什么ejbCreate(),EJBLoad,EJBActive()到底是什么時(shí)候
    調(diào)用的呢?接下來(lái)我們慢慢找,這可散布在各地呢:)
    }
    //其他幾個(gè)子類的構(gòu)造函數(shù)前3行也都如此,是類似的。
    對(duì)于StatelessSessionEnterpriseContext和MessageDrivenEnterpriseContext,緊接的是

    Method ejbCreate = instance.getClass().getMethod(\"ejbCreate\", new Class[0]);
    ejbCreate.invoke(instance, new Object[0]);
    //看看,來(lái)了一個(gè)ejbCreate:),對(duì)于StatelessSessionBean,一上來(lái)就ejbCreate()了~
    接下來(lái)看點(diǎn)簡(jiǎn)單的:對(duì)于EnterpriseContext,
    有public abstract void discard() throws RemoteException;
    對(duì)于MessageDriven...的
    public void discard() throws RemoteException
    {
    ((MessageDrivenBean)instance).ejbRemove();
    }
    對(duì)于StatelessSession的
    public void discard() throws RemoteException
    {
    ((SessionBean)instance).ejbRemove();
    }
    對(duì)于StatefulSession...的
    public void discard() throws RemoteException
    {
    // Do nothing
    }
    對(duì)于Entity....
    public void discard() throws RemoteException
    {
    ((EntityBean)instance).unsetEntityContext();
    }
    //discard 是在AbstractInstancePool中的
    void discard(EnterpriseContext ctx);調(diào)用的

    /**
    * 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還有個(gè)free方法:
    public void free(EnterpriseContext ctx) {
    ctx.clear();//記得ctx只是清掉id,transaction等,返回pool,準(zhǔn)備復(fù)用么?
    //discard是在發(fā)生錯(cuò)誤的時(shí)候,不希望擴(kuò)大影響,于是discard掉,
    //而對(duì)應(yīng)get()的free方法只是把EnterpriseContext返還給pool.
    }
    ----------------------------------------------------------------------------------

    專門對(duì)于Stateful....Context有設(shè)置EJB instance的函數(shù)
    /**
    * 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
    多了個(gè)implements Serializable,(其他都沒(méi)有),
    這是為了支持Activation/Passviation,Passviation的時(shí)候
    把EJB Instance寫到文件中。
    在StatefulSessionEnterpriseContext中有這樣兩個(gè)方法
    private void writeObject(ObjectOutputStream out)
    throws IOException, ClassNotFoundException
    {
    // do nothing
    }

    private void readObject(ObjectInputStream in)
    throws IOException, ClassNotFoundException
    {
    // do nothing
    }
    //說(shuō)明序列化的時(shí)候StatefulSessionEnterpriseContext本身不需要
    寫出什么狀態(tài),只有對(duì)應(yīng)的EJB instance才需要寫出狀態(tài)。
    現(xiàn)在來(lái)看AbstractInstancePool的源碼,由于內(nèi)容太多
    就不詳細(xì)解釋了。

    先看Abstract...Pool的create(Object instance)函數(shù)熱熱身~
    Abstract...Pool
    // Protected -----------------------------------------------------
    protected abstract EnterpriseContext create(Object instance)
    throws Exception;
    對(duì)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;//對(duì)于MDB和StatelessSessionBean,這個(gè)變量被設(shè)為true,// for MDB, we *do* pool // for SLSB, we *do* pool

    ok,現(xiàn)在來(lái)看pool的重頭戲,get()/free(EnterpriseContext ctx)函數(shù)
    (discard(EnterpriseContext ctx)前面講過(guò),不再重復(fù))
    這幾個(gè)函數(shù)也是Interface InstancePool里頭要實(shí)現(xiàn)的接口:)
    閑話少說(shuō),來(lái)看代碼~~
    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里頭有東東就拿出來(lái)
    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;
    }
    }
    }
    對(duì)于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掉不用了~
    }

    剩下的下回再講,先預(yù)告2個(gè)類體系:
    1.AbstractInstanceCache ,有EntityInstanceCache和StatefulSessionInstanceCache 子類。對(duì)于Entity,用它的
    PrimaryKey作Cache的Key,對(duì)于Stateful,Jboss也會(huì)付給
    每個(gè)instance一個(gè)唯一標(biāo)定的值用來(lái)做CacheKey.
    Abstract...Cache與Abstract...Pool結(jié)合使用,得到好的Performance。
    2.public abstract class Container,
    有EntityContainer,MessageDrivenContainer,Stateful/StatelessSessionContainer
    4個(gè)子類,用來(lái)提供對(duì)EJB instance的transaction/security/pool等服務(wù)。
    //看看它的成員變量,就能猜個(gè)大概
    /** 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,以前說(shuō)過(guò)Container有4種子類,分別對(duì)應(yīng)4種類型的EJB.
    一個(gè)Container是所有Container plugins(注1)和metadata(注2)的集散地,the container plugins可以從container拿到metadata和其他container plugins.EJB部署的時(shí)候會(huì)創(chuàng)建相應(yīng)的Container.Container基本不做太多事,主要delegate給plugins作事情。
    ok,讓我們來(lái)看看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作為一個(gè)單元部署的Module,比如一個(gè)ejb-jar就是一個(gè)Module,
    /*這個(gè) ejb-jar里頭可能有多個(gè)entitybean,sessionbean,那么對(duì)于 每個(gè)entitybean,sessionbean
    都會(huì)有一個(gè)對(duì)應(yīng)的container,而這些東東共享一個(gè)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了這個(gè)方法:
    /**
    * 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部分講解。
    現(xiàn)在先給個(gè)大略印象:
    BMPPersistenceManager實(shí)現(xiàn)
    public Object createBeanClassInstance() throws Exception {
    return con.getBeanClass().newInstance();
    }

    CMPPersistenceManager實(shí)現(xiàn)
    EntityPersistenceStore store;
    public Object createBeanClassInstance() throws Exception
    {
    return store.createBeanClassInstance();
    }
    -------------------------------------------------------------------
    ok,接下來(lái)看看Container如何處理Client過(guò)來(lái)的Invocation。
    一切精彩盡在下面這個(gè)函數(shù)
    public Object invoke(Invocation mi);
    //Invocation代表了Client端過(guò)來(lái)的調(diào)用
    //Invocation里頭有些成員變量,指明了要調(diào)用的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();
    //保存原來(lái)的classloader,在finally里恢復(fù)

    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端的調(diào)用鏈(Interceptor鏈,注4)
    間傳遞.
    -------------------------------------------------------
    ok,稍喘口氣,接下來(lái)看看兩個(gè)Internal的invoke,
    都是abstract,在字類實(shí)現(xiàn)
    public abstract Object internalInvokeHome(Invocation mi)
    throws Exception;
    public abstract Object internalInvoke(Invocation mi)
    throws Exception;
    至于具體實(shí)現(xiàn)么,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;
    用來(lái)load 這個(gè)Container里頭的類和資源,之所以要專門設(shè)一個(gè)Container
    的classLoader是因?yàn)槟苁笶JB re-deployable.(JBoss定期掃描deploy目錄,
    如果ejb更改就進(jìn)行redeploy,如果ejb刪除就undeploy)
    注4: Jboss會(huì)建立一個(gè)Interceptor 鏈,Invocation經(jīng)過(guò)鏈傳遞。
    比如有EntityInterceptor,SecurityInterceptor,TransactionInterceptor,
    InvokerInterceptor,一個(gè)套一個(gè),每個(gè)Interceptor對(duì)當(dāng)前Invocation進(jìn)行一些處理
    ,比如檢查權(quán)限,事物等等,然后傳給下一個(gè)Interceptor處理(這是Filter and Pipe模式了,也算是AOP拉~,別人說(shuō)
    JBoss 這個(gè)Interceptor實(shí)現(xiàn)屬于AOP方言特別重:)。
    所有的Interceptor都是現(xiàn)
    Object invokeHome(Invocation mi) throws Exception;
    和Object invoke(Invocation mi) throws Exception;
    在自己invoke的最后,
    經(jīng)過(guò)所有的Interceptor之后,調(diào)用下一個(gè)。
    看看AbstractInterceptor的缺省實(shí)現(xiàn):
    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);
    }
    在經(jīng)過(guò)重重Interceptor之后
    最后到達(dá)EJB Instance 調(diào)用你要的那個(gè)方法。
    其實(shí)實(shí)現(xiàn)很簡(jiǎn)單:
    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鏈的頭一個(gè),從這里調(diào)起~
    再來(lái)看看 void addInterceptor(Interceptor in);這個(gè)函數(shù)
    在Interceptor鏈最后再掛一個(gè)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,現(xiàn)在讓我們來(lái)看看Container都對(duì)EJB Instance暴露出來(lái)的
    方法都作了些什么,還有如何調(diào)用EJB Instance的方法.
    這里有重要的2個(gè)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調(diào)用
    //鏈的最后一個(gè),到這里你就會(huì)看到他調(diào)用了你的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();
    }
    }

    //可以看到,兩個(gè)Map作了個(gè)映射,Map的Key為
    在你想要調(diào)用的EJB instance方法,value為實(shí)際
    實(shí)現(xiàn)的方法,可能就是EJB instance本身實(shí)現(xiàn)的方法,
    或者是容器幫忙實(shí)現(xiàn)的(比如CMP 中abstract get/set方法,
    只能容器幫忙實(shí)現(xiàn)).
    從這里也可以看出來(lái),JBoss主要是保存了方法映射來(lái)處理
    EJBObject/EJBLocalObject 的調(diào)用請(qǐng)求,
    而其他一些J2EE AS是通過(guò)動(dòng)態(tài)生成EJBObject/EJBLocalObject
    和你的EJB Instance的字類來(lái)實(shí)現(xiàn)的(而JBoss就算在CMP2.0
    里動(dòng)態(tài)生成了一個(gè)東東,那也不是EJB Instance的子類)。
     
    ok,基本弄明白了Container的原理之后,我們來(lái)看看
    到底Container的一些初始化操作
    Container算是一項(xiàng)服務(wù),
    JBoss在deploy/undeploy/redeploy時(shí)會(huì)調(diào)用
    與Service相關(guān)的幾個(gè)函數(shù):
    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
    // 調(diào)用Container里頭的CreateService,我們回頭再看
    super.createService();

    //建立剛才所說(shuō)的兩個(gè)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;
    }
    }

    posted on 2005-03-29 09:46 笨笨 閱讀(686) 評(píng)論(0)  編輯  收藏 所屬分類: J2EEALLJBOSS
    主站蜘蛛池模板: jzzijzzij在线观看亚洲熟妇| 成人毛片免费视频| 日本系列1页亚洲系列| 亚洲自偷自拍另类12p| 国产成人麻豆亚洲综合无码精品| 毛片免费观看视频| 真实国产乱子伦精品免费| 久久久久国色AV免费观看| 99亚洲男女激情在线观看| 亚洲一区二区三区在线观看网站| 亚洲国产高清在线| 亚洲国产一成人久久精品| 亚洲一级片免费看| 免费一级毛片一级毛片aa| 日韩成人在线免费视频| 午夜爱爱免费视频| 成在人线AV无码免费| 欧美a级成人网站免费| 亚洲成人免费在线观看| 一级毛片aaaaaa免费看| 国产永久免费高清在线| 在线观看人成视频免费无遮挡| 无码人妻一区二区三区免费视频| 国产偷国产偷亚洲高清在线| 风间由美在线亚洲一区| 国产精品日本亚洲777| 美女扒开屁股让男人桶爽免费| 亚洲av日韩av永久无码电影| 中文字幕亚洲综合久久综合 | 日韩亚洲综合精品国产| 性色av极品无码专区亚洲| 亚洲AV无码一区二区三区性色 | 黄页网站免费观看| 成年女人喷潮毛片免费播放| 影音先锋在线免费观看| 国产成人免费a在线视频app| va亚洲va日韩不卡在线观看| 免费观看日本污污ww网站一区| 亚洲国产精品无码久久青草| 亚洲精品无码永久中文字幕| 亚洲欧洲日产国产综合网|