Reputation: 4602
First, some code:
interface Foo {
void bar();
}
@Configuration
class FooConfig {
@Bean
public Foo foo() { return new MagicFoo(); }
class MagicFoo implements Foo { ... }
}
@Component
class FooImpl implements Foo {
public void bar() { }
}
@Component
class BarImpl {
final Foo foo;
public BarImpl(Foo foo) { this.foo = foo; }
}
As this example stands, when BarImpl
is instantiated, the Spring framework will look for a bean matching Foo
and prefer the bean defined by FooConfig
(i.e. the MagicFoo
) over the implementing-class FooImpl
.
My question is: is there any way to configure this code so that ONLY beans directly matching the interface (e.g. Foo
), and not any implementing classes (e.g. FooImpl
) are acceptable for a particular interface dependency? I.e. somehow configure Spring to treat Foo
dependencies in this special way.
In such a configuration, if I removed FooConfig
, I would get an error trying to instantiate BarImpl
because no suitable bean can be found, even though a bean for FooImpl
is available. In other words, with this desired configuration in place, the developer is forced to explicitly define beans for the identified interface instead of labeling implementing classes as beans.
Upvotes: 0
Views: 469
Reputation: 4602
At this point I've accomplished the desired behavior with the following setup:
@ActvityImplementation
)
@ActivityInterface
)@ActivityImplementation
annotation.
@ActivityInterface
annotation.This logic ensures that I (and anyone else using the framework) cannot forget to configure the "magic" interface implementation. When the "magic" implementation is present, it is the bean returned for the interface. When the "magic" implementation is not present, Spring falls back to the implementation bean, which then triggers the error.
Upvotes: 0
Reputation: 159086
If you have multiple beans implementing Foo
, they are all candidates for autowiring a parameter of type Foo
.
You cannot distinguish between beans created by @Bean
vs beans created by @Component
.
You can however use @Qualifier
to isolate/separate them.
@Configuration
class FooConfig {
@Bean
@Qualifier("ABC")
public Foo foo() { return new MagicFoo(); }
class MagicFoo implements Foo { ... }
}
@Component
@Qualifier("XYZ")
class FooImpl implements Foo {
public void bar() { }
}
@Component
class BarImpl {
final Foo foo;
public BarImpl(@Qualifier("ABC") Foo foo) { this.foo = foo; }
}
The parameter can now only be autowired by the @Bean
created bean, because that is the only one with the correct qualifier.
Upvotes: 2