前言
大家应该都有所了解,随着Ruby、Groovy等动态语言的流行,相比较之下Java的开发显得格外笨重。繁多的配置、低下的开发效率、复杂的部署流程以及第三方技术集成难度大等问题一直被人们所诟病。随着Spring家族中的新星Spring Boot的诞生,这些问题都在逐渐被解决。
个人觉得Spring Boot中最重要的两个优势就是可以使用starter简化依赖配置和Spring的自动配置。下面这篇文章将给大家详细介绍Spring Boot自动配置的相关内容,话不多说,来一起看看详细的介绍。
使用starter简化依赖配置
Spring提供了一系列starter来简化Maven配置。其核心原理也就是Maven和Gradle的依赖传递方案。当我们在我们的pom文件中增加对某个starter的依赖时,该starter的依赖也会自动的传递性被依赖进来。而且,很多starter也依赖了其他的starter。例如web starter就依赖了tomcat starter,并且大多数starter基本都依赖了spring-boot-starter。
Spring自动配置
Spring Boot会根据类路径中的jar包、类,为jar包里的类自动配置,这样可以极大的减少配置的数量。简单点说就是它会根据定义在classpath下的类,自动的给你生成一些Bean,并加载到Spring的Context中。自动配置充分的利用了spring 4.0的条件化配置特性,能够自动配置特定的Spring bean,用来启动某项特性。
条件化配置
假设你希望一个或多个bean只有在某种特殊的情况下才需要被创建,比如,一个应用同时服务于中美用户,要在中美部署,有的服务在美国集群中需要提供,在中国集群中就不需要提供。在Spring 4之前,要实现这种级别的条件化配置是比较复杂的,但是,Spring 4引入了一个新的@Conditional注解可以有效的解决这类问题。
@Bean @Conditional(ChinaEnvironmentCondition.class) public ServiceBean serviceBean(){ return new ServiceBean(); }
当@Conditional(ChinaEnvironmentCondition.class)条件的值为true的时候,该ServiceBean才会被创建,否则该bean就会被忽略。
@Conditional指定了一个条件。他的条件的实现是一个Java类——ChinaEnvironmentCondition,要实现以上功能就要定义ChinaEnvironmentCondition类,并继承Condition接口并重写其中的matches方法。
class ChinaEnvironmentCondition implements Condition{ public final boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { Environment env = context.getEnvironment(); return env.containProperty("ENV_CN"); } }
在上面的代码中,matches方法的内容比较简单,他通过给定的ConditionContext对象进而获取Environment对象,然后使用该对象检查环境中是否存在ENV_CN属性。如果存在该方法则直接返回true,反之返回false。当该方法返回true的时候,就符合了@Conditional指定的条件,那么ServiceBean就会被创建。反之,如果环境中没有这个属性,那么这个ServiceBean就不会被创建。
除了可以自定义一些条件之外,Spring 4本身提供了很多已有的条件供直接使用,如:
@ConditionalOnBean @ConditionalOnClass @ConditionalOnExpression @ConditionalOnMissingBean @ConditionalOnMissingClass @ConditionalOnNotWebApplication
Spring Boot应用的启动入口
自动配置充分的利用了spring 4.0的条件化配置特性,那么,Spring Boot是如何实现自动配置的?Spring 4中的条件化配置又是怎么运用到Spring Boot中的呢?这要从Spring Boot的启动类说起。Spring Boot应用通常有一个名为*Application的入口类,入口类中有一个main方法,这个方法其实就是一个标准的Java应用的入口方法。一般在main方法中使用SpringApplication.run()来启动整个应用。值得注意的是,这个入口类要使用@SpringBootApplication注解声明。@SpringBootApplication是Spring Boot的核心注解,他是一个组合注解。
@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 { // 略 }
@SpringBootApplication是一个组合注解,它主要包含@SpringBootConfiguration、@EnableAutoConfiguration等几个注解。也就是说可以直接在启动类中使用这些注解来代替@ SpringBootApplication注解。 关于Spring Boot中的Spring自动化配置主要是@EnableAutoConfiguration的功劳。该注解可以让Spring Boot根据类路径中的jar包依赖为当前项目进行自动配置。
至此,我们知道,Spring Boot的自动化配置主要是通过@EnableAutoConfiguration来实现的,因为我们在程序的启动入口使用了@SpringBootApplication注解,而该注解中组合了@EnableAutoConfiguration注解。所以,在启动类上使用@EnableAutoConfiguration注解,就会开启自动配置。
那么,本着刨根问底的原则,当然要知道@EnableAutoConfiguration又是如何实现自动化配置的,因为目前为止,我们还没有发现Spring 4中条件化配置的影子。
EnableAutoConfiguration
其实Spring框架本身也提供了几个名字为@Enable开头的Annotation定义。比如@EnableScheduling、@EnableCaching、@EnableMBeanExport等,@EnableAutoConfiguration的理念和这些注解其实是一脉相承的。
下面是EnableAutoConfiguration注解的源码:
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import({EnableAutoConfigurationImportSelector.class}) public @interface EnableAutoConfiguration { //略 }
观察@EnableAutoConfiguration可以发现,这里Import了@EnableAutoConfigurationImportSelector,这就是Spring Boot自动化配置的“始作俑者”。
至此,我们知道,至此,我们知道,由于我们在Spring Boot的启动类上使用了@SpringBootApplication注解,而该注解组合了@EnableAutoConfiguration注解,@EnableAutoConfiguration是自动化配置的“始作俑者”,而@EnableAutoConfiguration中Import了@EnableAutoConfigurationImportSelector注解,该注解的内部实现已经很接近我们要找的“真相”了。
EnableAutoConfigurationImportSelector
EnableAutoConfigurationImportSelector的源码在这里就不贴了,感兴趣的可以直接去看一下,其实实现也比较简单,主要就是使用Spring 4 提供的的SpringFactoriesLoader工具类。通过SpringFactoriesLoader.loadFactoryNames()读取了ClassPath下面的META-INF/spring.factories文件。
这里要简单提一下spring.factories文件,它是一个典型的java properties文件,配置的格式为Key = Value形式。
EnableAutoConfigurationImportSelector通过读取spring.factories中的key为org.springframework.boot.autoconfigure.EnableAutoConfiguration的值。如spring-boot-autoconfigure-1.5.1.RELEASE.jar中的spring.factories文件包含以下内容:
# Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\ org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\ org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\ org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\ org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\ org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\ org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\ ...... org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration
上面的EnableAutoConfiguration配置了多个类,这些都是Spring Boot中的自动配置相关类;在启动过程中会解析对应类配置信息。每个Configuation都定义了相关bean的实例化配置。都说明了哪些bean可以被自动配置,什么条件下可以自动配置,并把这些bean实例化出来。
如果我们新定义了一个starter的话,也要在该starter的jar包中提供 spring.factories文件,并且为其配置org.springframework.boot.autoconfigure.EnableAutoConfiguration对应的配置类。
Configuation
我们从spring-boot-autoconfigure-1.5.1.RELEASE.jar中的spring.factories文件随便找一个Configuration,看看他是如何自动加载bean的。
@Configuration @AutoConfigureAfter({JmxAutoConfiguration.class}) @ConditionalOnProperty( prefix = "spring.application.admin", value = {"enabled"}, havingValue = "true", matchIfMissing = false ) public class SpringApplicationAdminJmxAutoConfiguration { @Bean @ConditionalOnMissingBean public SpringApplicationAdminMXBeanRegistrar springApplicationAdminRegistrar() throws MalformedObjectNameException { String jmxName = this.environment.getProperty("spring.application.admin.jmx-name", "org.springframework.boot:type=Admin,name=SpringApplication"); if(this.mbeanExporter != null) { this.mbeanExporter.addExcludedBean(jmxName); } return new SpringApplicationAdminMXBeanRegistrar(jmxName); } }
看到上面的代码,终于找到了我们要找的东西——Spring 4的条件化配置。上面SpringApplicationAdminJmxAutoConfiguration在决定对哪些bean进行自动化配置的时候,使用了两个条件注解:ConditionalOnProperty和ConditionalOnMissingBean。只有满足这种条件的时候,对应的bean才会被创建。这样做的好处是什么?这样可以保证某些bean在没满足特定条件的情况下就可以不必初始化,避免在bean初始化过程中由于条件不足,导致应用启动失败。
总结
至此,我们可以总结一下Spring Boot的自动化配置的实现:
通过Spring 4的条件配置决定哪些bean可以被配置,将这些条件定义成具体的Configuation,然后将这些Configuation配置到spring.factories文件中,作为key: org.springframework.boot.autoconfigure.EnableAutoConfiguration的值,这时候,容器在启动的时候,由于使用了EnableAutoConfiguration注解,该注解Import的EnableAutoConfigurationImportSelector会去扫描classpath下的所有spring.factories文件,然后进行bean的自动化配置。
所以,如果我们想要自定义一个starter的话,可以通过以上方式将自定义的starter中的bean自动化配置到Spring的上下文中,从而避免大量的配置。
好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对小牛知识库的支持
本文向大家介绍apollo与springboot集成实现动态刷新配置的教程详解,包括了apollo与springboot集成实现动态刷新配置的教程详解的使用技巧和注意事项,需要的朋友参考一下 分布式apollo简介 Apollo(阿波罗)是携程框架部门研发的开源配置管理中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性。 本文主要介
4.1 根据条件的自动配置 @conditional是基于条件的自动配置,一般配合Condition接口一起使用,只有接口实现类返回true,才装配,否则不装配. 用实现了Condition接口的类传入@Conditional中 @Conditional可以标记在配置类的方法中,也可以标记在配置类上.标记的位置不同,作用域不同. @Conditional可以传入多个实现了condition接口的类
触发器介绍 我们打开应用的引擎模块,默认就进入到了触发器模块,在这个页面我们可以很方便进行的查询、编辑,禁用等操作。 触发器相关文档请移步这里 触发类型:数据表 下面我们先以数据表作为触发条件,方便大家实操。 邮件模板 准备工作 我们先在数据页面,创建一个product表,然后添加如下一个字段: 字段名称 类型 name string 创建触发器 我们新建一个触发类型为数据表的触发器,条件卡片的配
本文向大家介绍SpringBoot自动装配原理详解,包括了SpringBoot自动装配原理详解的使用技巧和注意事项,需要的朋友参考一下 首先对于一个SpringBoot工程来说,最明显的标志的就是 @SpringBootApplication它标记了这是一个SpringBoot工程,所以今天的 SpringBoot自动装配原理也就是从它开始说起。 自动装配流程 首先我们来看下@SpringBoot
本文向大家介绍springboot 多环境配置教程,包括了springboot 多环境配置教程的使用技巧和注意事项,需要的朋友参考一下 在上一课中我们通过idea工具没有做任何配置就构建了一个springboot项目,并且已经成功启动了,但我们都很清楚这些都远远不能达到我们实际项目的需求,比如我们要引入我们自己的redis配置、mysql配置等,应该如何处理呢?在spring mvc中我们都是通过
本文向大家介绍Spring实战之XML与JavaConfig的混合配置详解,包括了Spring实战之XML与JavaConfig的混合配置详解的使用技巧和注意事项,需要的朋友参考一下 前言 之前提到了关于Spring的显示配置方式有两种,一种是基于XML配置,一种是基于JavaConfig的方式配置。对于这两种配置方式并不是互斥关系,相反,他们两能够相互融合,有效的搭配完成Spring的bean注