如果@Singleton bean中有@Stateless字段会发生什么?

时间:2015-01-28 14:37:44

标签: java singleton ejb stateless

我不确定 @EJB 注释如何分配字段等。

我们假设我们有3个班级:

  • A - 无状态(有一个带 @EJB 注释的B字段)
  • B - Singleton (有一个带 @EJB 注释的C字段)
  • C - 无国籍

在这种情况下,当用户尝试访问bean时会发生什么?

  1. 用户 1 访问bean(第一次)
    1. 已创建,需要 B 才能正常工作
    2. B 已创建,需要 C 才能正常工作
    3. C 已创建
  2. 用户2连接和
    1. 创建,因为用户1仍在使用 A
    2. B 是必需的,但它是一个单身,因此只返回了唯一的实例
    3. C 未创建为Singleton B 已为其分配了引用
  3. 这是否意味着如果 @Singleton 需要任何其他bean,那么它将用作 @Singleton 的bean? ( @Stateless 将充当单身人士)

2 个答案:

答案 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()之后创建。那个男士在调用代理方法时。