我不确定 @EJB 注释如何分配字段等。
我们假设我们有3个班级:
在这种情况下,当用户尝试访问bean时会发生什么?
这是否意味着如果 @Singleton 需要任何其他bean,那么它将用作 @Singleton 的bean? ( @Stateless 将充当单身人士)
答案 0 :(得分:1)
不一定。如果单例允许多个并发调用@Lock(READ)
或@ConcurrencyManagement(BEAN)
,那么将创建多个C bean,每个调用者线程一个与A bean相同。但是,如果单例bean使用@ConcurrencyManagement(CONTAINER)
与@Lock(WRITE)
的默认并发,那么是的,bean C实际上也将是一个单例(假设它不在其他地方访问)。
答案 1 :(得分:1)
我为您的问题创建了一个示例实现。你可以在GitHub上找到它: https://github.com/StefanHeimberg/stackoverflow-28194928
使用NetBeans 8.0.2打开此项目,并在Glassfish 4.1上部署(运行)此项目。
部署后会创建以下日志:
Information: visiting unvisited references
Information: visiting unvisited references
Information: Portable JNDI names for EJB C: [java:global/mavenproject1/C!com.mycompany.mavenproject1.C, java:global/mavenproject1/C]
Schwerwiegend: C[uuid=e1c73e4b-998c-4666-bac9-4825556aa20a] => created
Information: Portable JNDI names for EJB Bootstrap: [java:global/mavenproject1/Bootstrap!com.mycompany.mavenproject1.Bootstrap, java:global/mavenproject1/Bootstrap]
Information: Portable JNDI names for EJB A: [java:global/mavenproject1/A, java:global/mavenproject1/A!com.mycompany.mavenproject1.ARemote]
Information: Glassfish-specific (Non-portable) JNDI names for EJB A: [com.mycompany.mavenproject1.ARemote, com.mycompany.mavenproject1.ARemote#com.mycompany.mavenproject1.ARemote]
Information: Portable JNDI names for EJB B: [java:global/mavenproject1/B!com.mycompany.mavenproject1.B, java:global/mavenproject1/B]
Schwerwiegend: B[uuid=868f15c0-728d-4079-b90a-2b55ae413c33] => created
WARN: WELD-000411: Observer method [BackedAnnotatedMethod] private org.glassfish.jersey.gf.cdi.internal.CdiComponentProvider.processAnnotatedType(@Observes ProcessAnnotatedType<Object>) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds.
WARN: WELD-000411: Observer method [BackedAnnotatedMethod] public org.glassfish.jms.injection.JMSCDIExtension.processAnnotatedType(@Observes ProcessAnnotatedType<Object>) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds.
WARN: WELD-000411: Observer method [BackedAnnotatedMethod] org.glassfish.sse.impl.ServerSentEventCdiExtension.processAnnotatedType(@Observes ProcessAnnotatedType<Object>, BeanManager) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds.
Schwerwiegend: ========================
Schwerwiegend: Bootstrap.init()
Schwerwiegend: ========================
Information: mavenproject1 was successfully deployed in 419 milliseconds.
现在只运行焦点测试方法ARemoteIT.client1()。生成以下输出:
Schwerwiegend: A[uuid=9be077f8-945a-4db2-ba3e-ea0003692c0f] => created ()
Schwerwiegend: A[uuid=9be077f8-945a-4db2-ba3e-ea0003692c0f] => B of type com.mycompany.mavenproject1.__EJB31_Generated__B__Intf____Bean__ injected
Schwerwiegend: A[uuid=9be077f8-945a-4db2-ba3e-ea0003692c0f] => ready to use
Schwerwiegend: A[uuid=9be077f8-945a-4db2-ba3e-ea0003692c0f] [client1] => doSomething() called
Schwerwiegend: B[uuid=ce1be5f1-0b82-4990-a9b5-153a2540a891] => created
Schwerwiegend: B[uuid=ce1be5f1-0b82-4990-a9b5-153a2540a891] => C of type com.mycompany.mavenproject1.__EJB31_Generated__C__Intf____Bean__ injected
Schwerwiegend: B[uuid=ce1be5f1-0b82-4990-a9b5-153a2540a891] => ready to use
Schwerwiegend: B[uuid=ce1be5f1-0b82-4990-a9b5-153a2540a891] [client1] => doSomething() called
Schwerwiegend: C[uuid=5f1bed5c-80e8-41c8-b524-51cac3e3de0f] => created
Schwerwiegend: C[uuid=5f1bed5c-80e8-41c8-b524-51cac3e3de0f] => ready to use
Schwerwiegend: C[uuid=5f1bed5c-80e8-41c8-b524-51cac3e3de0f] [client1] => doSomething() called
在C.doeSomething()中,现在超时1分钟......
在此超时时间内,无法同时访问单例bean B,因为默认锁定类型为Write(@Lock(WRITE))。
如果你现在在1分钟的超时时间内开始使用已故的测试方法ARemoteIT.client2(),则会生成以下输出:
Schwerwiegend: A[uuid=c358e9f3-8687-4d76-a9ca-38b31357649b] => created ()
Schwerwiegend: A[uuid=c358e9f3-8687-4d76-a9ca-38b31357649b] => B of type com.mycompany.mavenproject1.__EJB31_Generated__B__Intf____Bean__ injected
Schwerwiegend: A[uuid=c358e9f3-8687-4d76-a9ca-38b31357649b] => ready to use
Schwerwiegend: A[uuid=c358e9f3-8687-4d76-a9ca-38b31357649b] [client2] => doSomething() called
在这里你可以看到client2是Waitung for B来调用B.doSomething。在1分钟超时完成后。该 可以访问单例bean,client2可以跟随B.doSomething。
这是client1 C.doSomething超时后的日志:
Schwerwiegend: C[uuid=5f1bed5c-80e8-41c8-b524-51cac3e3de0f] [client1] => doSomething() finished
Schwerwiegend: B[uuid=ce1be5f1-0b82-4990-a9b5-153a2540a891] [client1] => doSomething() finished
Schwerwiegend: A[uuid=9be077f8-945a-4db2-ba3e-ea0003692c0f] [client1] => doSomething() finished
Schwerwiegend: B[uuid=ce1be5f1-0b82-4990-a9b5-153a2540a891] [client2] => doSomething() called
Schwerwiegend: C[uuid=5f1bed5c-80e8-41c8-b524-51cac3e3de0f] [client2] => doSomething() called
Schwerwiegend: C[uuid=5f1bed5c-80e8-41c8-b524-51cac3e3de0f] [client2] => doSomething() finished
Schwerwiegend: B[uuid=ce1be5f1-0b82-4990-a9b5-153a2540a891] [client2] => doSomething() finished
Schwerwiegend: A[uuid=c358e9f3-8687-4d76-a9ca-38b31357649b] [client2] => doSomething() finished
<强> Additionals:强>
你可以看到它不是真正注入B或C的实例!相反,这些只是代理。 但您也可以看到glassfish在部署后自动创建B和C的新实例。
使用@Stateless,您无法保证您收到所需EJB的相同实例。它也可能是那样的 每次在代理上调用方法时,都会收到所需EJB的另一个实例。容器正在管理这个。 如果所有EJB都在使用中,那么容器使用一个EJB池或创建一个新实例。
在日志中,您会看到B仅在调用A.doSomething()之后创建。那个男士在调用代理方法时。