1.DataSource配置

1.1 默认配置application.xml

spring.datasource.url=jdbc:mysql://localhost/test
spring.datasource.username=root
spring.datasource.password=****
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.type=com.zaxxer.hikari.HikariDataSource

需要在pom.xml加入依赖(我使用了mybatis+mysql)

      <dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>${mybatis-spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>   

   <dependency>
    <groupId>com.zaxxer</groupId>
    <artifactId>HikariCP</artifactId>
    <exclusions>
      <exclusion>
        <artifactId>tools</artifactId>
        <groupId>com.sun</groupId>
      </exclusion>
    </exclusions>
  </dependency>

2.自定义DataSource

1.1 application.xml配置文件

spring:
application:
name: data-multidatasource
datasource:
type: com.zaxxer.hikari.HikariDataSource
url: jdbc:mysql://localhost:3306/test
username: sa
password: ****
second-datasource:
driver-class-name: org.hsqldb.jdbc.JDBCDriver
url: jdbc:hsqldb:mem:db2
username: sa
password:****

1.2 自定义DataSource配置

@Configuration
public class SencondDataSourceConfiguration {
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource newDataSource() {
return DataSourceBuilder.create().build();
} @Bean(name = "secondDatasource")
@ConfigurationProperties(prefix = "spring.second-datasource")
public DataSource secondDataSource() {
return DataSourceBuilder.create().build();
}
}

3.工作原理

spring boot的auto-configuration最具魔力的地方是@EnableAutoConfiguration注解

通常注解application应用使用@SpringBootApplication或者如下自定义的方式:

@Configuration

@EnableAutoConfiguration

@ComponentScan

public class Application

{

}

@EnableAutoConfiguration注解开启了spring ApplicationContext的自动配置功能,

它通过扫描classpath下的组件,满足不同Conditions的bean注册到容器中。

spring boot提供了不同的AutoConfiguration实现类,这些类都在spring-boot-autoconfigure-{version}.jar中,用来注册各种各样的组件。

通常,当AutoConfiguration实现类打上@Configuration标签,可以作为spring配置类,当AutoConfiguration实现类打上@EnableConfigurationProperties标签,可以绑定自定义属性或者更多Conditional bean注册方法。

下面就org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration来分析一下:

/**
* {@link EnableAutoConfiguration Auto-configuration} for {@link DataSource}.
*
* @author Dave Syer
* @author Phillip Webb
* @author Stephane Nicoll
* @author Kazuki Shimizu
*/
@Configuration
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({ Registrar.class, DataSourcePoolMetadataProvidersConfiguration.class })
public class DataSourceAutoConfiguration { private static final Log logger = LogFactory
.getLog(DataSourceAutoConfiguration.class); @Bean
@ConditionalOnMissingBean
public DataSourceInitializer dataSourceInitializer(DataSourceProperties properties,
ApplicationContext applicationContext) {
return new DataSourceInitializer(properties, applicationContext);
} /**
* Determines if the {@code dataSource} being used by Spring was created from
* {@link EmbeddedDataSourceConfiguration}.
* @param beanFactory the bean factory
* @return true if the data source was auto-configured.
*/
public static boolean containsAutoConfiguredDataSource(
ConfigurableListableBeanFactory beanFactory) {
try {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition("dataSource");
return EmbeddedDataSourceConfiguration.class.getName()
.equals(beanDefinition.getFactoryBeanName());
}
catch (NoSuchBeanDefinitionException ex) {
return false;
}
} @Conditional(EmbeddedDatabaseCondition.class)
@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
@Import(EmbeddedDataSourceConfiguration.class)
protected static class EmbeddedDatabaseConfiguration { } @Configuration
@Conditional(PooledDataSourceCondition.class)
@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
@Import({ DataSourceConfiguration.Tomcat.class, DataSourceConfiguration.Hikari.class,
DataSourceConfiguration.Dbcp2.class, DataSourceConfiguration.Generic.class })
protected static class PooledDataSourceConfiguration { } @Configuration
@ConditionalOnProperty(prefix = "spring.datasource", name = "jmx-enabled")
@ConditionalOnClass(name = "org.apache.tomcat.jdbc.pool.DataSourceProxy")
@Conditional(DataSourceAutoConfiguration.DataSourceAvailableCondition.class)
@ConditionalOnMissingBean(name = "dataSourceMBean")
protected static class TomcatDataSourceJmxConfiguration { @Bean
public Object dataSourceMBean(DataSource dataSource) {
if (dataSource instanceof DataSourceProxy) {
try {
return ((DataSourceProxy) dataSource).createPool().getJmxPool();
}
catch (SQLException ex) {
logger.warn("Cannot expose DataSource to JMX (could not connect)");
}
}
return null;
} } /**
* {@link AnyNestedCondition} that checks that either {@code spring.datasource.type}
* is set or {@link PooledDataSourceAvailableCondition} applies.
*/
static class PooledDataSourceCondition extends AnyNestedCondition { PooledDataSourceCondition() {
super(ConfigurationPhase.PARSE_CONFIGURATION);
} @ConditionalOnProperty(prefix = "spring.datasource", name = "type")
static class ExplicitType { } @Conditional(PooledDataSourceAvailableCondition.class)
static class PooledDataSourceAvailable { } } /**
* {@link Condition} to test if a supported connection pool is available.
*/
static class PooledDataSourceAvailableCondition extends SpringBootCondition { @Override
public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) {
ConditionMessage.Builder message = ConditionMessage
.forCondition("PooledDataSource");
if (getDataSourceClassLoader(context) != null) {
return ConditionOutcome
.match(message.foundExactly("supported DataSource"));
}
return ConditionOutcome
.noMatch(message.didNotFind("supported DataSource").atAll());
} /**
* Returns the class loader for the {@link DataSource} class. Used to ensure that
* the driver class can actually be loaded by the data source.
* @param context the condition context
* @return the class loader
*/
private ClassLoader getDataSourceClassLoader(ConditionContext context) {
Class<?> dataSourceClass = new DataSourceBuilder(context.getClassLoader())
.findType();
return (dataSourceClass == null ? null : dataSourceClass.getClassLoader());
} } /**
* {@link Condition} to detect when an embedded {@link DataSource} type can be used.
* If a pooled {@link DataSource} is available, it will always be preferred to an
* {@code EmbeddedDatabase}.
*/
static class EmbeddedDatabaseCondition extends SpringBootCondition { private final SpringBootCondition pooledCondition = new PooledDataSourceCondition(); @Override
public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) {
ConditionMessage.Builder message = ConditionMessage
.forCondition("EmbeddedDataSource");
if (anyMatches(context, metadata, this.pooledCondition)) {
return ConditionOutcome
.noMatch(message.foundExactly("supported pooled data source"));
}
EmbeddedDatabaseType type = EmbeddedDatabaseConnection
.get(context.getClassLoader()).getType();
if (type == null) {
return ConditionOutcome
.noMatch(message.didNotFind("embedded database").atAll());
}
return ConditionOutcome.match(message.found("embedded database").items(type));
} } /**
* {@link Condition} to detect when a {@link DataSource} is available (either because
* the user provided one or because one will be auto-configured).
*/
@Order(Ordered.LOWEST_PRECEDENCE - 10)
static class DataSourceAvailableCondition extends SpringBootCondition { private final SpringBootCondition pooledCondition = new PooledDataSourceCondition(); private final SpringBootCondition embeddedCondition = new EmbeddedDatabaseCondition(); @Override
public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) {
ConditionMessage.Builder message = ConditionMessage
.forCondition("DataSourceAvailable");
if (hasBean(context, DataSource.class)
|| hasBean(context, XADataSource.class)) {
return ConditionOutcome
.match(message.foundExactly("existing data source bean"));
}
if (anyMatches(context, metadata, this.pooledCondition,
this.embeddedCondition)) {
return ConditionOutcome.match(message
.foundExactly("existing auto-configured data source bean"));
}
return ConditionOutcome
.noMatch(message.didNotFind("any existing data source bean").atAll());
} private boolean hasBean(ConditionContext context, Class<?> type) {
return BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
context.getBeanFactory(), type, true, false).length > 0;
} } }

