zoukankan      html  css  js  c++  java
  • spring boot自动配置之jdbc(转)

    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

  • 相关阅读:
    C++ 中复杂的声明
    指向成员的指针
    指针与引用的操作符
    char指针
    软件测试
    网络应用层协议
    BOOL,int,float,指针变量与零值比较的if语句
    有关单向链表的题目
    main方法执行之前,做什么事
    C++复制控制
  • 原文地址:https://www.cnblogs.com/jpfss/p/8422052.html
Copyright © 2011-2022 走看看