新建的项目结构如下图:
1.POM 文件
项目会默认依赖 spring-boot-starter-parent 项目
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent>
这个parent项目又依赖下面
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.0.4.RELEASE</version> <relativePath>../../spring-boot-dependencies</relativePath> </parent>
spring-boot-dependencies 这个依赖里面定义spring boot 真正依赖的jar包和适配的版本号,所以后面的依赖就不用定义版本号,spring boot 已经自动适配了合适的版本。
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
同时还依赖了spring-boot-starter-*,spring boot 官方文档 https://docs.spring.io/spring-boot/docs/2.0.4.RELEASE/reference/htmlsingle/#using-boot-dependency-management ,13.5 章节介绍了这些Satrter ,根据文档,这些starter 是spring boot 根据实际应用场景封装的一系列场景启动器,可以为我们提供相应场景的一站式服务,比如我们需要data-jpa支持,我们只要导入spring-boot-starter-data-jpa 这个启动器即可,spring boot 会导入相应jar包,并自动配置相应的场景。
pom文件中同时还有关于 Spring Boot Maven 插件,它可以将项目打成单独的jar包,通过java -jar 命令已独立的应用形式来运行。
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
2.启动类
项目类路径下有一个名称为***Application 的类
@SpringBootApplication public class SpringbootAutoconfigApplication { public static void main(String[] args) { SpringApplication.run(SpringbootAutoconfigApplication.class, args); } }
@SpringBootApplication 这个注解的意思是:将当前类标志为主程序类,程序的运行入口为这个类。这个注解是多个注解的组合
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) public @interface SpringBootApplication {
其中最重要的@EnableAutoConfiguration这个注解的意思是:开启spring boot 自动配置功能,然后通过AutoConfigurationImportSelector 来选择应该自动将哪些自动配置导入到容器中,要导入的自动配置组件都在META-INF/spring-autoconfigure-metadata.properties这个配置文件中有相应配置。在spring-boot-autoconfigure-2.0.4.RELEASE.jar 里面有所有Starter自动配置,在相应的自动配置类里面可以看到配置的生效条件,和我们可以自己配哪些属性。以dao的自动配置为例
@ConditionalOnClass(PersistenceExceptionTranslationPostProcessor.class) public class PersistenceExceptionTranslationAutoConfiguration { @Bean @ConditionalOnMissingBean @ConditionalOnProperty(prefix = "spring.dao.exceptiontranslation", name = "enabled", matchIfMissing = true) public static PersistenceExceptionTranslationPostProcessor persistenceExceptionTranslationPostProcessor( Environment environment) { PersistenceExceptionTranslationPostProcessor postProcessor = new PersistenceExceptionTranslationPostProcessor(); boolean proxyTargetClass = environment.getProperty( "spring.aop.proxy-target-class", Boolean.class, Boolean.TRUE); postProcessor.setProxyTargetClass(proxyTargetClass); return postProcessor; } }
@ConditionalOnClass 类路径下有 PersistenceExceptionTranslationPostProcessor的class时生效
@ConditionalOnMissingBean 意思是没有这个组件的时候生效,我们可以配置的内容是 spring.dao.exceptiontranslation,没有配置的情况下的默认值是true。
官方文档的15至16介绍了关于自动配置的其他内容。我们可以自己编写自定义的配置和禁用部分自动配置。如何编写自己的自动以类呢?
官方文档是这么说的,我们可以不用将所有 的配置放在,我们只需要自己编写配置类,并让它加载进容器中就可以了。比如
@Configuration @EnableAutoConfiguration @Import({ MyConfig.class, MyAnotherConfig.class })
//@ComponentScan(basePackages={"xx.xx.xx.MyConfig,xx.xx.xx.MyAnotherConfig"}) public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
或者 在Application 中已@Bean的注解来创建一个组件,并将组件加入到容器中
@Import注解的意思是将类作为组件加载到容器中
@ComponentScan 注解的意思的将路径的中的类作为组件天剑到容器中。由于Application 默认扫描的是当前所在目录及其下级目录的组件,所以一般情况下不需要声明扫包的路径,但是如有其它第三方的的包可以用这种方式将组件添加到容器中。
如何禁用自动配置呢?官方文档的16.2章节有 说明。比如下面:
import org.springframework.boot.autoconfigure.*; import org.springframework.boot.autoconfigure.jdbc.*; import org.springframework.context.annotation.*; @Configuration @EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class}) public class MyConfiguration { }
自定义一个Configuration,通过exclude排除不需要自动配置的组件。然后再主程序中将这个配置类添加到容器中即可。
关于这条件注解分为以下几类:
注解 | 处理类 | 处理逻辑 | 实例 |
---|---|---|---|
@Conditional | OnBeanCondition | 当给定的类型、类名、注解、昵称在beanFactory中存在时返回true.各类型间是or的关系 | @ConditionalOnBean (CacheManager.class) |
@ConditionalOnSingleCandidate | OnBeanCondition | 当给定类型的bean存在并且指定为Primary的给定类型存在时,返回true | @ConditionalOnSingleCandidate (DataSource.class) |
@ConditionalOnMissingBean | OnBeanCondition | 当给定的类型、类名、注解、昵称在beanFactory中不存在时返回true.各类型间是or的关系 | @ConditionalOnMissingBean |
@ConditionalOnClass | OnClassCondition | 当给定的类型、类名在类路径上存在时返回true,各类型间是and的关系 | @ConditionalOnClass({ EnableAspectJAutoProxy.class, Aspect.class, Advice.class }) |
@ ConditionalOnMissingClass | OnClassCondition | 当给定的类名在类路径上不存在时返回true,各类型间是and的关系 | @ConditionalOnMissingClass(“org.thymeleaf.templatemode.TemplateMode”) |
@ConditionalOnCloudPlatform | OnCloudPlatformCondition | 当所配置的CloudPlatform为激活时返回true | @ConditionalOnCloudPlatform(CloudPlatform.CLOUD_FOUNDRY) |
@ConditionalOnExpression | OnExpressionCondition | 如果该表达式返回true则代表匹配,否则返回不匹配 | @ConditionalOnExpression(“true”) |
@ConditionalOnJava | OnJavaCondition | 运行时的java版本号是否包含给定的版本号.如果包含,返回匹配,否则,返回不匹配 | @ConditionalOnJava(ConditionalOnJava.JavaVersion.EIGHT) |
@ConditionalOnJndi | OnJndiCondition | 给定的jndi的Location 必须存在一个.否则,返回不匹配 | @ConditionalOnJndi({ “java:comp/TransactionManager”}) |
@ConditionalOnNotWebApplication | OnWebApplicationCondition | 不在web环境时返回匹配 | @ConditionalOnNotWebApplication |
@ConditionalOnWebApplication | OnWebApplicationCondition | 不在web环境时返回匹配 | @ConditionalOnWebApplication |
@ConditionalOnProperty | OnPropertyCondition | 配置的属性存在时匹配 | @ConditionalOnProperty(prefix = “spring.aop”, name = “auto”, havingValue = “true”, matchIfMissing = true) |
@ConditionalOnResource | OnResourceCondition | 指定的资源必须存在,否则返回不匹配 | @ConditionalOnResource(resources = “classpath:META-INF/build-info.properties”) |