ripudam ripudam - 2 months ago 37
Java Question

ComponentScan excludeFilters Not Working In Spring 4.0.6.RELEASE

I have a class which I want to exclude while component scanning. I am using the below code to do that but that doesn't seem to work although everything seems to be right

@ComponentScan(basePackages = { "common", "adapter", "admin"}, excludeFilters = { @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = ServiceImpl.class) })

Actually I want have "ServiceImpl" class, which implements "Service" interface, is being used in my rest api logic and while doing the integration test of an api I want to exclude this implmentation and load the mocked implementation. But this doesn't seem to happen as even after using the above I am getting the below error

No qualifying bean of type [admin.Service] is defined: expected single matching bean but found 2: ServiceMockImpl,ServiceImpl

I spent too much of time on this but nothing works.

Any help is appreciated.


After lot of work and research I noticed that Spring's behavior is little weird in term of component scanning.

Artifacts were like this :

"ServiceImpl" is the real implementation class which implements "Service" interface. "ServiceMockImpl" is the mocked implantation class which implements "Service" interface.

I wanted to tweak the component scanning so that it only loads the "ServiceMockImpl" but not "ServiceImpl".

I had to add the "@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = ServiceImpl.class)", in the "@ComponentScan" of test configuration class, to exclude that particular class from component scanning. But both the classes were getting loaded even after doing the above changes and tests were failing.

After lot of work and research I found that the "ServiceImpl" was getting loaded because of the other class which was getting loaded and has "@ComponentScan" for all packages on top of in it. So I added the code to exclude the "Application" class from the component scanning as follows "@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = Application.class)".

After that it worked as expected.

Code like below

@ComponentScan(excludeFilters = {
    @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = OAuthCacheServiceImpl.class),
    @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = Application.class) }, basePackages = {
    "common", "adapter", "admin"})

I have seen that lot of questions on component scanning are unanswered for long hence I thought to add these details as it may help somebody in the future.