Reputation: 349
In my spring-based project I have a core module ('core') with a class
@Component
public class Superclass {
// stuff
}
instances of which are injected by type throughout the code like this:
public class AService {
@Autowired
private Superclass superclass;
// service stuff
}
I also have two other modules that depend on the core module and one of which (let's call it 'module1') extends Superclass:
@component
public class Subclass extends Superclass {
// overridden stuff
}
The other module ('module2') uses Superclass as is.
Now I want that when I compile and run 'child1' an instance of Subclass is used everywhere an instance of Superclass is expected. So I write a configuration class:
@Configuration
public class Module2Configuration {
@Bean
public Superclass superclass(){
return new Subclass();
}
}
When I run this I see both Superclass and Subclass instantiated which is definitely not what I want. How do specify in 'module1' which type Spring should instantiate?
Upvotes: 2
Views: 15643
Reputation: 11
There are 2 methods: Use @Qualifier("SubclassName") Or Mark your subclass as @Component and declare the subclass when @Autowired
In your case:
Use @Qualifier("SubclassName")
@Component
public class Superclass {
// stuff
}
@component
public class Subclass extends Superclass {
// overridden stuff
}
public class AService {
@Autowired
@Qualifier("Subclass")
private Superclass superclass;
// service stuff
}
2.Mark your subclass as @Component and declare the subclass when @Autowired
public class Superclass {
// stuff
}
@component
public class Subclass extends Superclass {
// overridden stuff
}
public class AService {
@Autowired
private Subclass subclass;
// service stuff
}
Upvotes: 1
Reputation: 917
Spring eagerly instantiates singleton beans as stated in the documentation:
By default, ApplicationContext implementations eagerly create and configure all singleton beans as part of the initialization process.
which might explain why both @Components
are created.
To specifiy which implementation is provided as a dependency you might want to check on Qualifiers that enable to choose between different implementations. In combination with lazy loading this should do the trick.
Depending on your personal taste you could also use delegation instead of inheritance using a separated interface:
public interface MyService {
public String foobar(int baz);
}
public static class CommonBehavior {
// whatever is used by Superclass and Subclass
}
@Component @Lazy
public class FormerSuperClass implements MyService {
private final CommonBehavior ...;
...
}
@Component @Lazy
public class FormerSubClass implements MyService {
private final CommonBehavior ...;
...
}
Good luck!
Upvotes: 2
Reputation: 1806
You can use @Qualifier("some name") annotation. There is more information about that: http://blogs.sourceallies.com/2011/08/spring-injection-with-resource-and-autowired/
Upvotes: 3