Spring Java 配置 - 使用接口公开 bean
Spring Java Config - exposing bean using Interface
我有一个 class,假设 'DefaultService' 实现了两个接口:'Service1' 和 'Service2'。 Spring java 配置如下所示:
@Bean
Service1 defaultService() {
return new DefaultService();
}
现在,我有另一个需要 'Service2'.
的 bean Foo
public class Foo implements AnotherInterface {
@Autowired
private Service2 service2;
}
并且这个 bean 也是通过 Java 配置配置的:
@Bean
AnotherInterface anotherInterface(){
return new Foo();
}
Spring 不喜欢这个配置。我想这是有道理的,因为 'DefaultService' 公开为 'Service1',而不是 'Service2'(Foo 需要)。
No qualifying bean of type [...Service2] found for dependency: expected at least 1 bean which qualifies ...
当然,我可以将 DefaultService 公开为 Service2。但是如果有另一个 bean 需要 Service1 怎么办? Spring 针对此场景的建议是什么?我发现的另一个(奇怪的)问题是以下配置有效:
@Bean
Service2 defaultService(){ // exposing the bean as Service2, to fix dependency on Foo
return new DefaultService();
}
@Bean
AnotherDependant anotherDependant(Service1 service1){
return new AnotherDependant(service1);
}
Spring 如何将 Service1 连接到 'AnotherDependant' 的配置声明(我在第一个场景中对 @Autowired 感到不满意)?
我正在使用 Spring 3.2.2.RELEASE,尽管我怀疑版本是否真的很重要..
我的最佳解决方法是:
@Bean
DefaultService defaultService(){
return new DefaultService();
}
@Bean
Service1 service1(){
return defaultService();
}
@Bean
Service2 service2(){
return defaultService();
}
但这很丑...
=========================================== ==========================
正在回复@Oskar。
基本上@Oskar 的建议与在 xml 中声明两个相同。即在 spring 容器中创建两个相同 class 的实例。
public interface Driveable {}
public interface Vehicle {}
public class Car implements Vehicle, Driveable{}
@Configuration
public class Config {
@Bean
public Vehicle vehicle() {
return new Car();
}
@Bean
public Driveable driveable() {
return new Car();
}
}
public class Main {
public static void main(String[] args) {
final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
final Driveable driveable = context.getBean("driveable", Driveable.class);
final Vehicle vehicle = context.getBean("vehicle", Vehicle.class);
System.out.println(driveable == vehicle);
}
}
public interface Driveable {}
public interface Vehicle {}
@Component
public class Car implements Vehicle, Driveable{}
@Configuration
public class Config {
@Autowired
private Car car;
@Bean
public Vehicle vehicle() {
return car;
}
@Bean
public Driveable driveable() {
return car;
}
}
public class Application {
public static void main(String[] args) throws Exception {
final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class, Car.class);
final Driveable driveable = context.getBean("driveable", Driveable.class);
final Vehicle vehicle = context.getBean("vehicle", Vehicle.class);
System.out.println(driveable == vehicle);
}
}
以问题中的汽车为例,
- 将汽车定义为@Component。
- 在自动装配的 Config 中声明一个字段
Car car
。
- 使用从两个@Bean 注释方法返回的自动装配字段。
如果我们使用 @ComponentScan
,汽车组件将被自动拾取。否则,如果我们自己创建上下文,我们可以在 AnnotationConfigApplicationContext
构造函数中传递 Car class(如代码所示)。
我有一个 class,假设 'DefaultService' 实现了两个接口:'Service1' 和 'Service2'。 Spring java 配置如下所示:
@Bean
Service1 defaultService() {
return new DefaultService();
}
现在,我有另一个需要 'Service2'.
的 bean Foopublic class Foo implements AnotherInterface {
@Autowired
private Service2 service2;
}
并且这个 bean 也是通过 Java 配置配置的:
@Bean
AnotherInterface anotherInterface(){
return new Foo();
}
Spring 不喜欢这个配置。我想这是有道理的,因为 'DefaultService' 公开为 'Service1',而不是 'Service2'(Foo 需要)。
No qualifying bean of type [...Service2] found for dependency: expected at least 1 bean which qualifies ...
当然,我可以将 DefaultService 公开为 Service2。但是如果有另一个 bean 需要 Service1 怎么办? Spring 针对此场景的建议是什么?我发现的另一个(奇怪的)问题是以下配置有效:
@Bean
Service2 defaultService(){ // exposing the bean as Service2, to fix dependency on Foo
return new DefaultService();
}
@Bean
AnotherDependant anotherDependant(Service1 service1){
return new AnotherDependant(service1);
}
Spring 如何将 Service1 连接到 'AnotherDependant' 的配置声明(我在第一个场景中对 @Autowired 感到不满意)? 我正在使用 Spring 3.2.2.RELEASE,尽管我怀疑版本是否真的很重要..
我的最佳解决方法是:
@Bean
DefaultService defaultService(){
return new DefaultService();
}
@Bean
Service1 service1(){
return defaultService();
}
@Bean
Service2 service2(){
return defaultService();
}
但这很丑...
=========================================== ========================== 正在回复@Oskar。 基本上@Oskar 的建议与在 xml 中声明两个相同。即在 spring 容器中创建两个相同 class 的实例。
public interface Driveable {}
public interface Vehicle {}
public class Car implements Vehicle, Driveable{}
@Configuration
public class Config {
@Bean
public Vehicle vehicle() {
return new Car();
}
@Bean
public Driveable driveable() {
return new Car();
}
}
public class Main {
public static void main(String[] args) {
final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
final Driveable driveable = context.getBean("driveable", Driveable.class);
final Vehicle vehicle = context.getBean("vehicle", Vehicle.class);
System.out.println(driveable == vehicle);
}
}
public interface Driveable {}
public interface Vehicle {}
@Component
public class Car implements Vehicle, Driveable{}
@Configuration
public class Config {
@Autowired
private Car car;
@Bean
public Vehicle vehicle() {
return car;
}
@Bean
public Driveable driveable() {
return car;
}
}
public class Application {
public static void main(String[] args) throws Exception {
final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class, Car.class);
final Driveable driveable = context.getBean("driveable", Driveable.class);
final Vehicle vehicle = context.getBean("vehicle", Vehicle.class);
System.out.println(driveable == vehicle);
}
}
以问题中的汽车为例,
- 将汽车定义为@Component。
- 在自动装配的 Config 中声明一个字段
Car car
。 - 使用从两个@Bean 注释方法返回的自动装配字段。
如果我们使用 @ComponentScan
,汽车组件将被自动拾取。否则,如果我们自己创建上下文,我们可以在 AnnotationConfigApplicationContext
构造函数中传递 Car class(如代码所示)。