For those of you who aren't familiar with it, a component scan makes it very easy to create a new component. All you need to do is place an @Component tag on the class itself and then indicate in one of your configuration files that Spring should scan for components in the directory that your class is in.
A brief example:
First, define the component using the @Component tag.
package my.component.pkg; import org.springframework.stereotype.Component; @Component public class MyComponent { ... }
Next, tell Spring to scan for components. I'll give both the Java and xml configurations, but really only one is necessary.
package my.configuration.pkg; import my.component.pkg.MyComponent; import org.springframework.context.annotation.*; @Configuration @ComponentScan("my.component.pkg") public class MyConfiguration { }
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.7.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.7.xsd"> <context:component-scan base-package="my.component.pkg" /> </beans>
Pretty nifty, huh? Well, maybe. Until you try to run a bunch of integration tests. You see, I might have hundreds (or even thousands) of components defined this way (within the same package or in multiple base packages). Now suppose I want to run an integration test on MyComponent. When Spring starts up, it loads not just MyComponent, but every component in your application. This is not only unnecessary, but for a very large application, it can take up to a minute, possibly more, before your test can even begin running.
The above issue has led my team recently to abandoning using the component scan. We have begun defining beans using the @Bean tag in a Java configuration file in the same package as the component. The above example would then look like this:
package my.component.pkg; class MyComponent { ... }
package my.component.pkg; import org.springframework.context.annotation.*; @Configuration public class ComponentConfig { @Bean MyComponent myComponent() { return new MyComponent(); } .. }
We would define all components in the my.component.pkg package in this configuration file. Then, when running a test on MyComponent, I only need to load this configuration and can skip loading the components that are not needed for the test.
This finally brings me to my question: do you/would you use component scan to simplify the creation of component beans or do you/would you avoid it in order to be able to more easily control how much of the application context must be loaded when running a test? Please leave a response in the comments.