什么是Spring boot
before
依靠Spring 配置文件xml,例如applicationContext.xml,配置不同的bean,交给Spring管理。
after
充分实践“约定大于配置”的思想。
- maven的目录结构(默认以jar的方式打包/包括resources文件夹,static和templates)
- spring-boot-starter-web,内置tomcat
- 默认application.properties
Spring boot 特色
- AutoConfiguration基于注解的自动装配
- starter
- Actuator
- Springboot CLI
jdk5 提供了javaConfig的支持即注解 ,spring3 与时俱进开始支持xml与注解两种方式。
@Configuration
public class ConfigurationDemo {
/**
* 基于注解被spring托管
* @return
*/
@Bean
public DemoClass getDemoClass() {
return new DemoClass();
}
}
@ComponentScan
默认扫描当前类所在目录下的所有class文件。basePackages 可指定扫描的目录。
@EnableAutoConfiguration
@AutoConfigurationPackage + @Import
Spring 3.1 enable
根据上下文激活不同的bean,动态注入bean。
- ImportSelector
- 定义AppleImportSelector 实现 org.springframework.context.annotation.ImportSelector 接口
- 重写#selectImports,选择import到IOC容器中的class全路径名称
- 定义接口
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AppleImportSelector.class, CarDefinitionRegistrar.class})
public @interface EnableAppleService {
/**
* 自定义基于注解的判断逻辑
*/
Class<?>[] exclude() default {};
}
- 在启动类中添加自定义注解,完成class的自动注入
- ImportBeanDefinitionRegistrar
同上面接口一样,实现接口后,在#registerBeanDefinitions中自定义注册到IOC容器的bean。
继续看@SpringBootApplication,由下面三个注解复合组成。
@SpringBootConfiguration ≈ @Configuration
@EnableAutoConfiguration ≈ @AutoConfigurationPackage + @Import(AutoConfigurationImportSelector.class)
@ComponentScan
@AutoConfigurationPackage = @Import(AutoConfigurationPackages.Registrar.class)
所以下面再看AutoConfigurationPackages.Registrar.class
#selectImports -> #loadMetadata -> #getAutoConfigurationEntry -> #getCandidateConfigurations ……
通过spi加载配置文件中的数据,删除重复项,删除exclusions,顾虑autoConfigurationMetadata,返回需要注入到class文件名称数组。
简单理解如下:你想通过XML配置化管理某一类文件,但是一股脑儿全部加在到容器中又有点多余,因为某些类缺少依赖运行不起来,加进去白占地方,徒添隐患;然后你又搞了个配置文件管理这些依赖逻辑(元数据);(starter中的)这两个文件在IOC启动时候被扫描加载处理,完成IOC初始化操作,这就是下面的SPI机制。
SPI
Service Provider Interface,是一种服务发现机制。Spring启动时候以Properties加载META-INF/spring.factories,遍历内容,返回Map集合。根据factoryTypeName返回对应的list数据。
为什么会有SPI?因为Java是编译性语言,class文件不方便修改,所以为了提供接口配置化管理选择了配置文件这种走后门的方式。总体上还是约定大于配置的体现:计算机只会按照既定方案执行命令,不会像人类一样自我识别;你这么定义数据,我就能正常加载你。
/**
* factoryType = EnableAutoConfiguration.class
*/
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
String factoryTypeName = factoryType.getName();
return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
}
参考一下spring-boot 相关starter的spi文件内容
快克版 SPI
-
在resources目录下创建META-INF/spring.factories,
-
编辑内容
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.hzb.code.springbootfirst.kuaike.KuaikeService
-
context.getBean(KuaikeService.class)成功获取到bean。
ConditionalOnClass ConditionOnBean
Spring boot中基于注解上的if-else判断。下面两种方式,一样的结果,都是当classpath下存在CodeService时候,才会加载KuaikeService到IOC容器中(没有感冒就没有快克- -)。
全都是基于Spring 4.0 @Conditional 的扩展注解。
岗位名称:Java开发工程师
岗位薪资: 20k-40k
工作地址:北京大兴区
职位描述:
负责京东物流服务+相关业务需求分析,系统设计,具体开发,系统部署等。任职要求:
1.统招本科及以上学历,计算机相关专业,5-10年以上相关工作经验,平均每段工作经验2年以上;
2.对当前主流框架有丰富的使用经验和并对原理有较深的理解;
3.具有丰富的海量数据场景相关的开发经验;
4.具有一定的大型项目实战经验,能够推进项目正常发展及识别过程风险
有意者联系我 727513648@qq.com