How are the components scanned in spring boot - java

How does spring boot take care of component scan? We do not specify <component-scan> tag in spring boot in some web.xml file. We do not write any dispatcher servlet in spring boot. So where does spring boot do a component scan and how does it register all the controllers, services? What is the entry point for the spring boot web services micro-service? Note: Since it is a web-project I may not want to use the main method here.

There is an implicit one for the same package and sub-packages if you take a look at the annotation:
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
#Documented
#Inherited
#Configuration
#EnableAutoConfiguration
#ComponentScan
public #interface SpringBootApplication {...
Of course, it will be executed after the run method:
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
The question was: we do not specify component-scan and this is not true. It is declared in the Spring Boot annotation.
Edit 1: Spring MVC alternative
However, <component-scan> is a Spring annotation not just Spring Boot. You could configure your WAR web app with Spring MVC and you will not need Spring Boot libraries at all. Take a look at: http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#mvc-config-customize
#Configuration
#EnableWebMvc
public class ConfigWebMVC extends WebMvcConfigurerAdapter
{
...
}
Additionally, for better understanding of #ComponentScan I would like to highlight some points of the documentation:
About bean lifecycle:
By default, ApplicationContext implementations eagerly create and
configure all singleton beans as part of the initialization process..
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-factory-lazy-init
About Component scanning:
By default, classes annotated with #Component, #Repository, #Service,
#Controller, or a custom annotation that itself is annotated with
#Component are the only detected candidate components. However, you
can modify and extend this behavior simply by applying custom filters.
Add them as includeFilters or excludeFilters parameters of the
#ComponentScan annotation (or as include-filter or exclude-filter
sub-elements of the component-scan element)
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-scanning-filters

Related

Auto-Configuration vs Auto-Wiring - Spring Boot