从上面看到,

1. DataSourceAutoConfiguration打上了@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })标签,这意味着只有当DataSource.class和EmbeddedDatabaseType.class出现在classpath时,DataSourceAutoConfiguration内的自动配置bean才可能被注册。

2. DataSourceAutoConfiguration打上了@EnableConfigurationProperties(DataSourceProperties.class)标签,意味着application.properties中的属性和DataSourceProperties类自动绑定了。

@ConfigurationProperties(prefix = DataSourceProperties.PREFIX)

public class DataSourceProperties implements BeanClassLoaderAware, EnvironmentAware, InitializingBean {

 public static final String PREFIX = "spring.datasource";

 ...

 ...

 private String driverClassName;

 private String url;

 private String username;

 private String password;

 ...

 //setters and getters

}

上面的配置类中说明,在application.properties中以spring.datasource开头的属性将自动绑定到DataSourceProperties对象上。其他注解,如@ConditionalOnMissingBean, @ConditionalOnClass and @ConditionalOnProperty等,标识只要条件满足,bean definition将注册到ApplicationContext中。

参考文件:

【1】http://www.liaoxuefeng.com/article/001484212576147b1f07dc0ab9147a1a97662a0bd270c20000

【2】https://dzone.com/articles/how-springboot-autoconfiguration-magic-works

