Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ComponentScan excludeFilters Not Working In Spring 4.0.6.RELEASE

Tags:

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.

like image 730
Ripu Daman Avatar asked Aug 28 '14 13:08

Ripu Daman


People also ask

How do I enable component scans in Spring?

Using @ComponentScan in a Spring Application. With Spring, we use the @ComponentScan annotation along with the @Configuration annotation to specify the packages that we want to be scanned. @ComponentScan without arguments tells Spring to scan the current package and all of its sub-packages.

What is the difference between @component and ComponentScan?

@Component and @ComponentScan are for different purposes. @Component indicates that a class might be a candidate for creating a bean. It's like putting a hand up. @ComponentScan is searching packages for Components.

Where can I use ComponentScan?

The @ComponentScan annotation is used with the @Configuration annotation to tell Spring the packages to scan for annotated components. @ComponentScan also used to specify base packages and base package classes using thebasePackageClasses or basePackages attributes of @ComponentScan.

Does Spring boot require component scan?

So if your application doesn't have a varying package structure then there is no need for explicit component scanning. Specifying a @Configuration -annotated class in the default package will tell Spring to scan all the classes in all the JARS in the classpath. Don't do that!


2 Answers

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.

HTH...

like image 81
Ripu Daman Avatar answered Oct 29 '22 16:10

Ripu Daman


At first,Thanks very much about the answers of @Yuriy and @ripudam,but what makes me confused is when my excludeFilters contains Configuration.class I have to use @Import to import the Classe which annotated by @Configuration.I found when i use excludeFilters = {@Filter(type = FilterType.ANNOTATION,value{EnableWebMvc.class,Controller.class}),all works well.The ContextLoaderListener doesn`t regist the Controller at first.

For example

//@Import(value = { SecurityConfig.class, MethodSecurityConfig.class, RedisCacheConfig.class, QuartzConfig.class }) @ComponentScan(basePackages = { "cn.myself" }, excludeFilters = {         @Filter(type = FilterType.ANNOTATION,value={EnableWebMvc.class,Controller.class}) }) public class RootConfig { } 
like image 36
Forest10 Avatar answered Oct 29 '22 16:10

Forest10