Spring #ComponentScan annotation - spring

Why do we use #ComponentScan annotation in spring ? I am not being able to figure out the exact difference between context:componentscan in xml file and #ComponentScan annotations in java and how to use them in case of classes which have been annotated with #Configuration

In short, there is no difference.
#ComponentScan - Used with #Configuration classes, for example, when you have java-based configurations for Spring.
It provides support parallel with Spring XML's <context:component-scan> element. The purpose of those two are exactly the same - to scan spring components.

But there is one advantage of xml based configuration - you don't need to compile your java code. When you added some package under <context:component-scan> then you don't need to compile java source code. Place the xml configuration file in your server and restart it.

Related

What does it mean by #SpringBootConfiguration allows the configuration to be found automatically?

I was searching for the difference between the #Configuration vs #SpringBootConfiguration. I found many articles mentioned "As per the Spring documentation, #SpringBootConfiguration is just an alternative to the Spring standard #Configuration annotation. The only difference between the two is that the #SpringBootConfiguration allows the configuration to be found automatically".
So what does it mean by #SpringBootConfiguration allows the configuration to be found automatically? If we use the #Configuration for a class that contains #Bean annotated methods, Spring will create instantiation for those beans as well. Can anybody explain this to me clearly?
Because this question was driving me a little crazy and this was the first StackOverflow page I found, which didn't resolve the issue for me, I'm going to try to explain my findings:
#SpringBootApplication is a specialisation of #SpringBootConfiguration, which is a specialisation of #Configuration.
You may only have 1 #SpringBootConfiguration, which means you can't have both a #SpringBootConfiguration and a #SpringBootApplication in your application.
"#SpringBootConfiguration allows the configuration to be found automatically" means you don't have to do anything to have this (and therefore #SpringBootApplication) found. Other #Configuration classes are generally discovered by #ComponentScan
An extra advantage over #Configuration, is that it will be discovered by #StringBootTest.
Just open https://github.dev/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-docs/src/docs/asciidoc and search for SpringBootConfiguration you will find some information about it.
such as
#SpringBootConfiguration: enable registration of extra beans in the
context or the import of additional configuration classes. An
alternative to Spring’s standard #Configuration that aids
configuration detection in your integration tests.
and
Detecting Test Configuration If you are familiar with the Spring Test
Framework, you may be used to using #ContextConfiguration(classes=…​)
in order to specify which Spring #Configuration to load.
Alternatively, you might have often used nested #Configuration classes
within your test.
When testing Spring Boot applications, this is often not required.
Spring Boot’s #*Test annotations search for your primary configuration
automatically whenever you do not explicitly define one.
The search algorithm works up from the package that contains the test
until it finds a class annotated with #SpringBootApplication or
#SpringBootConfiguration. As long as you structured your code in a
sensible way, your main configuration is usually found.

Spring boot auto configuration with dependency and without #ComponentScan

Spring boot provides #ComponentScan to find packages to be scanned.
I am building a library which has #RestControllers inside with package com.mylib.controller. There are other classes as well with stereotype annotations in different packages.
So, if some one is developing SpringBoot Application with com.myapp base package.
He uses my library in his application. He need to mention #ComponentScan("com.mylib") to discover stereotype components of library.
Is there any way to scan components without including library package in #ComponentScan?
As spring-boot-starter-actuator expose its endpoints just with dependency, without defining #ComponentScan. OR any default package which is scanned regardless of application base package.
You could create a Spring Boot Starter in the same style as the Spring Provided Starters. They are essentially a jar'd library with a a spring.factories file pointing to the #Configuration class to load with some other annotations on there to provide overriding/bean back off (#ConditionalOnMissingBean) and generally provide their own #ConfigurationProperties.
Stéphane Nicoll provided an excellent demo of how to build one.
https://github.com/snicoll-demos/hello-service-auto-configuration
It is also documented in the Spring Boot documentation. https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-auto-configuration.html
The library approach would also work but I see no benefit in not making it a starter. Additionally for any library/starter I'd recommend dropping the #ComponentScan and just defining the beans in a #Configuration. This will work for sterotypes like #RestController etc. will function as normal if you create an #Bean out of it in a configuration.
Spring boot starter are special artifacts designed by Spring and used by Spring.
You can check that in the source code that contains mainly a
spring.provides file :
provides: spring-boot-actuator,micrometer-core
I don't know the exact way to process in the same way as Spring Boot Starter but as probably acceptable workaround, you could define in your jar a #Configuration class that specifies #ComponentScan("com.mylib").
#Configuration
#ComponentScan("com.mylib")
public class MyLibConfig {
//...
}
In this way, clients of the jar need "only" to import the #Configuration class :
#Import(MyLibConfig.class)
#Configuration
public class ClientConfig{
//...
}

Why AutoConfigurationPackages not consider #ComponentScan?

