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 </span>= "secondDatasource"<span style="color: #000000;">)</br>

@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 {

</span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">final</span> Log logger =<span style="color: #000000;"> LogFactory</br>
.getLog(DataSourceAutoConfiguration.</span><span style="color: #0000ff;">class</span><span style="color: #000000;">);</br>



@Bean

@ConditionalOnMissingBean

public DataSourceInitializer dataSourceInitializer(DataSourceProperties properties,

ApplicationContext applicationContext) {

return new DataSourceInitializer(properties, applicationContext);

}

</span><span style="color: #008000;">/**</span><span style="color: #008000;"></br>
* Determines if the {</span><span style="color: #808080;">@code</span><span style="color: #008000;"> dataSource} being used by Spring was created from</br>
* {</span><span style="color: #808080;">@link</span><span style="color: #008000;"> EmbeddedDataSourceConfiguration}.</br>
* </span><span style="color: #808080;">@param</span><span style="color: #008000;"> beanFactory the bean factory</br>
* </span><span style="color: #808080;">@return</span><span style="color: #008000;"> true if the data source was auto-configured.</br>
</span><span style="color: #008000;">*/</span></br>
<span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">boolean</span><span style="color: #000000;"> containsAutoConfiguredDataSource(</br>
ConfigurableListableBeanFactory beanFactory) {</br>
</span><span style="color: #0000ff;">try</span><span style="color: #000000;"> {</br>
BeanDefinition beanDefinition </span>= beanFactory.getBeanDefinition("dataSource"<span style="color: #000000;">);</br>
</span><span style="color: #0000ff;">return</span> EmbeddedDataSourceConfiguration.<span style="color: #0000ff;">class</span><span style="color: #000000;">.getName()</br>
.equals(beanDefinition.getFactoryBeanName());</br>
}</br>
</span><span style="color: #0000ff;">catch</span><span style="color: #000000;"> (NoSuchBeanDefinitionException ex) {</br>
</span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #000000;">;</br>
}</br>
}</br></br> @Conditional(EmbeddedDatabaseCondition.</span><span style="color: #0000ff;">class</span><span style="color: #000000;">)</br>
@ConditionalOnMissingBean({ DataSource.</span><span style="color: #0000ff;">class</span>, XADataSource.<span style="color: #0000ff;">class</span><span style="color: #000000;"> })</br>
@Import(EmbeddedDataSourceConfiguration.</span><span style="color: #0000ff;">class</span><span style="color: #000000;">)</br>
</span><span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">class</span><span style="color: #000000;"> EmbeddedDatabaseConfiguration {</br></br> }</br> @Configuration</br>
@Conditional(PooledDataSourceCondition.</span><span style="color: #0000ff;">class</span><span style="color: #000000;">)</br>
@ConditionalOnMissingBean({ DataSource.</span><span style="color: #0000ff;">class</span>, XADataSource.<span style="color: #0000ff;">class</span><span style="color: #000000;"> })</br>
@Import({ DataSourceConfiguration.Tomcat.</span><span style="color: #0000ff;">class</span>, DataSourceConfiguration.Hikari.<span style="color: #0000ff;">class</span><span style="color: #000000;">,</br>
DataSourceConfiguration.Dbcp2.</span><span style="color: #0000ff;">class</span>, DataSourceConfiguration.Generic.<span style="color: #0000ff;">class</span><span style="color: #000000;"> })</br>
</span><span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">class</span><span style="color: #000000;"> PooledDataSourceConfiguration {</br></br> }</br> @Configuration</br>
@ConditionalOnProperty(prefix </span>= "spring.datasource", name = "jmx-enabled"<span style="color: #000000;">)</br>
@ConditionalOnClass(name </span>= "org.apache.tomcat.jdbc.pool.DataSourceProxy"<span style="color: #000000;">)</br>
@Conditional(DataSourceAutoConfiguration.DataSourceAvailableCondition.</span><span style="color: #0000ff;">class</span><span style="color: #000000;">)</br>
@ConditionalOnMissingBean(name </span>= "dataSourceMBean"<span style="color: #000000;">)</br>
</span><span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">class</span><span style="color: #000000;"> TomcatDataSourceJmxConfiguration {</br>



