Spring Boot @EnableAutoConfiguration
1. Introduction
In this article, We'll be learning how to use @EnableAutoConfiguration annotation in spring boot.
@EnableAutoConfiguration is an interface as part of org.springframework.boot.autoconfigure package.
2. @EnableAutoConfiguration
This enables auto-configuration of your application context that is based on our needs and tries to attempt to configure beans. Mainly this autoconfiguration is decided based on your classpath and what are the jars added to the application.
If you have added tomcat-embedded.jar then it tries to intellectually configure TomcatServletWebServerFactory if you do not have specified explicitly as ServletWebServerFactory bean.
@Retention(value=RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters={@ComponentScan.Filter(type=CUSTOM,classes=TypeExcludeFilter.class),})
public @interface SpringBootApplication
Note:
If you are using @SpringBootApplication then by default auto-configure feature is enabled automatically. So, adding explicitly @EnableAutoConfiguration annotation has no value added.
Read more on @ComponentScan annotation.
Below are the example classes created to simulate auto configurations. In real-time applications, manually created classes do not need to use this annotation. In this example, trying to add custom classes to be auto-configured by spring with @EnableAutoConfiguration.
[post_ads]
class Message {
public String getMessage() {
return "New message generated";
}
}
@Controller
class MessageController {
Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private Message msg;
@PostMapping("/send")
public void messageSender() {
String messag = msg.getMessage();
logger.info("Message : " + messag);
logger.info("Message sent....");
}
}
package com.javaprogram.auto.configurations;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
@EnableAutoConfiguration
public class AutoConfigureApplication {
public static void main(String[] args) {
SpringApplication.run(AutoConfigureApplication.class, args);
}
}
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.2.6.RELEASE)
2020-04-19 12:44:00.498 INFO 78470 --- [ main] c.j.a.c.AutoConfigureApplication : Starting AutoConfigureApplication on.local with PID 78470 (/Users/Spring-Boot-Tutorials/target/classes started by in /Users/workspace/Spring-Boot-Tutorials)
2020-04-19 12:44:00.501 INFO 78470 --- [ main] c.j.a.c.AutoConfigureApplication : No active profile set, falling back to default profiles: default
2020-04-19 12:44:01.425 INFO 78470 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2020-04-19 12:44:01.441 INFO 78470 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2020-04-19 12:44:01.441 INFO 78470 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.33]
2020-04-19 12:44:01.527 INFO 78470 --- [ main] o.a.c.c.C.[.[localhost].[/api/v1] : Initializing Spring embedded WebApplicationContext
2020-04-19 12:44:01.528 INFO 78470 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 996 ms
2020-04-19 12:44:01.711 INFO 78470 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2020-04-19 12:44:01.796 INFO 78470 --- [ main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page template: index
2020-04-19 12:44:01.964 INFO 78470 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path '/api/v1'
2020-04-19 12:44:01.967 INFO 78470 --- [ main] c.j.a.c.AutoConfigureApplication : Started AutoConfigureApplication in 2.135 seconds (JVM running for 2.708)
2020-04-19 12:44:32.079 INFO 78470 --- [nio-8080-exec-1] o.a.c.c.C.[.[localhost].[/api/v1] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2020-04-19 12:44:32.079 INFO 78470 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
When I hit localhost:8080/api/v1/send api, it returns 404 always.
Because created controller and beans are not registered with spring because these are not auto-configured by spring even though @EnableAutoConfiguration is enabled.
Now, we have to tell spring to configure all these as below. Let us see if the below configuration works or not?
@EnableAutoConfiguration
public class AutoConfigureApplication {
@Bean
public Message getMessage() {
return new Message();
}
@Bean
public MessageController getMessageController() {
return new MessageController();
}
public static void main(String[] args) {
SpringApplication.run(AutoConfigureApplication.class, args);
}
}
Yes now, all of these are registered and after hitting the request got the response as a success.
2020-04-19 13:04:49.728 INFO 79367 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2020-04-19 13:04:49.751 INFO 79367 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 23 ms
2020-04-19 13:04:49.808 INFO 79367 --- [nio-8080-exec-1] c.j.a.configurations.MessageController : Message : New message generated
2020-04-19 13:04:49.809 INFO 79367 --- [nio-8080-exec-1] c.j.a.configurations.MessageController : Message sent...
3. Exclude Auto-Configuration Classes
If you do not want to include some of the classes then we can exclude them using exclude and excludeName attributes.
excludeName - which takes class names that should be ignored by auto configurations.
public abstract String[] excludeName
exclude - Which takes the classes that are never applied to auto configurations.
public abstract Class[] exclude
Now, Let us try to exclude the classes that we have created earlier in this article.
@EnableAutoConfiguration(exclude = MessageController.class, excludeName = "Message")
public class AutoConfigureApplication {
public static void main(String[] args) {
SpringApplication.run(AutoConfigureApplication.class, args);
}
}
[post_ads_2]
This code produces the error because these two create by us and they are not auto configured classes. Only autoconfigured classes that are managed by application context will only be excluded. Even though excluding user-defined classes will not work with exclude attributes.
2020-04-19 13:13:13.051 ERROR 79761 --- [ main] o.s.boot.SpringApplication : Application run failed
java.lang.IllegalStateException: The following classes could not be excluded because they are not auto-configuration classes:
- com.javaprogram.auto.configurations.MessageController
at org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.handleInvalidExcludes(AutoConfigurationImportSelector.java:209) ~[spring-boot-autoconfigure-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.checkExcludedClasses(AutoConfigurationImportSelector.java:195) ~[spring-boot-autoconfigure-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.getAutoConfigurationEntry(AutoConfigurationImportSelector.java:119) ~[spring-boot-autoconfigure-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.autoconfigure.AutoConfigurationImportSelector$AutoConfigurationGroup.process(AutoConfigurationImportSelector.java:396) ~[spring-boot-autoconfigure-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorGrouping.getImports(ConfigurationClassParser.java:878) ~[spring-context-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorGroupingHandler.processGroupImports(ConfigurationClassParser.java:808) ~[spring-context-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorHandler.process(ConfigurationClassParser.java:779) ~[spring-context-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:192) ~[spring-context-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:319) ~[spring-context-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:236) ~[spring-context-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:275) ~[spring-context-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:95) ~[spring-context-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:706) ~[spring-context-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:532) ~[spring-context-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141) ~[spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747) [spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) [spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) [spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) [spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) [spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at com.javaprogram.auto.configurations.AutoConfigureApplication.main(AutoConfigureApplication.java:28) [classes/:na]
Exclude JmsAutoConfiguration and SecurityAutoConfiguration:
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
@EnableAutoConfiguration(exclude = JmsAutoConfiguration.class, excludeName = "SecurityAutoConfiguration")
public class AutoConfigureApplication {
}
Pass the class names to either exclude or excludenames attributes. This tells to spring to ignore these two classes when doing auto configuration step. Here, it won't throw an exception because these are auto configured by spring boot.
@EnableAutoConfiguration(exclude = { SecurityAutoConfiguration.class, SecurityAutoConfiguration.class })
[post_ads_2]
4. Conclusion
In this article, We've seen how to use @EnableAutoConfiguration in spring boot and its attributes. If you are using spring boot, you need not mention this annotation.
Alternatively, we can use ComponetScan to register with Spring.
Leave your questions in the comments section.
All the examples shown in this article are over GitHub.
GitHub Code
0 Comments