關於EJB3.x的命名空間一直都很迷惑,閱讀規範以後這裏作一下筆記:java
EJB reference,是指一個EJB引用另外一個EJB的business interface, non-interface views或者home接口。ios
咱們能夠在部署描述符ejb-jar.xml中:web
一、在同一ejb-jar.xml中一個EJB對另外一個EJB的引用,所以大多數狀況下,。服務器
二、同一應用(企業應用)中一個EJB對另外一個EJB的引用(它們在不一樣的ejb-jar.xml中被聲明)。app
三、java:global中的引用(這一點爲何規範中沒有說?)。less
JAVAEE中EJB的JNDI有下面幾個命名空間:ide
java:globalflex
java:appui
java:modulethis
java:comp
每一個Bean擁有本身的java:comp,Bean與Bean之間java:comp是相互隔離的,一樣module與module之間的java:module是相互隔離的,應用與應用之間java:app是相互隔離的。另外打包在war中的Bean比較特殊,全部的web組件(servlet/filter)與全部的Bean(包括Bean與Bean之間)共用同一個java:comp空間。
<ejb-link>在下面的狀況下會使用:
Here are some scenarios that hopefully clarify why <ejb-link/> (or @EJB(beanName="...")) and EJB ref bindings are both useful and complementary: An application can itself be logically broken up into components, and the developer chooses to use EJBs to implement those components. In this case, the application developer knows the target EJB component that the client wants to use. If there are multiple components implementing the same interface, then some disambiguation is required, and <ejb-link/> can be used. An application has a dependency on an external service. In this case, the application knows it has a dependency on an external service, so <ejb-link/> cannot be used since the service implementation does not exist in the same application. An application has a dependency on an external service, but a minimal implementation is provided in the same application. In this case, the developer might use an <ejb-link/> as in #1, but the deployer has the flexibility to override that choice as in #2.
<resource-ref>和<resource-env-ref>
<resource-ref>與<resource-env-ref>本質上沒有太大的區別:
一、他們都使用@Resource註解來標記,有些類型甚至還能夠互換。
二、<resource-ref>與<resource-env-ref>不一樣之處在於,<resource-ref>是指引用咱們在JavaEE應用服務器上配置的資源,好比jdbc,ConnectionFacotry等等這一類型的資源,一般來講這些資源具備Factory性質,固然不是Factory性質也能夠,這沒有明確的規定,有一些資源應用服務器會進行特殊處理,好比ConnectionFactory之類的。
但<resource-env-ref>通常是指引用咱們應用服務器的組件,好比下面這些類型,它們不少是bean運行時涉及的上下組件,也有一些像Queue,Topic之類的配置性資源,它們大部分是直接的組件(非factory性質):
public static final Set<String> knownResourceEnvTypes = new TreeSet<String>(Arrays.asList( "javax.ejb.EJBContext", "javax.ejb.SessionContext", "javax.ejb.EntityContext", "javax.ejb.MessageDrivenContext", "javax.transaction.UserTransaction", "javax.jms.Queue", "javax.jms.Topic", "javax.xml.ws.WebServiceContext", "javax.ejb.TimerService", "javax.enterprise.inject.spi.BeanManager", "javax.validation.Validator", "javax.validation.ValidatorFactory" ));
下面有是JavaEE規範對<resource-env-ref>的描述:
This section describes the programming and deployment descriptor interfaces that
allow the Application Component Provider to refer to administered objects that are
associated with a resource (for example, a Connector CCI InteractionSpec
instance) by using 「logical」 names called resource environment references. The
resource environment references are special entries in the application component’s
environment. The Deployer binds the resource environment references to
administered objects in the target operational environment.
相似的還有@PersistenceContext,@PersistenceUnit:
@PersistenceContext用於注入/引用 EntityManager
@PersistenceUnit用於注入EntityManagerFactory
glassfish中的mappedName並非指將ejb映射到java:global下,而是指全局jndi,全局jndi跟java:global並非一個東西,並且從glassfish的jndi結構上來看,java:global只是全局jndi下面的一個子context。
在EJB中咱們一般稱JNDI爲ENC,也就是Enterprise Naming Context的縮寫。
resource-ref的ref-name:指程序代碼中所使用的進行lookup的jndi name,若是咱們不指定它所注入資源的jndi名稱,則默認注入名爲java:comp/env/full-qualified.class.name/member的資源。
resource-ref的mapped-name:指所引用的外部(全局)的資源的id。
resource-env-ref與resource-ref差很少,但resource-env-ref是直接的資源,針對 queue 和topic這一類的。
new InitialContext()的時候,這個InitialContext並不必定是指向java:comp/env,有的應用服務器會指向這個位置,但規範裏面並無這個規定,由於這樣子的程序並非portable的。好比Tomcat的InitialContext就不是(今天同事遇到這個問題了)。
ejb-ref(@Remote類型的接口/View引用), ejb-local-ref(Local類型的接口/View引用),(區別於env-entry,env-entry只能聲明基本類型的引用如string, int, boolean等):
能夠往bean的NamingContext(也就是java:comp命名空間下面)bind其它bean的reference。這樣子咱們能夠lookup到這些引用,並在適當的時候能夠經過修改ejb-jar.xml來改變bean的引用,而不須要去修改代碼。
ejb規範建議,bean全部的對其它bean的引用都應該位於java:comp/env/ejb下面。但經過註解所聲明的引用將不會在任何subContext下面。
另外,咱們還可使用註解來進行聲明ejb-ref,以下:
@EJB(name="ejb/EmplRecord", beanInterface=EmployeeRecordHome.class) @Stateless public class EmployeeServiceBean implements EmployeeService { public void changePhoneNumber(...) { ... // Obtain the default initial JNDI context. Context initCtx = new InitialContext(); // Look up the home interface of the EmployeeRecord // enterprise bean in the environment. Object result = initCtx.lookup( "java:comp/env/ejb/EmplRecord"); // Convert the result to the proper type. EmployeeRecordHome emplRecordHome = (EmployeeRecordHome) javax.rmi.PortableRemoteObject.narrow(result, EmployeeRecordHome.class); ... } }
ejb-ref-name就是咱們要綁定到java:comp下面的jndi名字,咱們進行lookup的時候須要用這個name進行lookup,
ejb-ref-type是可選填寫的,能夠是Entity/Session
home/remote/local-home/local用於指定引用bean的接口類型,若是引用ejb2.x的bean的話,home是必須指定的。
ejb-link/lookup-name用於指定所引用的外部bean(target)。二者不能同時使用,ejb-link是可選的,若是不填寫的話,則在當前的ejb-jar.xml(包括註解)中查找具備相應接口的bean。ejb-link的值是須要引用的bean的<ejb-name>,固然也能夠用註解來進行聲明 。
與<ejb-ref>/<ejb-local-ref>相對應的註解是@EJB
@EJB.name => <ejb-ref-name>
@EJB.beanName => <ejb-link>
@EJB.lookup => <lookup-name>
@EJB.mappedName => <mapped-name>
EJB的home接口的實現由JavaEE應用服務器提供,用戶只須要提供接口。其中建立bean的方法必須是create<METHOD>(xxx,xxx)的形式,Stateless Session Bean只能是create(),而對於Stateful Session Bean而言,建立Bean實例後,服務器將會去調用Bean實例上的ejbCreate<Method>方法。