目录
一、前言
SpringBoot将很多魔法带入Spring应用,其中最重要包含以下四个核心。
- 自动配置:针对很多Spring应用程序常见的应用功能,SpringBoot能自动提供相关的配置!《今天主要解析内容》
- 起步依赖:告诉SpringBoot需要什么功能,它就能引入需要的库。
二、起步依赖
向项目中添加依赖时间富有挑战的事。你需要什么库?他的Group和Artifact是什么?你需要哪个版本?哪个版本不会和项目中的其他依赖发生冲突?SpringBoot通过起步依赖为项目的依赖管理提供帮助,起步依赖其实就是特殊的Maven依赖,利用依赖传递解析,把常用库聚合在一起,组成了几个为特定功能而定制的依赖!
举个例子,假设你正在用Spring MVC构建一个RESR API,并将JSON作为资源表述。此外,你还想运用遵循JSR-303规范的声明式校验,并使用嵌入式的Tomcat服务器提供服务,实现以上目标,你在Maven中至少要依赖以下依赖:
- spring-core
- spring-web
- spring-webmvc
- jackson-databind等等
不过、如果打算利用SpringBoot的起步依赖,你只需要添加SpringBoot的WEB起步依赖(spring-boot-starter-web),仅此一个,它会根据依赖传递把其他所以需要的依赖传递到项目里,我们就不需要考虑细节依赖了!
比起减少依赖数量,起步依赖还引入了一些微妙的变化、项目中添加了web起步依赖,实际上指定了应用程序所需的一类功能,因为应用是个WEB应用程序,所有加入WEB的起步依赖,与之类似,如果应用程序要用到JPA持久化,那么就可以加入JPA起步依赖。如果需要安全功能,那就加入security起步依赖。简而言之,你不再需要考虑支持某种功能需要什么库了,引入相关的起步依赖就行。
此外,SpringBoot的起步依赖还把你从“需要哪些库、哪些版本”这个问题里解放出来,起步依赖引入的库和版本都是经过测试,因此你可以完全放心,他们之间不会存在不兼容的问题!
springboot的starters列表
三、自动配置
自动装配,SpringBoot的自动装配是一个运行时(更准确地说,是应用程序启动时)的过程。考虑了众多因素,才决定Spring配置应该用哪个,不加载哪个类的Bean!
举几个例子:
- Spring的JdbcTemplate是不是在Classpath里,如果是,并且有DataSource的bean,符合这俩条件则自动配置一个JdbcTemplate的bean
- Thymeleaf是不是在Clasapath里,如果是,则配置Thymeleaf的模版解析器、试图解析器以及模版引擎。
每当应用程序启动的时候,SpringBoot的自动装配都要做将近200次这样的决定,覆盖安全集成、持久化、Web开发等诸多方面。所有这些自动配置就是为了尽量不让开发者自己写配置~
他到底是如何做到自动加载配置呢?我们来解析以下,解读之前,我们需要了解Spring4条件加载特性!
1.Spring4条件化配置
SpringBoot之所以能够自动加载配置,Spring4更新的条件化配置决定性因素,我们先回顾下这个技术点再深入理解SpringBoot自动配置的实现原理!
在Spring4更新的条件化配置,可以让你通过判断条件,去决定是否加载和初始化一个类!我们要自定义条件其实很简单!
步骤1:实现Condition接口,覆盖它的matches()方法,matches()方法中自己编写条件控制返回boolean决定是否加载!
步骤2:声明类的时候使用对注解指向条件即可!(@Conditional(Condition实现类.class))
条件类代码:
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
/**
* projectName: JVM
*
* @author: 赵伟风
* time: 2021-02-04 00:51
* description:userservice加载条件类
*/
public class UserServiceConditional implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
try {
//判断是否有user类,决定返回值!
Class.forName("com.zwf.boot_auto_configure.bean.User");
return true;
} catch (ClassNotFoundException e) {
e.printStackTrace();
return false;
}
}
}
业务类代码:
import com.zwf.boot_auto_configure.conditional.UserServiceConditional;
import org.springframework.context.annotation.Conditional;
import org.springframework.stereotype.Service;
/**
* projectName: JVM
*
* @author: 赵伟风
* time: 2021-02-04 00:49
* description:
*/
@Service
@Conditional(UserServiceConditional.class) //加载判断条件,需要条件类matches返回值决定是否加载
public class UserService {
public String retMsg(){
return "service msg";
}
}
controller测试类代码:
import com.zwf.boot_auto_configure.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* projectName: JVM
*
* @author: 赵伟风
* time: 2021-02-04 00:49
* description: 测试获取业务类实体
*/
@RestController
public class UserController {
/**
* 自己创建和删除实体类,测试是否装配此实体,理解条件化加载!
*/
@Autowired
private UserService userService;
@GetMapping("/retmsg")
public String retMsg(){
return userService.retMsg();
}
}
通过控制UserServiceConditional判断条件返回值,可以动态控制是否配置UserService类!
其他条件化注解注解:
条件化注解 | 条件化注解 |
@ConditionalOnBean | 当存在某个类Bean生效 |
@ConditionalOnMissingBean | 当不存在某个类的Bean生效 |
@ConditionalOnClass | 当Classpath里有指定的类生效 |
@ConditionalOnMissingClass | 当Classpath里没有指定的类生效 |
@ConditionalOnMissingClass | 当指定java版本生效 |
@ConditionalOnProperty | 当指定配置属性要有一个明确的值 |
@ConditionalOnReource | 当指有某个配置资源的时候生效 |
@ConditionalOnWebApplication | 当是一个web应用的时候生效 |
@ConditionalOnNotWebApplication | @ConditionalOnNotWebApplication |
2、Springboot自动配置
自动配置就基于条件化配置,其实你可能理解了,springboot只不过是预先写好了配置类,在配置类加上各种条件,
例如需要jpa的bean,需要有数据库链接池才会加载!
只要倒入了对应的依赖,触发条件就会自动加载配置类!
在springboot中会依赖名为spring-boot-autoconfigure的jar,这里面有很多的配置类,每个配置类都在classpath里,只要符合条件就会自动加载!
举个例子:
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnBean({DataSource.class})
@ConditionalOnClass({JpaRepository.class})
@ConditionalOnMissingBean({JpaRepositoryFactoryBean.class, JpaRepositoryConfigExtension.class})
@ConditionalOnProperty(
prefix = "spring.data.jpa.repositories",
name = {"enabled"},
havingValue = "true",
matchIfMissing = true
)
@Import({JpaRepositoriesRegistrar.class})
@AutoConfigureAfter({HibernateJpaAutoConfiguration.class, TaskExecutionAutoConfiguration.class})
public class JpaRepositoriesAutoConfiguration {
//省略
}
我们随便找了其中一个配置类,他的加载,就有很多条件,
@ConditionalOnBean({DataSource.class})配置jpa就必须先要包含datasource连接池的Bean
@ConditionalOnClass({JpaRepository.class})必须存在这个JpaRepository.类!也就是说必须导入Jpa的依赖包等!
说到这里,你对自动配置有个初步了解了么?
欢迎在评论互动讨论,我在接下来的文章中分析,如何触发自动加载和加载的springboot配置读取过程!