一.概述
Spring Boot 之所以能大幅简化 Spring 开发,核心在于其 **“约定优于配置”** 的设计理念,通过一系列特性消除了传统 Spring 中繁琐的配置工作。
约定大于配置即使用springboot框架自己的默认的规则,无需手动开发,如果需要特定功能,自定义配置即可。这样便可减少重复配置的书写,因为大多数配置都是固定的。
二.问题
我们先看spring编写的一套代码。
首先我们看一下项目结构:

分别是三层架构加resources层的配置文件。
Cotroller中注入service接口,serviceImpl中注入mapper接口,分别有对应的类实现对应的接口,完成从Controller层前端控制器到数据库操作层mapper的业务代码。
Controller层
@Controller("UserController")
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@PostMapping("/add")
public void addUser(){
System.out.println("UserController中的addUser方法");
userService.save();
}
}
Service层
public interface UserService {
public void save();
}
@Service("UserService")
public class UserServiceImpl implements UserService {
@Autowired
UserDao userDao;
@Override
public void save() {
System.out.println("执行service中save方法");
userDao.add();
}
}
Dao层
public interface UserDao {
public void add();
}
@Repository("UserDao")
public class UserDaoImpl implements UserDao {
@Override
public void add() {
System.out.println("执行mybatis数据库操作");
System.out.println("完成从controller到mapper层的依赖注入");
}
}
配置文件applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.pxq"/>
</beans>
User实体类
@Data
@Component("user")
@Scope("singleton")
@ToString
public class User {
private String id;
private String name;
private String password;
private String email;
public User(@Value("1") String id,
@Value("张三")String name,
@Value("123")String password,
@Value("123@qq.com") String email) {
this.id = id;
this.name = name;
this.password = password;
this.email = email;
}
}
还有最后的测试代码:
public class UserTest {
public static void main(String[] args) {
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
UserController userController = (UserController) context.getBean("UserController");
userController.addUser();
}
}
从上述代码看,1.传统spring,需要手写扫描包下所有组件并注册进容器。
<context:component-scan base-package="com.pxq"/>
@ComponentScan(basePackages = "com.pxq")
2.写测试代码需要读取配置文件中的内容,获得所有组件来使用对应的方法,测试代码繁琐,而且web项目难以测试。
3.需要手动配置很多依赖,且要考虑版本兼容问题。
三.优化
1.对于第一个问题的优化。
先说结论:项目启动类所在层及其子层的所有组件都被扫入容器并注册,并加载需要的配置类。
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
上述代码中起主要作用的是@SpringBootApplication注解
我们来看看它的内涵:
这个层级结构遵循yaml规则,同一层,级别相同。
@SpringBootApplication
@SpringBootConfiguration
@Configuration //标注当前类为一个配置类
@EnableAutoConfiguration
@AutoConfigurationPackage
@Import({AutoConfigurationPackages.Registrar.class})
//获取启动类根目录,指定组件扫描器扫描的包位置
@Import({AutoConfigurationImportSelector.class})
//筛选出符合当前环境的自动配置类(根据pom文件中加入的依赖)
@ComponextScan
//组件扫描器,扫描指定包下注解类文件,并作为spring容器使用
根据组合逻辑:
@Import({AutoConfigurationPackages.Registrar.class})
//获取启动类根目录,指定组件扫描器扫描的包位置
@ComponextScan
//组件扫描器,扫描指定包下注解类文件,并作为spring容器使用
便可以完成对启动类下所有注解文件扫描和注册。
还要提到的是:@ComponextScan 可以使用excludeFilters属性,过滤掉不需要加载的类
其中存在两个过滤类:TypeExcludeFilter和AutoCongigurationExcludeFilter。
TypeExcludeFilter会去BeanFactory中查找所有类型为TypeExcludeFilter的组件,并自定义过滤方法。
AutoCongigurationExcludeFilter用于过滤使用@Configuration和EnableAutoConfigure的类。
2.关于测试方面的优化
传统spring需要读取配置文件,来完成测试,而springboot项目可以在类中加上注解
@SpringBootTest(webEnvironment=springBootTest.WebEnvironment.***)
其中分为WebEnvironment.***的后缀有四种
MOCK:加载WebApplicationContext并模拟一个servlet环境,根据当前设置确定是否启动web环境
DEFINED_PORT:加载EmbeddedWebApplicationContext并提供真正的Servlet环境,使用自定义端口作为web服务器端口。
RANDOM_PORT:加载EmbeddedWebApplicationContext并提供真正的Servlet环境,使用随机端口作为web服务器端口。
NONE:加载ApplicationContext但不启动web环境。
@SpringBootTest(WebEnvironment=SpringBootTest.WebEnvironment.NONE)
public class MyTest(){
@Autowired
private UserService userService;
public void Test(){
userService.getById(1);
}
}
将测试类当作组件,在组件中注入要用的组件,便可使用其方法完成测试。
web形式的测试就不写了,可以去查阅其他资料。
3.依赖配置的优化
在springboot中如果想引入某个技术,只需使用springboot针对该技术的整合好的模块即可,这种模块称为starter,也叫启动器。
我们来看看最基础的依赖。
<!-- 最基础的启动器:所有功能的基石 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.7.0</version> <!-- 版本号可根据实际情况调整 -->
</dependency>
再往下看
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.7.0</version>
</dependency>
再往下看
<tomcat.version>9.0.63</tomcat.version> <!-- 默认嵌入式 Tomcat -->
<jetty.version>9.4.44.v20210927</jetty.version> <!-- 可选 Jetty 服务器 -->
<undertow.version>2.2.16.Final</undertow.version> <!-- 可选 Undertow 服务器 -->
<jackson.version>2.13.3</jackson.version> <!-- JSON 处理 -->
<mybatis.version>3.5.9</mybatis.version> <!-- MyBatis -->
<mybatis-spring.version>2.0.7</mybatis-spring.version>
<spring-data-commons.version>2.7.0</spring-data-commons.version> <!-- Spring Data 通用 -->
<spring-data-jpa.version>2.7.0</spring-data-jpa.version> <!-- JPA -->
<hibernate-core.version>5.6.10.Final</hibernate-core.version> <!-- JPA 实现 -->
<mysql-connector-java.version>8.0.29</mysql-connector-java.version> <!-- MySQL 驱动 -->
<spring-tx.version>${spring-framework.version}</spring-tx.version> <!-- 事务 -->
<spring-aop.version>${spring-framework.version}</spring-aop.version> <!-- AOP -->
<lombok.version>1.18.24</lombok.version> <!-- Lombok -->
<logback.version>1.2.11</logback.version> <!-- 日志实现 -->
<slf4j.version>1.7.36</slf4j.version> <!-- 日志门面 -->
这些还只是一部分,还有很多依赖的版本,还有一些关于spring等重要依赖未展示。
所以在最外层只需要在pom.xml中加入对应功能的启动器来调用对应功能,因为内部封装了对应的版本,无需手动写版本号,也避免了不兼容的问题。
基础型:
1.spring-boot-starter
2.spring-boot-starter-test
Web型:
1.spring-boot-starter-web
2.spring-boot-starter-webflux
不过多做展示了,可以去查阅相关启动器类型的资料帮助你更好理解。
至此关于我提出的三个问题我分别做出了解答。
四.关于后续
springboot最核心的部分还没出现,我将结合之后的内容,通过自动配置结合对应功能来更清晰的表述出springboot对于spring的优化。
1559

被折叠的 条评论
为什么被折叠?



