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
Related
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.
I am working on a Spring boot application that uses Spring JPA with PostgreSQL. I am using #SpringBootTest(classes = <my package>.Application.class) to initialize my unit test for a controller class.
The problem is that this is causing the entityManagerFactory bean (and many other objects related to jpa, datasource, jdbc, etc.) to be created which is not needed for unit tests. Is there a way to prevent Spring from automatically creating these objects till they are actually used the first time?
I spent a lot of time trying to load up only the beans I need for my unit test but ran into many errors. I am relatively new to Spring and I am hoping someone else has run into this before...and can help. I can post code snippets if needed.
Update: I am not sure if I should edit or answer my own question...choosing to edit since I ended up changing my approach to unit tests. I added this to my test config class.
#Configuration
#ComponentScan(basePackages = {"api.controller", "api.config", "api.utils"})
public class TestControllerConfig {
}
and I mocked out the service and repository classes.
You can disable auto configuration in spring-boot using exclude attribute of #EnableAutoConfiguration, as follows:
#Configuration
#EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
public class TestConfig {
}
From #EnableAutoConfiguration documentation:
If the class is not on the classpath, you can use the excludeName attribute of the annotation and specify the fully qualified name instead. Finally, you can also control the list of auto-configuration classes to exclude via the spring.autoconfigure.exclude property.
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
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.
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