What is the difference between Spring Boot's auto-configuration and auto-wiring?
Is it that, autowiring is injection of a Bean into another class, and auto-configuration is the term used for complete auto-wired application?
Auto-configuration in Spring refers to what Spring does for you to configure your application based on the dependencies that you have added. Instead of having bean definitions and having to configure your own stuff in Spring MVC (Do you remember the amount of xml configs you had to do?), Spring Boot essentially "listens" for things on your class path, and if it's something that it's able to auto-configure for you, it'll do so.
The #SpringBootApplication annotation automatically opts you into having Spring automatically configure various beans for you.
You are correct in the sense that auto-wiring relates to Dependency Injection. Having the annotation #Autowired inside one of your classes, means that you bring an instance of the class that's being annotated, into the class that the annotation exists in.
● #SpringBootApplication
If you don’t want to use #SpringBootApplication, the #EnableAutoConfiguration and #ComponentScan annotations that it imports defines that behaviour so you can also use that instead.
#SpringBootApplication actually defines #EnableAutoConfiguration and #ComponentScan
● #EnableAutoConfiguration
Spring Boot auto-configuration attempts to automatically configure your Spring application based on the jar dependencies that you have added
● #ComponentScan
All of your application components (#Component, #Service, #Repository, #Controller etc.) are automatically registered as Spring Beans.
● #Autowired is used for dependency injection

Spring Boot - What Annotations Are Needed

I am new to Spring Boot and I was just wondering if I need all annotations on my main method that I currently have
Here they are
#Import(ServiceConfiguration.class)
#SpringBootApplication(scanBasePackages = {"com.myproject.rest",})
#EnableJpaRepositories({"com.myproject.dao.jpa"})
#EntityScan(basePackages = "com.myproject.domain.jpa")
The class ServiceConfiguration.class has the following annotations
#Configuration
#EnableConfigurationProperties({SlackServiceProperties.class})
My database objects have the #Entity annotation, my rest classes have the #RestController annotation and my service classes have the #Component annotation
Just wondering are they all needed or can I exclude any of these annotations?
Thanks
If your main method is located in a top-level package, then all you need is:
#SpringBootApplication
It will automatically scan your sources recursively and pick up any #Bean's, #Component's or #Configuration's
Spring Data JPA will also automatically be configured if you're using this starter:
spring-boot-starter-data-jpa
If you structure your code like so:
com.myproject
- Application.java
com.myproject.configuration
- ServiceConfiguration.java
- OtherConfiguration.java
com.myproject.dao.jpa
- .. your repositories..
com.myproject.domain.jpa
- .. your #Entity classes...
You ONLY need to annotate your Application class with #SpringBootApplication.
All your #Configuration, repositories, other #Component and #Service classes will be auto scanned and configured by Spring Boot. That means you DON'T need to manually #Import configurations, you don't need #EnableJpaRepositories or #EntityScan.
All you need for Spring Boot to configure JPA is to include the JPA starter:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
You can follow this tutorial: https://spring.io/guides/gs/accessing-data-jpa/
You will see that it requires minimal annotations.
I assume it may depend on what you need, as I have not used a few of those in your example. I am not too familiar with all of Spring's "magic" when it comes to behind-the-scenes work it does with annotations. I have a perfectly functioning Spring Boot app with only
#SpringBootApplication
#Configuration
#ComponentScan
In order,
#SpringBootApplication is Spring's way of identifying that this application is from Spring Boot (one consequence, for example, is that there is no web.xml file).
#Configuration tells Spring to look for .properties files on your src path. Here, for example, you can define an "application.properties" file to define your datasource (database information for Spring to use).
#Component tells Spring to look for "Components" when it starts up the application. Pretty much #Controllers, #Service, etc. that may be found throughout your application.
For more accurate and in-depth explanations for many of Spring's annotations, may I direct you to:
http://www.techferry.com/articles/spring-annotations.html
and
https://dzone.com/refcardz/spring-annotations
These both have excellent descriptions and examples for the annotations.
Edit: #Configuration and #ComponentScan are included in #SpringBootApplication, as Strelok has pointed out in the comments.
Hope that helps.

Why does Spring Autowire fail when I move #SpringBootApplication?

I'm completely new to Spring/Spring Boot so I need some help. I didn't notice any documentation that indicated that the #SpringBootApplication or #ComponentScan had to be in a particular spot:
Working folder structures
Not working
I suppose your Application class is a typical Spring Boot Application like following:
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
SpringBootApplication is just a composed annotation of:
// Others
#Configuration
#EnableAutoConfiguration
#ComponentScan
public #interface SpringBootApplication { .. }
That ComponentScan with no explicit base package, would use the package of Application class as its base package for scanning. So, when you put this class in your root package, any annotated class in root package and under it would be scanned by the component scanner and your app would successfully work.
But when you move your Application into app package, that very same component scanner wouldn't scan those beans in hello package and Spring would fail to wire some beans together.
Spring Boot does not require any specific code layout to work, however, there are some best practices that help. You can read about those best practices in Spring Boot Documentation.

Spring component scan annotation and meta data

I'm actually studying spring application, more particularly the ComponentScan annotation that scans java packages to find some classes annotated with #Component.
I was wondering if the Spring ComponentScan annotation stores the related components found in other packages inside of the meta-datas of the Main Class (where I have the static void main method?)
Is this the only place where the framework stores these informations?
<context:component-scan base-package="com.mycompany.package" />
tells spring that it should look on com.mycompany.package and find classes annotated with the following (not only #Component ):
#Controller
#Repository
#Service
#Component
Then Spring will register these classes with the bean factory.
the Spring IoC container consumes a form of configuration metadata; this configuration metadata represents how you as an application developer tell the Spring container to instantiate, configure, and assemble the objects in your application.
Configuration metada are either an xml Configuration or java classes annotated with #Configuration that's where spring stores config informations.

How to decide which spring components should be added into application context?

I need a mechanism to descide which components should be included into the application context. Currently, I use #Import for it. Whether it works, #Import is for #Configuration only. Is there an alternative?
EDIT:
I use #ComponentScan to register spring beans and components. I have a directory with controllers annotated with #Controller. For testing purpose I do not want to register all controllers, but only specific. Can I use something like
Currently I use
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = TestConfiguration.class)
#Transactional
#TransactionConfiguration(defaultRollback = true){/*testings*/}
#Configuration
#EnableAutoConfiguration
#ComponentScan(basePackageClasses = {AccountsRepository.class, LogoutService.class})
#Import({AccountCommandsController.class})
public class TestConfiguration {}
#Import works for me, but its for Configurations only, not for registering controller components. Is there an equaliant for controllers or components?
If are using Spring 3.1 you should really be using Spring Profiles for situations where you conditionally need to include beans in the application context. It makes setting up tests very easy
If you are using Spring 4 and your needs are not covered by profiles, you can look into Spring's #Conditional support
If you use that way, there is no need to use #Include. Just have regular #Configuration classes where either the whole class is annotated with #Profile or specific #Bean methods (only supported in Spring 4)
You can then activate whatever profiles the specific test requires by using #ActiveProfiles

Categories