Spring Boot's support for Spring data configuration is generally by org.springframework.boot.autoconfigure.data.AbstractRepositoryConfigurationSourceSupport, and this class use the follow code to determine what packages to scan for repositories:
AutoConfigurationPackages.get(this.beanFactory)
So, basically Spring Data with Spring Boot only scan the package which contains the #EnableAutoConfiguration or #ImportAutoConfiguration, but not consider the #ComponentScan, Is this correct ?
The #ComponentScan annotation is a core Spring Framework feature to search for classes annotated with #Component. Since Spring Data repositories are interfaces (and not annotated), the #ComponentScan annotation won't pick them up.
If you are using Spring Data outside of Spring Boot, you can scan for Spring Data repositories using #EnableJpaRepositories with the basePackages attribute set.
When it comes to Spring Boot, there's usually no need to use either #ComponentScan or #EnableJpaRepositories. If you structure your code as suggested, both components and repositories will be picked up.
To get back to your original question about AbstractRepositoryConfigurationSourceSupport. If you look at the source of #SpringBootApplication you'll see it's annotated with #ComponentScan (to find #Components) and #AutoConfigurationPackage (via #EnableAutoConfiguration). The #AutoConfigurationPackage sets up AutoConfigurationPackages with the value that's later retrieved.
If you want to override the packages the Spring Data searches for repositories (for example in tests) you'll need to use #EnableJpaRepositories to completely override auto-configuration. I usually don't do this, but instead use #DataJpaTest and pick up my main configuration.

Can I start with a spring boot application without the annotations componentscan,autoconfiguration,configuration,springbootapplication?

I have written some code in order test integration with mongoDB. Please find the link to the main method for running this spring boot application below,
https://github.com/siva54/simpleusercontrol/blob/master/src/main/java/com/siva/UserManagementApplication.java
From what I have read, An application should contain any of the configurations from the following URL to declare how the applications manages the context,
http://docs.spring.io/autorepo/docs/spring-boot/current/reference/html/using-boot-using-springbootapplication-annotation.html
I haven't used any of those contexts, However my application works fine and I'm able to run it without any issues. Am I missing something here? Can you please help with the info of how my application is able to start and manage the context/dependencies automatically?
Thanks in advance
#SpringBootApplication is equivalent of #Configuration, #EnableAutoConfiguration and #ComponentScan. Let's consider why your application works without of any of this three annotations.
Why it works without #Configuration:
When Spring will scan packages, it will find all classes marked by #Configuration and will use them as part of configuration. But in next line you manually passed UserManagementApplication as configuration source:
SpringApplication.run(UserManagementApplication.class, args);
So spring doesn't need to find this class by scan. Therefor it is not necessary to mark it by #Configuration.
Why it works without #ComponentScan:
Class UserManagementApplication has #ImportResource("classpath:spring/application-context.xml") annotation. That means file spring/application-context.xml will be included into configuration. And this file contains next line:
<context:component-scan base-package="com.siva.*" />
So, you don't need use annotation for scan packages, because you already declared it in the xml file.
Why it works without #EnableAutoConfiguration:
This annotation allows to Spring to try guess and configure the components automatically. For example, if you include the following dependency in your build.gradle:
dependencies {
compile 'org.springframework.boot:spring-boot-starter-data-mongodb'
}
Spring configures all the components required to work with MongoDB automatically. And all you need just specify host and user/pass in the aplication.proprties file.
But you preferred to declare all needed beans manually in the spring/application-context.xml file. So, you simply don't need #EnableAutoConfiguration annotation at all.

spring-boot without #SpringBootApplication

I am attempting to migrate a spring, non-boot, app to a boot app. The current one builds a war file. Following these instructions, I am walking through the steps to migrate.
I am finding that the #SpringBootApplication annotation forces a lot of things to fail. For instance, it tries to auto config security when I really need the existing xml security config to remain as is. I found that I can override #EnableAutoConfiguration and exclude configuration classes (.i.e. SecurityAutoConfiguration.class). But I am finding it is doing this a great deal for the items I already have on my classpath. I decided it would be better to remove #SpringBootApplication and replace it with just #Configuration, #ComponentScan and #ImportResource to load my original context xml. The class extends SpringBootServletInitializer so that I can register my custom servlets and filters.
What I have found, it now no longer knows to load the application.yml or bootstrap.yml. What triggers auto configuration of these files? Do I fall back to loading with the traditional properties placeholder configurers? I want to avoid this as the next step is to hook it up to spring cloud config to centralize the management of the application configuration.
#SpringBootApplication is a alternative for #Configuration, #EnableAutoConfiguration and #ComponentScan.
Probably you want use #Configuration + #ComponentScan. If you want load xml configuration you can use: #ImportResource annotation.
If you want use autoconfiguration, but you can disable a few auto configurations, eg:
#EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
Details:
http://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-auto-configuration.html
http://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-configuration-classes.html
http://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-using-springbootapplication-annotation.html

Resources