Spring更像是一种生态,Spring的一个最大的目的就是使JAVA EE开发更加容易,所以也可以将其理解为Spring是一个提供了更完善开发环境的一个框架
Spring 的特性和优势
从特性来看
- 非侵入式:基于Spring开发的应用中的对象可以不依赖于Spring的API
- 控制反转:IOC——Inversion of Control,指的是将对象的创建权交给 Spring 去创建。使用 Spring 之前,对象的创建都是由我们自己在代码中new创建。而使用 Spring 之后。对象的创建都是给了 Spring 框架
- 依赖注入:DI——Dependency Injection,是指依赖的对象不需要手动调用 setXX 方法去设置,而是通过配置赋值
- 面向切面编程:Aspect Oriented Programming——AOP
- 容器:Spring 是一个容器,因为它包含并且管理应用对象的生命周期
- 组件化:Spring 实现了使用简单的组件配置组合成一个复杂的应用。在 Spring 中可以使用XML和Java注解组合这些对象
- 一站式:在 IOC 和 AOP 的基础上可以整合各种企业应用的开源框架和优秀的第三方类库(实际上 Spring 自身也提供了表现层的 SpringMVC 和持久层的 Spring JDBC)
其中重点是控制反转和依赖注入(DI),那么Spring到底是如何进行创建对象和注入的呢?
在loC中,Spring容器会负责创建对象并注入依赖关系
在 Spring 框架中,构成应用程序骨干并由 Spring IoC 容器管理的对象称为 bean。bean 是由 Spring IoC 容器实例化、组装和管理的对象。除此之外,bean 只是应用程序中众多对象之一,bean 及其依赖关系都反映在容器使用的配置元数据中
根据官方文档中的
基于注释去进行容器配置
loC的写法
@Autowired
UserService userService;
/*
命名习惯
UserService 用户业务逻辑
UserRepository 用户数据库访问
UserController 用户接口控制器
*/
DI只是IoC里面对依赖和对象的具体处理方式,让agent帮我整理了一下创建对象/注入对象等的例子
package demo;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import java.util.UUID;
@Configuration
@ComponentScan(basePackageClasses = SpringCreateObjectWaysDemo.class)
@Import({
ImportedPlainBean.class,
ImportedConfig.class
})
public class SpringCreateObjectWaysDemo {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
// 方式10:直接把一个现成对象塞进 Spring 单例池
context.getBeanFactory().registerSingleton(
"way10_registerSingleton",
new RegisterSingletonBean()
);
// 方式11:用 GenericApplicationContext.registerBean 注册 Bean context.registerBean(
"way11_registerBeanApi",
RegisterBeanApiBean.class,
RegisterBeanApiBean::new
);
context.register(SpringCreateObjectWaysDemo.class);
context.refresh();
show(context, "way1_component");
show(context, "way2_service");
show(context, "way3_repository");
show(context, "way4_controller");
show(context, "way5_beanMethod");
showType(context, ImportedPlainBean.class);
show(context, "way7_importedBeanMethod");
show(context, "way8_factoryBean");
show(context, "&way8_factoryBean");
show(context, "way9_beanDefinition");
show(context, "way10_registerSingleton");
show(context, "way11_registerBeanApi");
show(context, "way12_prototypeBean");
show(context, "way13_constructorInjection");
show(context, "way14_fieldInjection");
show(context, "way15_setterInjection");
context.close();
}
// 方式5:@Bean 方法创建对象
@Bean("way5_beanMethod")
public BeanMethodBean beanMethodBean() {
return new BeanMethodBean();
}
private static void show(ApplicationContext context, String beanName) {
Object bean = context.getBean(beanName);
System.out.println(beanName + " -> " + bean.getClass().getName());
}
private static void showType(ApplicationContext context, Class<?> type) {
Object bean = context.getBean(type);
System.out.println(type.getSimpleName() + " -> " + bean.getClass().getName());
}
}
// 方式1:@Component 创建 Bean@Component("way1_component")
class ComponentBean {
}
// 方式2:@Service 创建 Bean,本质上也是 @Component,语义是业务层
@Service("way2_service")
class ServiceBean {
}
// 方式3:@Repository 创建 Bean,本质上也是 @Component,语义是数据库访问层
@Repository("way3_repository")
class RepositoryBean {
}
// 方式4:@Controller 创建 Bean,本质上也是 @Component,语义是 Web 控制器
@Controller("way4_controller")
class ControllerBean {
}
class BeanMethodBean {
}
// 方式6:通过 @Import 直接导入普通类
class ImportedPlainBean {
}
// 方式7:通过 @Import 导入配置类,再由配置类里的 @Bean 创建对象
@Configuration
class ImportedConfig {
@Bean("way7_importedBeanMethod")
public ImportedBeanMethodBean importedBeanMethodBean() {
return new ImportedBeanMethodBean();
}
}
class ImportedBeanMethodBean {
}
// 方式8:FactoryBean 创建对象
@Component("way8_factoryBean")
class CarFactoryBean implements FactoryBean<Car> {
@Override
public Car getObject() {
return new Car("created by FactoryBean");
}
@Override
public Class<?> getObjectType() {
return Car.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
class Car {
private final String source;
public Car(String source) {
this.source = source;
}
@Override
public String toString() {
return "Car{source='" + source + "'}";
}
}
// 方式9:BeanDefinitionRegistryPostProcessor 动态注册 BeanDefinition@Component
class DynamicBeanRegistrar implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
throws BeansException {
registry.registerBeanDefinition(
"way9_beanDefinition",
BeanDefinitionBuilder
.genericBeanDefinition(DynamicRegisteredBean.class)
.getBeanDefinition()
);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
throws BeansException {
}
}
class DynamicRegisteredBean {
}
class RegisterSingletonBean {
}
class RegisterBeanApiBean {
}
// 方式12:prototype,每次从容器拿都会创建新对象
@Component("way12_prototypeBean")
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
class PrototypeBean {
private final String id = UUID.randomUUID().toString();
@Override
public String toString() {
return "PrototypeBean{id='" + id + "'}";
}
}
// 方式13:@Lookup,让 Spring 动态返回 prototype Bean
// 下面三个不是“注册 Bean 的方式”,而是 Spring 创建 Bean 时常见的依赖注入方式
// 方式14:构造器注入,推荐
@Component("way13_constructorInjection")
class ConstructorInjectionBean {
private final ComponentBean componentBean;
public ConstructorInjectionBean(ComponentBean componentBean) {
this.componentBean = componentBean;
}
}
// 方式15:字段注入,不推荐,但能用
@Component("way14_fieldInjection")
class FieldInjectionBean {
@Autowired
private ComponentBean componentBean;
}
// 方式16:Setter 注入,适合可选依赖
@Component("way15_setterInjection")
class SetterInjectionBean {
private ComponentBean componentBean;
@Autowired
public void setComponentBean(ComponentBean componentBean) {
this.componentBean = componentBean;
}
}
输出
way1_component -> demo.ComponentBean
way2_service -> demo.ServiceBean
way3_repository -> demo.RepositoryBean
way4_controller -> demo.ControllerBean
way5_beanMethod -> demo.BeanMethodBean
ImportedPlainBean -> demo.ImportedPlainBean
way7_importedBeanMethod -> demo.ImportedBeanMethodBean
way8_factoryBean -> demo.Car
&way8_factoryBean -> demo.CarFactoryBean
way9_beanDefinition -> demo.DynamicRegisteredBean
way10_registerSingleton -> demo.RegisterSingletonBean
way11_registerBeanApi -> demo.RegisterBeanApiBean
way12_prototypeBean -> demo.PrototypeBean
way13_constructorInjection -> demo.ConstructorInjectionBean
way14_fieldInjection -> demo.FieldInjectionBean
way15_setterInjection -> demo.SetterInjectionBean
进程已结束,退出代码为 0
AOP(面向切面编程)
Spring 框架通过定义切面, 通过拦截切点实现了不同业务模块的解耦,这个就叫**面向切面编程 – Aspect Oriented Programming (AOP)
Spring Framework 提供了 Spring AOP 来实现
AOP常见术语
- 连接点(Jointpoint):表示需要在程序中插入横切关注点的扩展点,连接点可能是类初始化、方法执行、方法调用、字段调用或处理异常等等,Spring只支持方法执行连接点,在AOP中表示为在哪里干;
- 切入点(Pointcut): 选择一组相关连接点的模式,即可以认为连接点的集合,Spring支持perl5正则表达式和AspectJ切入点模式,Spring默认使用AspectJ语法,在AOP中表示为在哪里干的集合;
- 通知(Advice):在连接点上执行的行为,通知提供了在AOP中需要在切入点所选择的连接点处进行扩展现有行为的手段;包括前置通知(before advice)、后置通知(after advice)、环绕通知(around advice),在Spring中通过代理模式实现AOP,并通过拦截器模式以环绕连接点的拦截器链织入通知;在AOP中表示为干什么;
- 方面/切面(Aspect):横切关注点的模块化,比如上边提到的日志组件。可以认为是通知、引入和切入点的组合;在Spring中可以使用Schema和@AspectJ方式进行组织实现;在AOP中表示为在哪干和干什么集合;
- 引入(inter-type declaration):也称为内部类型声明,为已有的类添加额外新的字段或方法,Spring允许引入新的接口(必须对应一个实现)到所有被代理对象(目标对象), 在AOP中表示为干什么(引入什么);
- 目标对象(Target Object):需要被织入横切关注点的对象,即该对象是切入点选择的对象,需要被通知的对象,从而也可称为被通知对象;由于Spring AOP 通过代理模式实现,从而这个对象永远是被代理对象,在AOP中表示为对谁干;
- 织入(Weaving):把切面连接到其它的应用程序类型或者对象上,并创建一个被通知的对象。这些可以在编译时(例如使用AspectJ编译器),类加载时和运行时完成。Spring和其他纯Java AOP框架一样,在运行时完成织入。在AOP中表示为怎么实现的;
- AOP代理(AOP Proxy):AOP框架使用代理模式创建的对象,从而实现在连接点处插入通知(即应用切面),就是通过代理来对目标对象应用切面。在Spring中,AOP代理可以用JDK动态代理或CGLIB代理实现,而通过拦截器模型应用切面
如何简单理解切面?
比如我们有100个业务方法,但是后面老板突然要求说每个方法执行前都要打印日志,那么切面存在的意义就是,不用我们对每个方法去加上日志输出,而是写一处就可以在那100个方法里自动生效
写一个简单的AOP示例
我这里为了方便直接启用了一个Spring boot项目
项目结构
├── src
│ ├── main
│ │ ├── java
│ │ │ └── org
│ │ │ └── example
│ │ │ └── spring
│ │ │ ├── Application.java
│ │ │ ├── LogAspect.java
│ │ │ └── UserService.java
│ │ └── resources
│ │ ├── application.properties
│ │ ├── static
│ │ └── templates
│ └── test
│ └── java
│ └── org
│ └── example
│ └── spring
│ └── ApplicationTests.java
配置类
Application.java
package org.example.spring;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
//@SpringBootConfiguration
//本质就是 @Configuration,标明当前类是配置类
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
//SpringApplication.run(...):启动整个 Spring Boot 应用
//
//Application.class:告诉 Spring "把这个类作为主配置类,从这里开始加载一切"
// //args:把命令行参数传进去
}
Bean
UserService.java
package org.example.spring;
import org.springframework.stereotype.Service;
@Service
public class UserService {
public void addUser() {
System.out.println("添加用户");
}
}
切面
LogPect.java
package org.example.spring;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LogAspect {
@Before("execution(* org.example.spring.UserService.addUser(..))")
public void before() {
System.out.println("日志记录");
}
}
测试类
package org.example.spring;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class ApplicationTests {
@Autowired
private UserService userService;
//把容器里的 UserService Bean 注入到测试类中。这里能注入成功,说明 UserService 肯定被 @Service 之类注解标记,且被组件扫描到了
@Test
void addUserTriggersLogAspect() {
userService.addUser();
}
//
}

核心注解
| 注解 | 作用 | 常用程度 |
|---|---|---|
| @Aspect | 声明当前类是切面类 | 非常常用 |
| @Component | 把切面类交给 Spring 管理 | 非常常用 |
| @Pointcut | 定义可复用的切入点表达式 | 常用 |
| @Before | 目标方法执行前执行 | 常用 |
| @After | 目标方法结束后执行,不管成功还是异常 | 常用 |
| @AfterReturning | 目标方法正常返回后执行 | 常用 |
| @AfterThrowing | 目标方法抛异常后执行 | 常用 |
| @Around | 环绕通知,可以控制目标方法是否执行 | 最强大,也最常用 |
| @EnableAspectJAutoProxy | 开启 AOP 代理功能 | 普通 Spring 常用,Spring Boot 通常自动配置 |
| @Order | 控制多个切面的执行顺序 | 多切面时常用 |
Spring组件

以上几乎包含了Spring所有模块
Core Container
核心容器由 Beans 模块、Core 核心模块、Context 上下文模块和 SpEL 表达式语言模块组成
简单介绍一下:
- Core 模块
- Core 是 Spring 最基础的核心模块,提供框架的底层能力,例如资源访问、类型转换、工具类等
- 其他模块很多功能都依赖 Core 模块
- Beans 模块
- Beans 模块负责对象的创建、配置和管理,是 Spring IoC 容器的重要基础
- 我们平时说的 Bean、依赖注入、BeanFactory 等概念都和它有关
- Context 模块
- Context 模块建立在 Core 和 Beans 之上,提供更高级的容器功能
- 常用的 ApplicationContext 就属于这个模块,它支持国际化、事件发布、资源加载、注解配置等功能
- SpEL 模块
- SpEL 是 Spring Expression Language,中文叫 Spring 表达式语言
- 它可以在运行时解析表达式,用来读取对象属性、调用方法、进行逻辑判断等,常见于配置文件和注解中
Data Access/Integration(数据访问/集成)
数据访问/集成层包括 JDBC、ORM、OXM、JMS 和 Transactions 模块
- JDBC 模块
- JDBC 模块对原生 JDBC 进行了封装,简化了数据库操作
- 它可以减少重复代码,例如创建连接、释放资源、处理异常等
- ORM 模块
- ORM 模块用于整合对象关系映射框架,例如 Hibernate、JPA、MyBatis 等
- 它可以让 Java 对象和数据库表之间进行映射,简化数据库开发
- OXM 模块
- OXM 是 Object XML Mapping,对象 XML 映射
- 它用于 Java 对象和 XML 数据之间的转换,常用于 XML 数据处理场景
- JMS 模块
- JMS 是 Java Message Service,Java 消息服务。
- Spring 的 JMS 模块用于支持消息队列,方便应用之间通过消息进行异步通信
- Transactions 模块
- Transactions 是事务模块,用于管理数据库事务
- 它支持声明式事务,例如使用 @Transactional 控制方法的事务提交和回滚
Web模块
Spring 的 Web 层包括 Web、Servlet、WebSocket 和 Webflux 组件
- Web 模块:
- 提供了基本的 Web 开发集成特性,例如多文件上传功能、使用的 Servlet 监听器的 IOC 容器初始化以及 Web 应用上下文
- Servlet 模块:
- 提供了一个 Spring MVC Web 框架实现。Spring MVC 框架提供了基于注解的请求资源注入、更简单的数据绑定、数据验证等及一套非常易用的 JSP 标签,完全无缝与 Spring 其他技术协作
- WebSocket 模块:
- 提供了简单的接口,用户只要实现响应的接口就可以快速的搭建 WebSocket Server,从而实现双向通讯
- Webflux 模块:
- Spring WebFlux 是 Spring Framework 5.x中引入的新的响应式web框架。与Spring MVC不同,它不需要Servlet API,是完全异步且非阻塞的,并且通过Reactor项目实现了Reactive Streams规范。Spring WebFlux 用于创建基于事件循环执行模型的完全异步且非阻塞的应用程序
- Portlet 模块:提供了在 Portlet 环境中使用 MVC 实现,类似 Web-Servlet 模块的功能
Test测试模块
主要用来测试的框架,其中包含了spring-test
Spring MVC
Spring MVC是什么?
是Spring提供的Web开发框架,主要用于开发Web应用和REST接口
MVC分别代表:Model模型,View视图,Controller控制器
简单来说就是将Web层进行解耦,业务、逻辑、页面分离,各司其职
Spring MVC 的核心思想
- 用户发送请求
- Spring MVC 接收请求
- 找到对应的 Controller 方法
- 执行业务逻辑
- 返回页面或 JSON 数据
Spring MVC 的执行流程
- 浏览器发送请求,例如:
http://localhost:8080/user/add
- 请求先到达 DispatcherServlet
- DispatcherServlet 是 Spring MVC 的前端控制器,负责统一接收所有请求
- 它根据请求路径找到对应的 Controller
- Controller 调用 Service 处理业务逻辑
- Service 返回处理结果
- Controller 再返回视图页面或 JSON 数据
- Spring MVC 将结果响应给浏览器
常用注解
- @Controller
- 标记一个类是控制器
- 通常用于返回页面
- @RestController
- 等价于 @Controller + @ResponseBody
- 通常用于返回 JSON 数据
- @RequestMapping
- 用于映射请求路径
- 可以写在类上,也可以写在方法上
- @GetMapping
- 处理 GET 请求
- @PostMapping
- 处理 POST 请求
- @PutMapping
- 处理 PUT 请求
- @DeleteMapping
- 处理 DELETE 请求
- @RequestParam
- 获取请求参数
- 例如:?name=Tom
- @PathVariable
- 获取路径参数
- 例如:/user/1
- @RequestBody
- 接收请求体中的 JSON 数据
- @ResponseBody
- 将方法返回值直接写入响应体
Spring Boot
Spring Boot 是什么?
- Spring Boot 是基于 Spring 的快速开发框架
- 它不是用来替代 Spring,而是用来简化 Spring 项目的创建、配置和运行
- 使用 Spring Boot 可以少写很多 XML 配置和重复配置
- 它的核心目标是让开发者更快地搭建一个可以运行的 Spring 项目
Spring Boot 和 Spring 的关系
- Spring 是基础框架,提供 IoC、AOP、事务、MVC 等核心能力
- Spring Boot 是对 Spring 的进一步封装
- Spring Boot 帮我们自动配置 Spring 项目
- Spring Boot 让 Spring 项目可以更快启动、更少配置、更容易部署
Spring Boot 主要解决的问题 - 简化项目搭建
- 简化依赖管理
- 简化配置文件
- 简化服务器部署
- 简化 Spring MVC、数据库、事务、AOP 等功能的整合
Spring Boot 的核心特点 - 自动配置
- Spring Boot 会根据项目中引入的依赖自动配置对应功能
- 例如引入 Web 依赖后,会自动配置 Spring MVC、Tomcat、JSON 转换等功能
- 起步依赖
- Spring Boot 提供了很多 starter 依赖
- starter 可以把某一类功能需要的依赖一次性引入
- 例如 Web 开发常用
spring-boot-starter-web或 Boot 4 中的spring-boot-starter-webmvc
- 内嵌服务器
- Spring Boot 默认可以内嵌 Tomcat、Jetty、Undertow 等服务器
- 项目不需要单独部署到外部 Tomcat
- 直接运行 main 方法就可以启动 Web 项目
- 约定大于配置
- Spring Boot 提供了一套默认约定
- 只要按照默认目录结构和默认配置来写,大部分功能都能自动生效
- 需要自定义时再通过配置文件修改
Spring Boot 启动类
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@SpringBootApplication是 Spring Boot 项目的核心注解- 它表示当前类是 Spring Boot 的启动类
SpringApplication.run用来启动 Spring 容器和整个应用
@SpringBootApplication 的作用
@SpringBootApplication可以看作三个注解的组合@SpringBootConfiguration- 表示这是一个 Spring Boot 配置类
@EnableAutoConfiguration- 开启自动配置
@ComponentScan- 开启组件扫描
组件扫描
- Spring Boot 默认会扫描启动类所在包及其子包
- 你的启动类在
org.example.spring包下 - 所以 Spring 会扫描
org.example.spring下面的类 - 加了
@Service、@Component、@Controller、@RestController的类会被 Spring 管理
自动配置
- 自动配置是 Spring Boot 最核心的能力之一
- Spring Boot 会根据 classpath 中的依赖判断要开启哪些功能
- 如果项目中有 Web 相关依赖,Spring Boot 就会自动配置 Web 环境
- 如果项目中有 JDBC 相关依赖,Spring Boot 就会尝试配置数据源
- 如果项目中有 AOP 相关依赖,Spring Boot 就会自动启用 AOP 支持
starter 起步依赖
- starter 是 Spring Boot 提供的依赖集合
- 它不是一个具体功能,而是一组依赖的组合
- 使用 starter 可以避免手动引入一堆零散依赖
常见 starter:
spring-boot-starter-webmvc Web MVC 开发
spring-boot-starter-test 测试
spring-boot-starter-jdbc JDBC 数据库访问
spring-boot-starter-data-jpa JPA 数据库访问
spring-boot-starter-validation 参数校验
spring-boot-starter-security 安全认证
spring-boot-starter-actuator 项目监控
spring-boot-starter-aspectj AOP 支持
配置文件
- Spring Boot 常用配置文件有两种
application.propertiesapplication.yml
示例:
server.port=8081
spring.application.name=spring-demo
server.port用来修改项目端口spring.application.name用来设置应用名称- Spring Boot 会自动读取这些配置
Spring Boot 和 Spring MVC
- Spring MVC 是 Web 框架
- Spring Boot 可以自动配置 Spring MVC
- 引入 Web 相关 starter 后,就可以直接写 Controller
- 不需要手动配置 DispatcherServlet、HandlerMapping、消息转换器等内容
示例:
@RestController
@RequestMapping("/user")
public class UserController {
@GetMapping("/hello")
public String hello() {
return "hello spring boot";
}
}
Spring Boot 项目常见分层
controller 接收请求
service 处理业务逻辑
mapper 操作数据库
entity 实体类
config 配置类
aspect 切面类
- Controller 负责和前端交互
- Service 负责业务处理
- Mapper 或 Repository 负责数据库操作
- Entity 表示数据对象
- Config 用来写配置
- Aspect 用来写 AOP 切面
Spring Boot 的优点
- 创建项目快
- 配置少
- 依赖管理简单
- 可以直接运行
- 适合开发 Web 接口
- 适合整合数据库、缓存、消息队列、安全框架等
- 适合微服务项目开发
一句话总结 - Spring Boot 是用来简化 Spring 开发的框架
- 它通过自动配置、起步依赖、内嵌服务器和约定大于配置,让 Spring 项目更容易创建、运行和部署
只是对基础做了简单的了解,深入还得等后续研究漏洞