将有序的 Bean 注入 Collection 不遵循定义的顺序
Injecting ordered Beans into a Collection does not honour the defined order
我有许多 bean 都实现了相同的类型,它们被标记为 @Order(x)
,其中 x
是 bean 的优先级。
通过将 bean 的集合作为参数传递给另一个 bean 来使用这些 bean,但是我们使用 SonarQube 来静态分析我们的代码,这建议您应该使用基础 class 除非您使用特定的功能child class.
@Bean
public SomeProcessor someProcessor(Collection<MyBean> beans) {
return new SomeProcessor(beans);
}
如果我 @Inject
或将它们作为 List<>
传递,它们将保留 @Order
注释定义的顺序。
如果我 @Inject
或将它们作为 Collection<>
传递,它们将保留它们创建的顺序,忽略 @Order
注释。
这是 Spring 注入的预期行为(使用 Spring Boot 2.4.4)吗?或者这是我应该作为错误提出的问题吗?
下面的代码演示了这个问题(尽管在生产代码中我们没有将字符串创建为 Bean,因为那样会……不寻常):
@Inject
private List<String> stringList;
@Inject
private Collection<String> stringCollection;
@Bean
@Order(1)
public String stringBean1() {
return "BEAN 1";
}
@Bean
@Order(3)
public String stringBean3() {
return "BEAN 3";
}
@Bean
@Order(2)
public String stringBean2() {
return "BEAN 2";
}
@PostConstruct
public void postConstruct() {
log.error("{}", stringCollection);
log.error("{}", stringList);
}
List
按1、2、3顺序存储。
Collection
按顺序 1、3、2 存储,“忽略”@Order
注释。
我不知道这种行为是否记录在案,但它是可以接受和理解的。 Collection
没有说明底层实现,它可以是有序的或无序的。
文档是这样说的
A collection represents a group of objects, known as its elements. Some collections allow duplicate elements and others do not. Some are ordered and others unordered.
另一方面List
是
An ordered collection (also known as a sequence).
事实上,您正在使用 List
class 的一项功能:它的顺序。我认为这里改为 Collection
是不正确的,因为你需要订购集合。
Spring 基于集合的排序最终在 4.0 版本中实现。 issue.
中记录了改进
您指出的问题在另一个 issue.
中以某种方式描述
但是正如那里所描述的,并且正如@jwillebrands 在 his/her 回答中指出的那样,Collection
可能会或可能不会被订购,而 Spring 只会保证订单在 lists and arrays:
Your target beans can implement the org.springframework.core.Ordered
interface or use the @Order
or standard @Priority
annotation if you want items in the array or list to be sorted in a specific order. Otherwise, their order follows the registration order of the corresponding target bean definitions in the container.
我有许多 bean 都实现了相同的类型,它们被标记为 @Order(x)
,其中 x
是 bean 的优先级。
通过将 bean 的集合作为参数传递给另一个 bean 来使用这些 bean,但是我们使用 SonarQube 来静态分析我们的代码,这建议您应该使用基础 class 除非您使用特定的功能child class.
@Bean
public SomeProcessor someProcessor(Collection<MyBean> beans) {
return new SomeProcessor(beans);
}
如果我 @Inject
或将它们作为 List<>
传递,它们将保留 @Order
注释定义的顺序。
如果我 @Inject
或将它们作为 Collection<>
传递,它们将保留它们创建的顺序,忽略 @Order
注释。
这是 Spring 注入的预期行为(使用 Spring Boot 2.4.4)吗?或者这是我应该作为错误提出的问题吗?
下面的代码演示了这个问题(尽管在生产代码中我们没有将字符串创建为 Bean,因为那样会……不寻常):
@Inject
private List<String> stringList;
@Inject
private Collection<String> stringCollection;
@Bean
@Order(1)
public String stringBean1() {
return "BEAN 1";
}
@Bean
@Order(3)
public String stringBean3() {
return "BEAN 3";
}
@Bean
@Order(2)
public String stringBean2() {
return "BEAN 2";
}
@PostConstruct
public void postConstruct() {
log.error("{}", stringCollection);
log.error("{}", stringList);
}
List
按1、2、3顺序存储。
Collection
按顺序 1、3、2 存储,“忽略”@Order
注释。
我不知道这种行为是否记录在案,但它是可以接受和理解的。 Collection
没有说明底层实现,它可以是有序的或无序的。
文档是这样说的
A collection represents a group of objects, known as its elements. Some collections allow duplicate elements and others do not. Some are ordered and others unordered.
另一方面List
是
An ordered collection (also known as a sequence).
事实上,您正在使用 List
class 的一项功能:它的顺序。我认为这里改为 Collection
是不正确的,因为你需要订购集合。
Spring 基于集合的排序最终在 4.0 版本中实现。 issue.
中记录了改进您指出的问题在另一个 issue.
中以某种方式描述但是正如那里所描述的,并且正如@jwillebrands 在 his/her 回答中指出的那样,Collection
可能会或可能不会被订购,而 Spring 只会保证订单在 lists and arrays:
Your target beans can implement the
org.springframework.core.Ordered
interface or use the@Order
or standard@Priority
annotation if you want items in the array or list to be sorted in a specific order. Otherwise, their order follows the registration order of the corresponding target bean definitions in the container.