Spring @Configuration @Bean - 如何获得更多关于创建 bean 的上下文信息?
Spring @Configuration @Bean - How can I get more context information for bean creation?
我想创建一个基于“字段属于哪个 class 的实例(或者甚至只是 class 该字段属于哪个实例)的 bean。类似于:
@Configuration
@ComponentScan
public class MyConfiguration {
@Bean
SomeClass getTheRightInstance(SomeContext someContext) {
if(someContext.getinjectedFieldHostInstance.getId() == 7) {
return new SpecificSomeClassImplForId7();
} else {
return new SomeClass();
}
}
Bean 将被注入以下 field
:
public class A {
private int final id;
@Inject private SomeClass field;
int getId();
public A() {
id = SerialIdGenerator.getNextID();
}
}
Select bean 基于 A
实例的 id
注入 A
的 field
public staitc void main(String[] args) {
A a1 = new A(); // has id '1', gets field injected with SimpleClass
A a2 = new A(); // has id '2', gets field injected with SimpleClass
...
A a7 = new A(); // gets field injected with SpecificSomeClassImplForId7
...
A last= new A(); // has id!=7, gets field injected with SimpleClass
}
总体思路是决定将哪个实现注入哪个字段,其中 class 在代码中定义。
我可以将不同的 bean 实例注入到相同 class 的不同实例的相同字段吗?如何通过代码配置它?
我不确定你为什么要这样做,但这似乎是个坏主意。
类 永远不应该围绕调用者配置它们的行为,这会导致代码紧密耦合且可移植性差。
相反,您应该找出是什么让这 2 个字段不同,并重构它们以使用 2 个不同的接口(在共享功能的情况下,它们甚至可能有一个通用的超级接口)。然后您可以轻松地为这些接口提供 2 种不同的实现。在您的情况下,您还可以编写一个 class 来处理 id == 7 的特定情况和其他情况(可能通过委托),并在将实例注入 A 之后或同时使用另一种方式配置实例。
我不知道有任何可能直接做你想做的事。
编辑:在评论中进一步讨论并进一步了解您想要完成的任务后,我认为最好有一个工厂来创建 A 实例:
@Service
class AFactory {
@Autowired
private SpecificSomeClassImplForId7 specificSomeClassImplForId7;
@Autowired
private SomeClass someClass;
public A makeA() {
if(isSpecialA()) {
return new A(specificSomeClassImplForId7);
} else {
return new A(someClass);
}
}
然后您可以在您的应用程序中的其他 Spring 个 Bean 中使用此工厂来制作 As。
您定义的 bean 是单例,因此它是在 Context-Initialization 创建的,然后应用程序知道任何人都可能自动装配该值。您必须将 Bean 创建为 Prototype
才能仅在自动装配上请求实例。
仍然无法获取有关 autowire-target 的信息。您可以使用 *Aware
接口来获取
- 自己独特的Beanname
- Beanfactory
- 应用程序上下文
但是自动装配的 target
和目标的 class
都不是。
注意:如果 autowire-field 被标记为 @Lazy
并且 Bean 的范围是 Prototype
您可以详细说明 bean 使用 bean 的 [=16= 自动装配的确切时间].
我想创建一个基于“字段属于哪个 class 的实例(或者甚至只是 class 该字段属于哪个实例)的 bean。类似于:
@Configuration
@ComponentScan
public class MyConfiguration {
@Bean
SomeClass getTheRightInstance(SomeContext someContext) {
if(someContext.getinjectedFieldHostInstance.getId() == 7) {
return new SpecificSomeClassImplForId7();
} else {
return new SomeClass();
}
}
Bean 将被注入以下 field
:
public class A {
private int final id;
@Inject private SomeClass field;
int getId();
public A() {
id = SerialIdGenerator.getNextID();
}
}
Select bean 基于 A
实例的 id
A
的 field
public staitc void main(String[] args) {
A a1 = new A(); // has id '1', gets field injected with SimpleClass
A a2 = new A(); // has id '2', gets field injected with SimpleClass
...
A a7 = new A(); // gets field injected with SpecificSomeClassImplForId7
...
A last= new A(); // has id!=7, gets field injected with SimpleClass
}
总体思路是决定将哪个实现注入哪个字段,其中 class 在代码中定义。
我可以将不同的 bean 实例注入到相同 class 的不同实例的相同字段吗?如何通过代码配置它?
我不确定你为什么要这样做,但这似乎是个坏主意。
类 永远不应该围绕调用者配置它们的行为,这会导致代码紧密耦合且可移植性差。
相反,您应该找出是什么让这 2 个字段不同,并重构它们以使用 2 个不同的接口(在共享功能的情况下,它们甚至可能有一个通用的超级接口)。然后您可以轻松地为这些接口提供 2 种不同的实现。在您的情况下,您还可以编写一个 class 来处理 id == 7 的特定情况和其他情况(可能通过委托),并在将实例注入 A 之后或同时使用另一种方式配置实例。
我不知道有任何可能直接做你想做的事。
编辑:在评论中进一步讨论并进一步了解您想要完成的任务后,我认为最好有一个工厂来创建 A 实例:
@Service
class AFactory {
@Autowired
private SpecificSomeClassImplForId7 specificSomeClassImplForId7;
@Autowired
private SomeClass someClass;
public A makeA() {
if(isSpecialA()) {
return new A(specificSomeClassImplForId7);
} else {
return new A(someClass);
}
}
然后您可以在您的应用程序中的其他 Spring 个 Bean 中使用此工厂来制作 As。
您定义的 bean 是单例,因此它是在 Context-Initialization 创建的,然后应用程序知道任何人都可能自动装配该值。您必须将 Bean 创建为 Prototype
才能仅在自动装配上请求实例。
仍然无法获取有关 autowire-target 的信息。您可以使用 *Aware
接口来获取
- 自己独特的Beanname
- Beanfactory
- 应用程序上下文
但是自动装配的 target
和目标的 class
都不是。
注意:如果 autowire-field 被标记为 @Lazy
并且 Bean 的范围是 Prototype
您可以详细说明 bean 使用 bean 的 [=16= 自动装配的确切时间].