在 CDI 中,如何在注入点为 bean 赋予范围?
In CDI, how to give scope to a bean at the point of injection?
在 CDI 中,我能够注入一个具有特定范围的 bean,该范围定义了 bean class。但是,如果我创建没有任何作用域的 bean class 并在注入时为该 bean 赋予作用域会怎样。我的要求是在后一种情况下使注入时间范围界定成为可能。问题是注入发生在 dependent scope
而不是所需的注释范围,除非我使用 producer
.
例如:
案例 1:
当我在其 class 声明中声明 bean 的范围时,如下所示:
@ApplicationScoped
class UserDetails {
...
}
并像这样注入:
@ViewScoped
class UserView {
@Inject
UserDetails userDetails;
.
.
}
它按预期工作。在应用程序范围内注入的 bean 在整个应用程序中的所有其他 bean 中都可用。
案例 2:
但是当我在 class 声明中没有给出范围时:
class UserDetails {
...
}
并像这样注入(在注入点给出范围):
@ViewScoped
class UserView {
@Inject @ApplicationScoped
UserDetails userDetails;
.
.
}
这失败了!...注入的 bean 没有注入 application scope
,而是注入了 dependent scope
(在我的例子中是 View Scope
)。
我必须创建一个 Producer
和一个 Qualifier
,其中 @Produces
方法在所需的 application scope
中提供 bean。在这种情况下,如果我必须在 application scope
中注入 bean class UserDetails,我觉得这个 producer/qualifier 扩展是一个开销。
事实是,UserDetails class 是第三方 jar 的一部分。这个 class 没有声明任何范围,是一个 POJO。我无法更改其源代码。
根据以上讨论,我有两个问题:
为什么有人知道要在特定范围内注入 bean 时会创建未定义范围的 bean classes?这种做法对设计有什么好处吗?
因为我无法控制 bean classes 的源代码,并且它们与任何范围都没有关联,所以 producer/qualifier 扩展是唯一的好方法吗在所需的范围内注入这样的豆?
1.未定义范围的对象 - 使用@Dependent
CDI 会将没有范围的对象视为 @Dependent scope。
An instance of a dependent bean is never shared between different
clients or different injection points. It is strictly a dependent
object of some other object. It is instantiated when the object it
belongs to is created, and destroyed when the object it belongs to is
destroyed.
Beans with scope @Dependent don’t need a proxy object. The client
holds a direct reference to its instance.
Spring IoC dev: CDI @Dependent scope is similar to Spring IoC Prototype scope.
2。没有 @Produces & 只使用 @Inject
CDI 将为每次注入创建新的 UserDetails 实例(@Dependent 范围)。这里没有共享数据!您不能像以前那样定义作用域(注入时)。
3。使用@Produces & 使用@Inject
您可以控制 UserDetails 对象的范围(ApplicationScoped、SessionScoped 或 RequestScoped)
public class Producers {
@Produces @ApplicationScoped
public UserDetails createUserDetails() {
// Initialize UserDetails
}
public void release(@Disposes UserDetails userDetails) {
// Release userDetails if you have to
}
}
4.另一种方法:尽可能扩展 UserDetails
@ApplicationScoped // Or @SessionScoped, @RequestScoped
public class UserDetailsImpl extends UserDetails {
//
}
如果你想要 UserDetails 的 ApplicationScoped。方式3或者方式4都可以。
作用域总是在 bean 上定义,而不是在注入点上。
注入点不能改变注入bean的范围。
我认为您可以通过在注入点附近指定 @New
注释将 @ApplicationScoped
bean 作为 @Dependent
bean 注入,但您不能相反。
在 CDI 中,我能够注入一个具有特定范围的 bean,该范围定义了 bean class。但是,如果我创建没有任何作用域的 bean class 并在注入时为该 bean 赋予作用域会怎样。我的要求是在后一种情况下使注入时间范围界定成为可能。问题是注入发生在 dependent scope
而不是所需的注释范围,除非我使用 producer
.
例如:
案例 1:
当我在其 class 声明中声明 bean 的范围时,如下所示:
@ApplicationScoped
class UserDetails {
...
}
并像这样注入:
@ViewScoped
class UserView {
@Inject
UserDetails userDetails;
.
.
}
它按预期工作。在应用程序范围内注入的 bean 在整个应用程序中的所有其他 bean 中都可用。
案例 2:
但是当我在 class 声明中没有给出范围时:
class UserDetails {
...
}
并像这样注入(在注入点给出范围):
@ViewScoped
class UserView {
@Inject @ApplicationScoped
UserDetails userDetails;
.
.
}
这失败了!...注入的 bean 没有注入 application scope
,而是注入了 dependent scope
(在我的例子中是 View Scope
)。
我必须创建一个 Producer
和一个 Qualifier
,其中 @Produces
方法在所需的 application scope
中提供 bean。在这种情况下,如果我必须在 application scope
中注入 bean class UserDetails,我觉得这个 producer/qualifier 扩展是一个开销。
事实是,UserDetails class 是第三方 jar 的一部分。这个 class 没有声明任何范围,是一个 POJO。我无法更改其源代码。
根据以上讨论,我有两个问题:
为什么有人知道要在特定范围内注入 bean 时会创建未定义范围的 bean classes?这种做法对设计有什么好处吗?
因为我无法控制 bean classes 的源代码,并且它们与任何范围都没有关联,所以 producer/qualifier 扩展是唯一的好方法吗在所需的范围内注入这样的豆?
1.未定义范围的对象 - 使用@Dependent
CDI 会将没有范围的对象视为 @Dependent scope。
An instance of a dependent bean is never shared between different clients or different injection points. It is strictly a dependent object of some other object. It is instantiated when the object it belongs to is created, and destroyed when the object it belongs to is destroyed.
Beans with scope @Dependent don’t need a proxy object. The client holds a direct reference to its instance.
Spring IoC dev: CDI @Dependent scope is similar to Spring IoC Prototype scope.
2。没有 @Produces & 只使用 @Inject
CDI 将为每次注入创建新的 UserDetails 实例(@Dependent 范围)。这里没有共享数据!您不能像以前那样定义作用域(注入时)。
3。使用@Produces & 使用@Inject
您可以控制 UserDetails 对象的范围(ApplicationScoped、SessionScoped 或 RequestScoped)
public class Producers {
@Produces @ApplicationScoped
public UserDetails createUserDetails() {
// Initialize UserDetails
}
public void release(@Disposes UserDetails userDetails) {
// Release userDetails if you have to
}
}
4.另一种方法:尽可能扩展 UserDetails
@ApplicationScoped // Or @SessionScoped, @RequestScoped
public class UserDetailsImpl extends UserDetails {
//
}
如果你想要 UserDetails 的 ApplicationScoped。方式3或者方式4都可以。
作用域总是在 bean 上定义,而不是在注入点上。
注入点不能改变注入bean的范围。
我认为您可以通过在注入点附近指定 @New
注释将 @ApplicationScoped
bean 作为 @Dependent
bean 注入,但您不能相反。