ChatGPT解决这个技术问题 Extra ChatGPT

How to scan multiple paths using the @ComponentScan annotation?

I'm using Spring 3.1 and bootstrapping an application using the @Configuration and @ComponentScan attributes.

The actual start is done with

new AnnotationConfigApplicationContext(MyRootConfigurationClass.class);

This Configuration class is annotated with

@Configuration
@ComponentScan("com.my.package")
public class MyRootConfigurationClass

and this works fine. However I'd like to be more specific about the packages I scan so I tried.

@Configuration
@ComponentScan("com.my.package.first,com.my.package.second")
public class MyRootConfigurationClass

However this fails with errors telling me it can't find components specified using the @Component annotation.

What is the correct way to do what I'm after?

Thanks

Two correct answers given at about the same time as far as I can tell. I'll give the accept to hage just because he has less points, but thank you both.
If you are wondering the same thing for kotlin version check this one stackoverflow.com/a/62818187/7747942

h
hage

@ComponentScan uses string array, like this:

@ComponentScan({"com.my.package.first","com.my.package.second"})

When you provide multiple package names in only one string, Spring interprets this as one package name, and thus can't find it.


P
Prancer

There is another type-safe alternative to specifying a base-package location as a String. See the API here, but I've also illustrated below:

@ComponentScan(basePackageClasses = {ExampleController.class, ExampleModel.class, ExmapleView.class})

Using the basePackageClasses specifier with your class references will tell Spring to scan those packages (just like the mentioned alternatives), but this method is both type-safe and adds IDE support for future refactoring -- a huge plus in my book.

Reading from the API, Spring suggests creating a no-op marker class or interface in each package you wish to scan that serves no other purpose than to be used as a reference for/by this attribute.

IMO, I don't like the marker-classes (but then again, they are pretty much just like the package-info classes) but the type safety, IDE support, and drastically reducing the number of base packages needed to include for this scan is, with out a doubt, a far better option.


Could someone explain why @ComponentScan({"com.app", "com.controllers"}) doesn't work for me but @ComponentScan(basePackageClasses ={"com.controllers"}) does work nice ? I find it boring writing every class name
You only have to specify one class in the package, for the package you want to scan. This is known as a marker class. If you need to scan a package higher in the hierarchy that has no classes, spring suggests a technique using a "spring marker" interface or final class defined in that package solely for the purpose of package scanning.
Thank you. I am so sick of tracking down #wheresWaldo with string-magic/magic-strings.
m
mprabhat

Provide your package name separately, it requires a String[] for package names.

Instead of this:

@ComponentScan("com.my.package.first,com.my.package.second")

Use this:

@ComponentScan({"com.my.package.first","com.my.package.second"})

Java's "when is a comma-separated", "when is it a string-array", "when is it a string varargs" jigsaw puzzle drives me nuts sometimes.
s
shashwatZing

Another way of doing this is using the basePackages field; which is a field inside ComponentScan annotation.

@ComponentScan(basePackages={"com.firstpackage","com.secondpackage"})

If you look into the ComponentScan annotation .class from the jar file you will see a basePackages field that takes in an array of Strings

public @interface ComponentScan {
String[] basePackages() default {};
}

Or you can mention the classes explicitly. Which takes in array of classes

Class<?>[]  basePackageClasses

k
ksw

You use ComponentScan to scan multiple packages using

@ComponentScan({"com.my.package.first","com.my.package.second"})


F
Farouk.ch

You can also use @ComponentScans annotation:

@ComponentScans(value = { @ComponentScan("com.my.package.first"),
                          @ComponentScan("com.my.package.second") })

Please consider adding explanation to your answer
A
Amirtha Krishnan

make sure you have added this dependency in your pom.xml

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

Thanks after spending close to half an hour this was the missing dependency
Spring Context is the only required dependency for those annotations.
D
Dharman

I use:

@ComponentScan(basePackages = {"com.package1","com.package2","com.package3", "com.packagen"})