@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;

}

}</br>

</span><span style="color: #008000;">/**</span><span style="color: #008000;"></br>
* {</span><span style="color: #808080;">@link</span><span style="color: #008000;"> AnyNestedCondition} that checks that either {</span><span style="color: #808080;">@code</span><span style="color: #008000;"> spring.datasource.type}</br>
* is set or {</span><span style="color: #808080;">@link</span><span style="color: #008000;"> PooledDataSourceAvailableCondition} applies.</br>
</span><span style="color: #008000;">*/</span></br>
<span style="color: #0000ff;">static</span> <span style="color: #0000ff;">class</span> PooledDataSourceCondition <span style="color: #0000ff;">extends</span><span style="color: #000000;"> AnyNestedCondition {





PooledDataSourceCondition() {


super(ConfigurationPhase.PARSE_CONFIGURATION);


}

    @ConditionalOnProperty(prefix </span>= "spring.datasource", name = "type"<span style="color: #000000;">)</br>
</span><span style="color: #0000ff;">static</span> <span style="color: #0000ff;">class</span><span style="color: #000000;"> ExplicitType {</br></br> }</br></br> @Conditional(PooledDataSourceAvailableCondition.</span><span style="color: #0000ff;">class</span><span style="color: #000000;">)</br>
</span><span style="color: #0000ff;">static</span> <span style="color: #0000ff;">class</span><span style="color: #000000;"> PooledDataSourceAvailable {</br></br> }</br></br> }</br></br></br> </span><span style="color: #008000;">/**</span><span style="color: #008000;"></br>
* {</span><span style="color: #808080;">@link</span><span style="color: #008000;"> Condition} to test if a supported connection pool is available.</br>
</span><span style="color: #008000;">*/</span></br>
<span style="color: #0000ff;">static</span> <span style="color: #0000ff;">class</span> PooledDataSourceAvailableCondition <span style="color: #0000ff;">extends</span><span style="color: #000000;"> SpringBootCondition {</br></br> @Override</br>
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> ConditionOutcome getMatchOutcome(ConditionContext context,</br>
AnnotatedTypeMetadata metadata) {</br>
ConditionMessage.Builder message </span>=<span style="color: #000000;"> ConditionMessage</br>
.forCondition(</span>"PooledDataSource"<span style="color: #000000;">);</br>
</span><span style="color: #0000ff;">if</span> (getDataSourceClassLoader(context) != <span style="color: #0000ff;">null</span><span style="color: #000000;">) {</br>
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> ConditionOutcome</br>
.match(message.foundExactly(</span>"supported DataSource"<span style="color: #000000;">));</br>
}</br>
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> ConditionOutcome</br>
.noMatch(message.didNotFind(</span>"supported DataSource"<span style="color: #000000;">).atAll());</br>
}</br> </span><span style="color: #008000;">/**</span><span style="color: #008000;"></br>
* Returns the class loader for the {</span><span style="color: #808080;">@link</span><span style="color: #008000;"> DataSource} class. Used to ensure that</br>
* the driver class can actually be loaded by the data source.</br>
* </span><span style="color: #808080;">@param</span><span style="color: #008000;"> context the condition context</br>
* </span><span style="color: #808080;">@return</span><span style="color: #008000;"> the class loader</br>
</span><span style="color: #008000;">*/</span></br>
<span style="color: #0000ff;">private</span><span style="color: #000000;"> ClassLoader getDataSourceClassLoader(ConditionContext context) {</br>
Class</span>&lt;?&gt; dataSourceClass = <span style="color: #0000ff;">new</span><span style="color: #000000;"> DataSourceBuilder(context.getClassLoader())
.findType();</br>
</span><span style="color: #0000ff;">return</span> (dataSourceClass == <span style="color: #0000ff;">null</span> ? <span style="color: #0000ff;">null</span><span style="color: #000000;"> : dataSourceClass.getClassLoader());</br>
}</br></br> }</br> </span><span style="color: #008000;">/**</span><span style="color: #008000;"></br>
* {</span><span style="color: #808080;">@link</span><span style="color: #008000;"> Condition} to detect when an embedded {</span><span style="color: #808080;">@link</span><span style="color: #008000;"> DataSource} type can be used.</br>
* If a pooled {</span><span style="color: #808080;">@link</span><span style="color: #008000;"> DataSource} is available, it will always be preferred to an</br>
* {</span><span style="color: #808080;">@code</span><span style="color: #008000;"> EmbeddedDatabase}.</br>
</span><span style="color: #008000;">*/</span></br>
<span style="color: #0000ff;">static</span> <span style="color: #0000ff;">class</span> EmbeddedDatabaseCondition <span style="color: #0000ff;">extends</span><span style="color: #000000;"> SpringBootCondition {</br></br> </span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">final</span> SpringBootCondition pooledCondition = <span style="color: #0000ff;">new</span><span style="color: #000000;"> PooledDataSourceCondition();</br></br> @Override</br>
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) {</br>
ConditionMessage.Builder message </span>=<span style="color: #000000;"> ConditionMessage</br>
.forCondition(</span>"EmbeddedDataSource"<span style="color: #000000;">);</br>
</span><span style="color: #0000ff;">if</span> (anyMatches(context, metadata, <span style="color: #0000ff;">this</span><span style="color: #000000;">.pooledCondition)) {</br>
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> ConditionOutcome</br>
.noMatch(message.foundExactly(</span>"supported pooled data source"<span style="color: #000000;">));</br>
}</br>
EmbeddedDatabaseType type </span>=<span style="color: #000000;"> EmbeddedDatabaseConnection</br>
.get(context.getClassLoader()).getType();</br>
</span><span style="color: #0000ff;">if</span> (type == <span style="color: #0000ff;">null</span><span style="color: #000000;">) {</br>
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> ConditionOutcome</br>
.noMatch(message.didNotFind(</span>"embedded database"<span style="color: #000000;">).atAll());</br>
}</br>
</span><span style="color: #0000ff;">return</span> ConditionOutcome.match(message.found("embedded database"<span style="color: #000000;">).items(type));</br>
}</br></br> }</br></br> </span><span style="color: #008000;">/**</span><span style="color: #008000;"></br>
* {</span><span style="color: #808080;">@link</span><span style="color: #008000;"> Condition} to detect when a {</span><span style="color: #808080;">@link</span><span style="color: #008000;"> DataSource} is available (either because
* the user provided one or because one will be auto-configured).</br>
</span><span style="color: #008000;">*/</span><span style="color: #000000;"></br>
@Order(Ordered.LOWEST_PRECEDENCE </span>- 10<span style="color: #000000;">)</br>
</span><span style="color: #0000ff;">static</span> <span style="color: #0000ff;">class</span> DataSourceAvailableCondition <span style="color: #0000ff;">extends</span><span style="color: #000000;"> SpringBootCondition {</br></br> </span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">final</span> SpringBootCondition pooledCondition = <span style="color: #0000ff;">new</span><span style="color: #000000;"> PooledDataSourceCondition();</br></br> </span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">final</span> SpringBootCondition embeddedCondition = <span style="color: #0000ff;">new</span><span style="color: #000000;"> EmbeddedDatabaseCondition();</br></br> @Override</br>
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> ConditionOutcome getMatchOutcome(ConditionContext context,</br>
AnnotatedTypeMetadata metadata) {</br>
ConditionMessage.Builder message </span>=<span style="color: #000000;"> ConditionMessage</br>
.forCondition(</span>"DataSourceAvailable"<span style="color: #000000;">);</br>
</span><span style="color: #0000ff;">if</span> (hasBean(context, DataSource.<span style="color: #0000ff;">class</span><span style="color: #000000;">)</br>
</span>|| hasBean(context, XADataSource.<span style="color: #0000ff;">class</span><span style="color: #000000;">)) {</br>
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> ConditionOutcome</br>
.match(message.foundExactly(</span>"existing data source bean"<span style="color: #000000;">));</br>
}</br>
</span><span style="color: #0000ff;">if</span> (anyMatches(context, metadata, <span style="color: #0000ff;">this</span><span style="color: #000000;">.pooledCondition,</br>
</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.embeddedCondition)) {</br>
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> ConditionOutcome.match(message</br>
.foundExactly(</span>"existing auto-configured data source bean"<span style="color: #000000;">));</br>
}</br>
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> ConditionOutcome</br>
.noMatch(message.didNotFind(</span>"any existing data source bean"<span style="color: #000000;">).atAll());</br>
}</br></br> </span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">boolean</span> hasBean(ConditionContext context, Class&lt;?&gt;<span style="color: #000000;"> type) {</br>
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> BeanFactoryUtils.beanNamesForTypeIncludingAncestors(</br>
context.getBeanFactory(), type, </span><span style="color: #0000ff;">true</span>, <span style="color: #0000ff;">false</span>).length &gt; 0<span style="color: #000000;">;</br>
}</br></br> }</br></br>

}

