In spring boot, there is a datasource automatic configuration class in the package spring-boot-autoconfigure
In the configuration file application.properties, after configuring spring.datasource.*, the datasource will be automatically configured
@Conditional(DataSourceAutoConfiguration.NonEmbeddedDataSourceCondition.class) @ConditionalOnMissingBean({ DataSource.class, XADataSource.class }) protected static class NonEmbeddedConfiguration { @Autowired private DataSourceProperties properties; @Bean @ConfigurationProperties(prefix = DataSourceProperties.PREFIX) public DataSource dataSource() { DataSourceBuilder factory = DataSourceBuilder .create(this.properties.getClassLoader()) .driverClassName(this.properties.getDriverClassName()) .url(this.properties.getUrl()).username(this.properties.getUsername()) .password(this.properties.getPassword()); if (this.properties.getType() != null) { factory.type(this.properties.getType()); } return factory.build(); } }
But there is a condition
@Conditional(DataSourceAutoConfiguration.NonEmbeddedDataSourceCondition.class)
It means that it will only be configured when there is a non-embedded DataSource, and the condition of the judgment is actually written in the DataSourceBuilder
private static final String[] DATA_SOURCE_TYPE_NAMES = new String[] { "org.apache.tomcat.jdbc.pool.DataSource", "com.zaxxer.hikari.HikariDataSource", "org.apache.commons.dbcp.BasicDataSource", "org.apache.commons.dbcp2.BasicDataSource" };
That is to say, these classes listed above must exist in the system.
So if you configure spring.datasource.* related information in application.properties and find that there is no datasource bean, it means that you can forget to add the above packages.
Although spring boot does a lot for us, it seems to be sneaky. If you don't understand the internal implementation, you may encounter situations that are sometimes effective and sometimes ineffective.
For peace of mind, you can also specify these configurations yourself.
@Configuration public class DbConfiguration implements TransactionManagementConfigurer { @Autowired private DataSourceProperties properties; @Bean public DataSource dataSource() { DataSourceBuilder factory = DataSourceBuilder .create(this.properties.getClassLoader()) .driverClassName(this.properties.getDriverClassName()) .url(this.properties.getUrl()).username(this.properties.getUsername()) .password(this.properties.getPassword()); if (this.properties.getType() != null) { factory.type(this.properties.getType()); } return factory.build(); } @Bean public PlatformTransactionManager txManager() { return new DataSourceTransactionManager(dataSource()); } @Override public PlatformTransactionManager annotationDrivenTransactionManager() { return txManager(); } }
The interface: TransactionManagementConfigurer is implemented here. When there are multiple transaction managers, the default transaction manager declared with annotations is specified here. For example, when Transactional is used, transactionManager is not specified.
application.properties
spring.datasource.username=username
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.type=org.apache.tomcat.jdbc.pool.DataSource
Of course, you can create DataSource directly instead of using DataSourceBuilder.