SpringBoot Auto configuration settings
Imagine that you're collaborating with a few teams working on various Spring boot projects or goods for ReallyBigCompanyTM. But you don't need the Spring Boot, only the basic Spring System.
Also, imagine that one of your developers had a brilliant idea at one point to remove one popular Application Context Configuration from all projects since she found that a few of the same beans are used by every business project.
@Configuration Settings
ReallyBigCompanySharedContextConfiguration public class {/ (1)
@Bean @Bean
Public flywayClone) (of ReallyBigCompanyProprietaryFlywayClone
New ReallyBigCompanyProprietaryFlywayClone) (is returned; / (2)
}
}
Imagine that a patented Flyway clone, i.e. something initializing and managing databases, was developed by ReallyBigCompany. And for any project in your business uses a relational database, extracting it into this shared structure makes sense. spring boot online training india
@Configuration Settings
@Import(SharedConfiguration.class ReallyBigCompany) / (1)
EarlyExitUnicornProjectContextConfiguration for Public Class
}
The SharedConfiguration is imported from now on by each company project, as it contains so many goodies (well, at the moment, just the Flyway clone, but you get the point).
As usual, you'd define your project-specific beans here.
Shared Application Context Configuration problem
In your business, having such a shared Spring Boot configuration works, but there is a problem on the horizon.
What if you want to build another project that needs to import the shared configuration, but does not have a ReallyBigCompanyProprietaryFlywayClone, since a relational database is not used?
Then you need a way to tell Spring that @Configuration is all right, but please don't build that particular @Bean one-just forget it. However, go ahead and build all the other @Beans.
That is exactly what the @Conditional annotation of Spring is about.
What is the @Conditional annotation for Spring?
The @Conditional annotation has been offered by the Spring Framework since version 4.0 (released in 2013). You can put it on @Bean, @Components, or even @Configurations methods and it looks like that:
@Conditional(SomeCondition.class)
It has a "Condition" class parameter that returns a simple Boolean, which is a class that has a method called "matches".
True: Build @Bean, @Component, or @Configuration (Further Evaluate/Register)
False: Don't build @Bean, @Component, or @Configuration (Stop Evaluating/Registering)
In short: While some @Bean meanings come with an ApplicationContextConfiguration, whether a bean is generated or not, you as the end-user may still have some impact.
Make @Conditional @Conditional shared ApplicationContextConfiguration
For our SharedConfiguration, what does that mean? We can reshape it to look like this:
@Configuration Settings
ReallyBigCompanySharedContextConfiguration Public Class
@Bean @Bean
@Conditional(Condition.classIsRelationalDatabase) / (1)
Public flywayClone) (of ReallyBigCompanyProprietaryFlywayClone
Fresh ReallyBigCompanyProprietaryFlywayClone) (return;);
}
}
It's exactly the same ContextConfiguration as before, except now that your @Bean method is also annotated with a condition we still have to write.
A Spring Condition Implementation
Com.marcobehler package;
Org.springframework.context.annotation.condition for importing;
Org.springframework.context.annotation. ConditionContext importation;
Org.springframework.core.type. AnnotatedTypeMetadata importation;
IsRelationalDatabaseCondition public class implements the condition.
From @Override
Boolean public matches(context of ConditionContext, metadata of AnnotatedTypeMetadata) {/ (1)
Return the oracleJdbcDriverOnClassPath) (& & UrlSet(context) database; / (2)
}
UrlSet(ConditionContext context) private boolean database {/(3)
Property("spring.datasource.url); "returns context.getEnvironment().containsProperty);
}
JdbcDriverOnClassPath) ({/ (4) Private Boolean oracle
Try {Try
Class.forName("oracle.jdbc.driver. OracleDriver);;);
True Return;
} (ClassNotFoundException e) {Catch}
False return;
}
}
}
Condition is an interface that exposes a method called "matches" which returns true/false: whether or not the condition has been met.
There are two conditions that I'm mixing up here: I want to verify if the Oracle driver class is on the classpath. And I want to check if the user in the .properties file has set the database URL.
It's pretty straightforward to search for a property since you can go through Spring's environment-class, which in turn will search for a property for all @PropertySources (think: application.properties).
It is also very easy to search for dependencies: you can search on your classpath for the existence of a certain class and if it is there, then you can conclude there is the entire library.
While in the real world you will most definitely break this class into two separate situations, it illustrates two most critical conditions:
Depending on particular available assets, you can build @Beans.
Depending on specific libraries, you can build @Beans on your classpath.
Spring boot
Even though we have not yet covered any Spring Boot source code, a new insight is looming now.
What if Spring Boot is just a setup for shared context with loads of @Conditionals?
Conditionals that build a DataSource for you because unique properties have been set (think: spring.datasource.url)? Or @Conditionals that boot because you have the Tomcat libraries on your classpath, an embedded Tomcat server for you?
Yeah, that is exactly what Spring Boot is (and not much more).
Source code for Spring Boot
You may want to check out the Spring Boot project yourself, to follow along. Don't worry, it's just a simple 'git clone' and import of projects away.
Note also that in the master branch, Spring Boot essentially moved to Gradle as a construction method, whereas older release branches are still based on Maven.
How AutoConfiguration can be analyzed: DataSourceAutoConfiguration
A subpackage and AutoConfiguration for any Spring or 3rd party library that Spring Boot interfaces with will be found within the spring-boot-autoconfigure module.
First, let's take a look at the class DataSourceAutoConfiguration.
Woohaa, look at this festival of annotations! Let's go line-by-line through it.
@Settings(proxyBeanMethods = false) / (1)
/ (2) @ConditionalOnClass ({DataSource.class, EmbeddedDatabaseType.class})
@EnablePropertiesConfiguration(DataSourceProperties.class) / (3)
/ (3) @Import ({DataSourcePoolMetadataProvidersConfiguration.class, DataSourceInitializationConfiguration.class})
DataSourceAutoConfiguration Public Class
@Settings(proxyBeanMethods = false)
@Conditional(Condition.classEmbeddedDatabase)
@MissingBeanConditionalOnMissingBean ({DataSource.class, XADataSource.class})
EmbeddedDataSourceConfiguration.class) @Import
EmbeddedDatabaseConfiguration Safe Static Class
}
@Settings(proxyBeanMethods = false) / (4)
/ (5) @Conditional(PooledDataSourceCondition.class)
/ (6) @ConditionalOnMissingBean ({DataSource.class, XADataSource.class})
@Import ({ConfigurationDataSource. Hikari.class, ConfigurationDataSource. Tomcat.class, / (7)
ConfigurationDataSource. Dbcp2.class, ConfigurationDataSource. Generic.class,
JmxConfiguration.class DataSource})
PooledDataSourceConfiguration Safe Static Class {PooledDataSourceConfiguration
}
/ A few more
}
Standard Spring @Configuration is a DataSourceAutoConfiguration.
You need to provide two classes on the classpath for @Configuration to be further evaluated: DataSource and EmbeddedDatabaseType. If that conditional is false, @Configuration is not checked in its entirety.
For now, we can ignore these two lines, but as a fast side-note: @EnableConfigurationProperties allows you to automatically set/convert the properties you put into your .properties files to an entity, like the DataSourceProperties here.
There are two more, internal @Configurations, in the DataSourceAutoConfiguration.
On a PooledDataSourceCondition, it has a @Condition, which really is a nested @ConditionalOnProperty. Ouch!-Ouch!
PooledDataSourceConfiguration can only be further evaluated if no DataSource or XADataSource has been defined by the user ( i.e. YOU) yet.
That's a lot to digest, but Spring @Configurations, safe-guarded with @Conditionals, is practically natural. Let's take a look at the imported DataSourceConfiguration. Hikari.class, to top it off.
/ * * / * *
* Setup of Hikari DataSource.
* /
@Settings(proxyBeanMethods = false) / (1)
@ConditionalOnClass(Source.classHikariData) / (2)
/ (3) @ConditionalOnMissingBean(DataSource.class)
@ConditionalOnProperty(name = "spring.datasource.type", withValue = "com.zaxxer.hikari. HikariDataSource", / (4)
SuitIfMissing = true)
Hikari Static Class
@The Bean / (5)
@PropertiesConfiguration(prefix = "spring.datasource.hikari")
HikariDataSource dataSource(Properties of DataSourceProperties)
DataSource of HikariDataSource = createDataSource(properties, HikariDataSource.class);
(StringUtils.hasText(properties.getName))) (if
DataSource.setPoolName(properties.getName());;Name);
}
DataSource Return;
}
}
Another Standard Spring @Settings.
HikariDataSource.class must be placed on the classpath, i.e. the pom.xml/build.gradle file must be linked to Hikari-cp.
A DataSource bean must not have been entered by the user himself.
Either the "spring.datasource.type" property is missing, or it must have a "com.zaxxer.hikari. HikariDataSource" unique meaning.
If all these circumstances match, a good old Spring @Bean is made. A Source for HikariData. This is what you will have to build yourself otherwise, by looking at the documentation of HikariCP.
Then a DataSource is booted for you, which you would otherwise have to manually configure yourself.
Or in simpler terms:
If you have HikariCP on your classpath, you will automatically generate a @Bean HikariDataSource. If you had (and Hikari excluded) the DBCP2 library on your classpath, then you would get a different pool of connexions. By simply modifying dependencies.
This is @Conditionals' authority!
Exercise:
Tomcat AutoConfiguration analysis
From the beginning, back to the question: How can Spring Boot boot an embedded Tomcat server by default? Plain:
If Tomcat is on the classpath, it needs to be checked. (@OnClassConditional(Tomcat.class))
Special properties that are set by the user, such as server.port, may be taken into account.
To make your @RestControllers with their @GetMappings and @PostMappings function, you need to take Spring WebMVC's DispatcherServlet and register it with Tomcat.
Your embedded Tomcat server (and, therefore, your DispatcherServlet) needs to start.
The exercise for you is to discover and understand the basic auto-configuration of those servlets, with their necessary conditions.
Conclusion
I hope you reach to a conclusion about Spring Boot auto-configuration settings. Thus, Spring boot enables you to configure the Spring app automatically on the basis of Jar dependencies. It helps to locate the various classes within the classpath. Later, the autoconfiguration mechanism makes sure to build and connect the beans you require. You can learn more through Spring boot online training. You can learn more about auto-configuration through Spring boot online training.
Comments
Post a Comment