从上面看到,

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. 关于新手必须要理解的几个名词,cookie、session和token

    以下要说的,虽然不是开发过程中必须会遇到的,但却是进阶之路上必须要掌握的,一些涉及到状态管理与安全的应用当中尤为重要. 我之前虽略有学习,但也是东拼西凑临时看的一点皮毛,所以在这个假期利用一点时间,整 ...

  2. 上海第三产业增加值 占比GDP首破七成

    上海第三产业增加值 占比GDP首破七成 2016年08月16日08:10  来源:新闻晨报 分享到:     不久前结束的ChinaJoy上,一家名为HYPEREAL的VR公司展台前,体验者的热情程度 ...

  3. 微信小程序连续旋转动画this.animation.rotate

    一..js中封装旋转动画方法 添加animation属性 data:{ animation:''" } 改变animation的值(官网提供角度范围是-180~180,但是我发现角度越大会一 ...

  4. struts2的default.properties详解

    Struts 2框架有两个核心配置文件:struts.xml和struts.properties 其中struts.xml文件主要负责管理应用中的Action映射,以及该Action包含的Result ...

  5. Python使用微信接入图灵机器人

    1.wxpy库介绍 wxpy 在 itchat 的基础上,通过大量接口优化提升了模块的易用性,并进行丰富的功能扩展. 文档地址:https://wxpy.readthedocs.io 从 PYPI 官 ...

  6. 03_Spring Bean的装配模式_基于Annotation配置方式

    前言 在Spring中尽管使用XML配置文件可以实现Bean的装配工作,但如果应用中Bean的数量较多,会导致XML配置文件过于臃肿,从而给维护和升级带来一定的困难.从JDK 5开始提供了名为Anno ...

  7. vue 路由跳转记住滚动位置,返回时回到上次滚动位置

    参考:https://blog.csdn.net/qq_40204835/article/details/79853685 方法一: 利用Keep-Alive和监听器 1.首先在路由中引入需要的模块 ...

  8. Python学习之--python概要

    1 Python的优点 Python语言类库齐全,语法简洁,而且在linux上自带安装,在处理大数据以及自动化方面有其独有的特点.2 Python的解释器 Python解释器用来解释python代码, ...

  9. MapReduce深入理解输入和输出格式(2)-输入和输出完全总结

    MapReduce太高深,性能也值得考虑,大家感兴趣的还是看看spark比较好. FileInputFormat类 FileInputFormat是所有使用文件为数据源的InputFormat实现的基 ...

  10. 各ui库项目结构

    饿了么的ui组件库 sass build:webpack配置文件 examples: element api的页面文档 packages: 放置组件  css放在./theme-chalk 下 src ...