7

Given I have a Spring bean configured as

@Service("myService")
public class DefaultService extends MyService {
}

and a class using this bean

public class Consumer {
    @Autowired
    @Qualifier("myService")
    private MyService service;
    ...
}

I now want my project, that includes the preceding classes, to have Consumer another implementation of MyService being injected. Therefore I would like to overwrite the bean myService

@Service("myService")
public class SpecializedService implements MyService {
}

resulting in Consumer carrying now an instance of SpecializedService instead of DefaultService. By definition I cannot have two beans with the same name in the Spring container. How can I tell spring, that the definition of the new service shall overwrite the older one? I don't want to modify the Consumer class.

Lars Blumberg
  • 19,326
  • 11
  • 90
  • 127

4 Answers4

3

Either define the service bean explicitly

<bean id="myService" class="x.y.z.SpecializedService" />

or component-scan it.

In either event, in your application context, avoid explicitly defining DefaultService and avoid component-scanning it.

  • Thanks, Willie. We ended up with your solution since we decided also for maintenance reasons (we're talking about hundreds of services) to keep the list of every service in one file - namely the spring bean configuration. Defining just id and the classname is not too painful as using annotations only is more tempting. – Lars Blumberg Apr 07 '11 at 08:37
2

Exclude it from component-scan by using a filter

<component-scan base-package="your-package">
    <exclude-filter type="regex" expression="DefaultService" />
</component-scan>

Not sure if there is a way to do it with only annotations (other than removing the @Service annotation from DefaultService).

Wilhelm Kleu
  • 10,821
  • 4
  • 36
  • 48
  • Thanks, Wilhelm, I am sure your solution would work. But then I would have to scan for my services by myself. Good idea! – Lars Blumberg Apr 07 '11 at 08:34
0

Annotation based wiring happens before the XML based configuration, that means beans defined in XML will overwrite those wiring done by Annotations. So defining it explicitely in XML, like Willie has said will do the work

<bean id="myService" class="x.y.z.SpecializedService" />

Spring recommends using XML for service and repository beans and annotation for MVC beans. It also recommends @Autowired without component scanning. But Annotation are in general encouraged, although it merges code and configuration together (against seperation of concerns).

Second thing is to use @Qualifiers("id of declared bean") where it is being passed.

vimal krishna
  • 2,886
  • 28
  • 22
-3

I know , its late . Still posting it.

You should have different names for different implementations of MyService.

For instance

@Service("mySpecializedService")
public class SpecializedService implements MyService {
}

@Service("myService")
public class DefaultService extends MyService {
 }

While autowiring them ( say in Controller) , you may use @Qualifier to inject desired implementation as mentioned below.

To get default implementation

@Autowired
@Qualifier("myService")
MyService myService;   

To get specialized implementation

@Autowired
@Qualifier("mySpecializedService")
MyService myService;
Gyro
  • 733
  • 7
  • 11