一、概念
Spring Boot的自动配置功能是通过条件注解实现的。这种方式可以根据一定的条件来判断是否需要自动配置某些组件,在程序启动时自动装配这些组件到Spring容器中。这样,我们在使用Spring Boot时,只需要添加相应的依赖,就可以直接使用这些组件了,无需手动配置。
具体来说,Spring Boot对于每个需要自动配置的组件会提供一个对应的 @Conditional 注解,用于判断条件是否成立。这些注解可以基于配置属性、类路径、其他Bean的存在和其他条件进行条件判断。
当条件成立时,Spring会使用指定的自动配置类进行自动配置。这些自动配置类包含了几乎所有常见组件的配置。
比如,当我们添加了Spring Boot的Web依赖(spring-boot-starter-web
)时,自动配置会检查类路径下是否存在org.springframework.web.servlet.DispatcherServlet
类。如果存在,就使用内置的Servlet容器(Tomcat、Jetty或Undertow)创建Web应用,并自动配置Servlet相关的组件(DispatcherServlet
、HandlerMapping
、ViewResolver
等等)。
通过这种方式,Spring Boot实现了自动装配的功能,简化了应用程序的开发配置,同时提供了许多可重用的、已经有了推荐的最佳实践的组件。
二、解析
Spring Boot的自动配置机制源码比较复杂,但是关键的部分还是比较容易理解的。我们来分析一下自动配置的源码实现。
首先是 @Conditional:Spring Boot中大量使用了这个注解,它的作用是根据某些条件决定是否执行某些Bean的创建和初始化操作。
@Target({ ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(Conditional.class)
public @interface Conditional {
Class<? extends Condition>[] value();
}
可以看到,@Conditional注解是可以重复的,也就是说可以同时使用多个条件进行判断。
Condition接口用于表示自定义的条件:
public interface Condition {
boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}
matches方法用于判断条件是否成立,返回值类型为布尔值。
然后是自动配置的实现,以MyBatis Starter为例:
在pom.xml中添加如下依赖:
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
使用mybatis-spring-boot-starter
依赖就可以自动配置MyBatis相关Bean。
在Spring Boot自动配置中,MybatisAutoConfiguration是用于自动配置Mybatis的核心类。它是一个@Configuration注解的类,用于定义Bean的创建和初始化过程。
@Configuration
@ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class })
@EnableConfigurationProperties(MybatisProperties.class)
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
public class MybatisAutoConfiguration {
// ...
}
其中,@ConditionalOnClass表示当classpath中存在指定的类时才进行自动配置;@EnableConfigurationProperties表示自动启用Spring的配置属性机制;@AutoConfigureAfter表示此配置类需要在哪些自动配置类完成后执行。
将具体的Mybatis配置细节从application.properties中分离出来:
mybatis.mapper-locations=classpath:mappers/*.xml
在MybatisAutoConfiguration类中,通过使用 @ConfigurationProperties(prefix = MybatisProperties.MYBATIS_PREFIX)
来绑定application.properties中的属性值:
@ConfigurationProperties(prefix = MybatisProperties.MYBATIS_PREFIX)
public class MybatisProperties {
public static final String MYBATIS_PREFIX = "mybatis";
// ...
private String mapperLocations;
// ...
}
然后,通过@Configuration注解的方法创建SqlSessionFactoryBean:
@Bean
@ConditionalOnMissingBean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
factory.setDataSource(dataSource);
Resource[] mapperLocations = resolver.getResources(properties.getMapperLocations());
factory.setMapperLocations(mapperLocations);
return factory.getObject();
}
这里的@ConditionalOnMissingBean注解表示当容器中不存在指定Bean时才去创建。
最后,通过 @MapperScan 注解自动扫描Mapper接口,使其成为Spring Bean:
@MapperScan(basePackages = "${mybatis.mapper-locations:}")
static class MybatisMapperScannerConfigurer {
// ...
}
整个自动配置的流程就是这样,通过条件注解、自动配置类、配置属性机制和相关的Bean的创建与初始化来实现。在Spring Boot中,各种自动配置机制相互配合,使开发者能够更加专注于业务逻辑的开发,提高了开发的效率和便利性。