spring boot自动配置之jdbc的更多相关文章

  1. spring boot自动配置之jdbc(转)

    1.DataSource配置 1.1 默认配置application.xml spring.datasource.url=jdbc:mysql://localhost/test spring.data ...

  2. Spring Boot自动配置与Spring 条件化配置

    SpringBoot自动配置 SpringBoot的自动配置是一个运行时(应用程序启动时)的过程,简化开发时间,无需浪费时间讨论具体的Spring配置,只需考虑如何利用SpringBoot的自动配置即 ...

  3. Spring Boot自动配置

    Spring Boot自动配置原理 Spring Boot的自动配置注解是@EnableAutoConfiguration, 从上面的@Import的类可以找到下面自动加载自动配置的映射. org.s ...

  4. Spring Boot自动配置原理(转)

    第3章 Spring Boot自动配置原理 3.1 SpringBoot的核心组件模块 首先,我们来简单统计一下SpringBoot核心工程的源码java文件数量: 我们cd到spring-boot- ...

  5. Spring Boot自动配置如何工作

    通过使用Mongo和MySQL DB实现的示例,深入了解Spring Boot的@Conditional注释世界. 在我以前的文章“为什么选择Spring Boot?”中,我们讨论了如何创建Sprin ...

  6. Springboot 系列(三)Spring Boot 自动配置原理

    注意:本 Spring Boot 系列文章基于 Spring Boot 版本 v2.1.1.RELEASE 进行学习分析,版本不同可能会有细微差别. 前言 关于配置文件可以配置的内容,在 Spring ...

  7. Spring Boot自动配置原理、实战

    Spring Boot自动配置原理 Spring Boot的自动配置注解是@EnableAutoConfiguration, 从上面的@Import的类可以找到下面自动加载自动配置的映射. org.s ...

  8. Spring boot 自动配置自定义配置文件

    示例如下: 1.   新建 Maven 项目 properties 2.   pom.xml <project xmlns="http://maven.apache.org/POM/4 ...

  9. Spring Boot自动配置原理与实践(一)

    前言 Spring Boot众所周知是为了简化Spring的配置,省去XML的复杂化配置(虽然Spring官方推荐也使用Java配置)采用Java+Annotation方式配置.如下几个问题是我刚开始 ...

随机推荐

  1. jms及active(jdk api)的实现

    在企业中,分布式的消息队列需要实现的问题: 1.不同的业务系统分别处理同一个消息(订阅发布),同一个业务系统负载处理同一类消息(队列模式) 2.消息的一致性问题,在互联网公司中一般不要求强一致性,一般 ...

  2. C++11新特性应用--实现延时求值(std::function和std::bind)

    说是延时求值,注意还是想搞一搞std::function和std::bind. 之前博客<C++11新特性之std::function>注意是std::function怎样实现回调函数. ...

  3. leveldb学习:sstable(2)

    block写入:block_builder block.h和.cc里定义了block的entry存储格式和restart,提供了entry的查找接口以及迭代器.那么怎样往写block里写entry呢? ...

  4. bzoj1830: [AHOI2008]Y型项链(LCP+贪心)

    1830: [AHOI2008]Y型项链 题目:传送门 简要题意: 给出三个字符串,可以对任意字符串进行操作,每次操作都可以再其中一个字符串的末尾删除或添加一个字符,求最小操作数使得所有的字符串相同 ...

  5. bzoj1082: [SCOI2005]栅栏(二分答案搜索判断)

    1082: [SCOI2005]栅栏 题目:传送门 题解: 是不是一开始在想DP?本蒟蒻也是qwq,结果很nice的错了ORZ 正解:二分+搜索 我们可以先把两种木材都进行排序,那么如果需要的最大木材 ...

  6. MongoDB 系列(一) C# 类似EF语法简单封装

    之前写过一篇关于MongoDB的封装 发现太过繁琐 于是打算从新写一篇简易版 1:关于MongoDB的安装请自行百度,进行权限认证的时候有一个小坑,3.0之后授权认证方式默认的SCRAM-SHA-1模 ...

  7. shiro什么时候会进入doGetAuthorizationInfo(PrincipalCollection principals)

    shiro会进入授权方法一共有三种情况!(注解.标签.代码) 1.subject.hasRole(“admin”) 或 subject.isPermitted(“admin”):自己去调用这个是否有什 ...

  8. Android 广播大全 Intent Action 事件详解

    Android 广播大全 Intent Action 事件详解 投稿:mrr 字体:[增加 减小] 类型:转载 时间:2015-10-20我要评论 这篇文章主要给大家介绍Android 广播大全 In ...

  9. c#.net 获取时间日期年月日时分秒生成自动文件名格式

    下面是日期和时间的各种方法,转换为字符串. 如果把输出的格式改下就可以做类似的文件名了,例如:2016010110101224356.doc  c#用DateTime.Now.ToString(&qu ...

  10. CF 286(div 2) B Mr. Kitayuta's Colorful Graph【传递闭包】

    解题思路:给出n个点,m条边(即题目中所说的两点之间相连的颜色) 询问任意两点之间由多少种不同的颜色连接 最开始想的时候可以用传递闭包或者并查集来做,可是并查集现在还不会做,就说下用传递闭包来做的这种 ...