《SpringBoot实战》读书笔记之自动配置原理

在向应用程序加入Spring Boot时,有个名为spring-boot-autoconfigure的JAR文件,其中包含了很多配置类。每个配置类都在应用程序的Classpath里,都有机会为应用程序的配置添砖加瓦。这些配置类里有用于Thymeleaf的配置,有用于Spring Data JPA的配置,有用于SpringMVC的配置,还有很多其他东西的配置,你可以自己选择是否在Spring应用程序中使用它们。

所有这些配置如此与众不同,原因在于它们利用了Spring的条件化配置,这是Spring4.0引入的新特性。条件化配置允许配置存在于应用程序中,但在满足某些特定条件之前都忽略这个配置。

在Spring里可以很方便地编写你自己的条件,你所要做的就是实现condition接口,覆盖它的matches()方法。举例来说,下面这个简单的条件类只有在Classpath里存在JdbcTemplate时才会生效:

package readinglist;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class JdbcTemplateCondition implements Condition
{
    @Override
    public boolean matches(ConditionContext context,AnnotatedTypeMetadata metadata)
    {
        try
        {
        context.getClassLoader().loadClass("org.springframework.jdbc.core.JdbcTemplate");
        return true;
        }
        catch(Exception e)
        {
            return false;
        }
    }
}

当你用Java来声明Bean的时候,可以使用这个自定义条件类:

@Conditional(JdbcTemplateCondition.class)
public MyService()
{
....
}

在例子中,只有当JdbcTemplateConditin类的条件成立时才会创建MyService这个Bean。也就是说MyService Bean 创建的条件是Classpath里有JdbcTemplate。否则,这个Bean的声明就会忽略掉。

在Spring Boot中定义了很多更有趣的条件,并把它们运用到了配置类上,这些配置类构成了Spring Boot的自动配置。Spring Boot 运用条件化配置的方法,定义多个特殊的条件化注解,并将他们用到配置类上。下面是Spring Boot自动配置中使用的条件化注解:

条件化注解配置生效条件
@ConditionalOnBean配置了某个特定Bean
@ConditionalOnMissingBean没有配置特定的Bean
@ConditionalOnClassClasspath里有指定的类
@ConditionalOnMissingClassClasspath里没有指定的类
@ConditionalOnExpression给定的Spring Expression Language表达式计算结果为true
@ConditionalOnJavaJava的版本匹配特定值或者一个范围
@ConditionalOnJndi参数中给定的JNDI位置必须存在一个
@ConditionalOnProperty指定的就配置属性要有一个明确的值
@ConditionalOnResourceClasspath里有指定的资源
@ConditionalOnWebApplication这是个Web应用程序
@ConditionalOnNotWebApplication这不是个Web应用程序

 

 

 

 

 

 

 

 

 

 

 

 

 

一般来说,无需查看Spring Boot自动配置类的源代码,但为了查看其自动配置的内核原理,我们可以看一下DataSourceAutoConfiguration里的这个片段(这是Spring Boot自动配置库的一部分)

@configuration
@conditionalonClass({DataSource.class,EmbeddedDatabaseType.class})
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({Reigstrar.class,DataSourcePoolMetadataProvidersConfiguration.class})
public class DataSourceAutoConfiguration{
....
}

在上述代码中,DataSourceAutoConfiguration添加了@Configuration注解,它从其他配置类中导入了一些额外的配置,还定义了一些Bean。最重要的是,DataSourceAutoConfiguration上添加了@ConditionalOnClass注解,要求Classpath里必须要有DataSource和EmbeddedDatabaseType。如果他们不存在,条件就不成立,DataSourceAutoConfiguration提供的配置都会被忽略。

DataSourceAutoConfiguration里嵌入了一个JdbcTemplateConfiguration类,自动配置了一个JdbcTemplate Bean;

@Configuration
@Conditional(DataSourceAutoConfiguration.DataSourceAvailableCondition.class)
protected static class JdbcTemplateConfiguration
{
    @Autowired(required=false)
    private DataSource dataSource;

    @Bean
    @ConditionalOnMissingBean(JdbcOperations.class)
    public JdbcTemplate jdbcTempalte()
    {
        return new JdbcTemplate(this.dataSource);
    }
...
}

自动配置会做出以下配置决策,比如:

  1. 因为Classpath里有H2,所以会创建一个嵌入式的H2数据库Bean,它的类型是javax.sql.DataSource,JPA实现(Hibernate)需要它来访问数据库。
  2. 因为Classpath里有Hibernate(Spring Data JPA传递引入的)的实体管理器,所以自动配置会配置与Hibernate相关的Bean,包括Spring 的LocalContainerEntityMangerFactoryBean和JpaVendorAdapter。
  3. 因为Classpath里有Spring Data JPA,所以它会自动配置为根据仓库的接口差U年间仓库实现。
  4. 因为Classpath里有Thymeleaf,所以Thymeleaf会配置为Spring MVC的视图,包括一个Thymeleaf的模板解析器、模板引擎及视图解析器。试图解析器会解析相对于Classpath根目录/templates目录里的模板。
  5. 因为Classpath里有Spring MVC,所以会配置Spring的DispatcherServlet并启动SpringMVC。
  6. 因为这是一个SpringMVCWeb应用程序,所以会注册一个资源处理器,把相对于Classpath根目录/static里的静态内容提供出来
  7. 因为Classpath里有Tomcat,所以会启动一个嵌入式的Tomcat容器,监听8080端口。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值