参考javaguide的学习笔记~
1 怎么那么多名字呀~
一开始看到这个图太劝退了,但实际上一开始只需要理解它是一个框架,包含很多个模块,能够简化开发。
使得接收HTTP请求,查数据库,写业务逻辑三部分能够分开。
并且能很方便地完成一些共同的逻辑。

2 IOC
2.1 Why?为什么要交给外部管理?
IoC(Inversion of Control)的思想是,将原本在程序中手动创建对象的控制权,交给Spring框架来管理。
- 控制:某一个类A创建另一个类的对象B,并对其进行管理的权力
- 反转:把这种控制权交给外部环境,示例化和管理由外部环境完成(Spring框架、IoC容器)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kByQj1Qy-1687247653132)(【Springboot】关于SpringBoot的那些事儿/image-20230618181702034.png)]](https://img-blog.csdnimg.cn/f64cfa6f2ab14bfca4331f07c6a64fe0.png)
如上图所示,传统的开发方式往往是在类A中通过new关键字来new一个B的对象出来。但按IoC的思想,IoC容器可以帮我们完成实例化对象,我们不必一遍又一遍地生产出Wheel类的示例,要使用某个对象时,直接从IoC容器里拿出来即可。
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3arKMxBx-1687247653132)(【Springboot】关于SpringBoot的那些事儿/image-20230618184412701.png)]](https://img-blog.csdnimg.cn/e39025bb1e67406187a2b33fa425238f.png)
比如,考虑这样一种情况,假如我们的车厂跟旧的车轮供应商闹掰了,想要把所有的轮子,全换成另一个供应商的轮子。按照旧的实现方式,我们需要把车厂中的所有车的旧轮子实例化改过来。
如果有很多个类都引用了OldWheel的具体实例化,修改起来将会非常复杂和痛苦:你不仅需要知道哪些地方引用了OldWheel,还需要知道NewWheel的构造函数需要什么参数,而更糟糕的是,这些参数有可能又有它们自己的构造函数。
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m9FDAR0s-1687247653133)(【Springboot】关于SpringBoot的那些事儿/image-20230618185432032.png)]](https://img-blog.csdnimg.cn/2dbba226053a41c68444f54b36140fc0.png)
而使用IoC的思想,我们把对象的控制权交给IoC容器管理,在使用时直接向IoC要就好了,小车类中的代码没有改动与变化。它把你从复杂的依赖关系中拯救出来,你完全不用考虑对象是如何被创建的。
3 Spring Bean是什么东东?
简单来说,Bean 代指的就是那些被 IoC 容器所管理的对象。
我们需要通知 IoC 容器帮助我们管理哪些对象,这种“通知”可以通过 XML 文件、注解或者 Java 配置类实现。
【我还是没有搞清楚BeanFactory巴拉巴拉的工作流程,但是啊,但是,我感觉框架存在的意义,就是我没必要知道这些东西是怎么工作的啊】
3.1 将一个类声明为 Bean 的注解有哪些?
@Component、@Repository、@Service、@Controller
-
@Component:通用的注解,可标注任意类为Spring组件。如果一个 Bean 不知道属于哪个层,可以使用@Component注解标注。 -
@Repository: 对应持久层 (Dao 层) ,主要用于数据库相关操作。可以看到其实现方式与@Component相同,只是明确这个类对数据库有CRUD的功能。@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Repository { @AliasFor( annotation = Component.class ) String value() default ""; } -
@Service: 对应服务层,主要涉及一些复杂的逻辑,需要用到 Dao 层。 -
@Controller: 对应 Spring MVC 控制层,主要用于接受用户请求并调用Service层返回数据给前端页面。
3.2 @Mapper和@Repository的区别?
@Mapper是Mybatis自带的一个注解。不需要在spring配置中设置扫描地址,通过mapper.xml里面的namespace属性对应相关的mapper类,Spring将动态生成Bean后注入到ServiceImpl中。@MapperScan 加在启动类上可以替代 @Mapper,把一个包里的内容都声明为Mapper。
@Repository是Spring提供的一个注解,用于声明一个Bean。在直接使用JDBC开发时可能会用到(然鹅现在大多都直接MyBatis)。
简单理解就是:@Mapper = @MapperScan(自动扫描配置)+Repository(可省略)
3.3 @Component和@Bean的区别?
@Component 注解作用于类,而@Bean注解作用于方法。
@Component通常是通过类路径扫描来自动侦测以及自动装配到 Spring 容器中(我们可以使用@ComponentScan注解定义要扫描的路径)。@Bean注解告诉了 Spring 这个方法将返回一个对象,这个对象要注册为Spring中的Bean,当我需要用它的时候还给我。
@Bean 注解比 @Component 注解的自定义性更强,而且很多地方我们只能通过 @Bean 注解来注册 bean。比如当我们引用第三方库中的类需要装配到 Spring容器时,则只能通过 @Bean来实现。
@Bean注解使用示例,按条件注入组件:
@Configuration
public class MyConfiguration {
@Bean
public User user() {
int i = 10;
if(i < 7) {
return new User("jack", 20);
} else {
return new User("david", 18);
}
}
}
@Autowired
private User user; // 将在IOC容器中寻找User对象
3.4 注入Bean的注解有哪些?
Spring 内置的 @Autowired 以及 JDK 内置的 @Resource 和 @Inject 都可以用于注入 Bean。
| Annotaion | Package | Source | |
|---|---|---|---|
@Autowired | org.springframework.bean.factory | Spring 2.5+ | byType |
@Resource | javax.annotation | Java JSR-250 | byName |
@Inject | javax.inject | Java JSR-330 |
@Autowired 和@Resource使用的比较多一些。
3.5 @Autowired 和 @Resource 的区别是什么?
@Autowired是 Spring 提供的注解,@Resource是 JDK 提供的注解。Autowired默认的注入方式为byType(根据类型进行匹配),@Resource默认注入方式为byName(根据名称进行匹配)。- 当一个接口存在多个实现类的情况下,
@Autowired和@Resource都需要通过名称才能正确匹配到对应的 Bean。Autowired可以通过@Qualifier注解来显式指定名称,@Resource可以通过name属性来显式指定名称。
1 @Autowired -> byType
Autowired 属于 Spring 内置的注解,默认的注入方式为byType(根据类型进行匹配),也就是说会优先根据接口类型去匹配并注入 Bean (接口的实现类)。
这会有什么问题呢? 当一个接口存在多个实现类的话,byType这种方式就无法正确注入对象了,因为这个时候 Spring 会同时找到多个满足条件的选择,默认情况下它自己不知道选择哪一个。
这种情况下,注入方式会变为 byName(根据名称进行匹配),这个名称通常就是类名(首字母小写)。就比如说下面代码中的 smsService 就是我这里所说的名称,这样应该比较好理解了吧。
// smsService 就是我们上面所说的名称
@Autowired
private SmsService smsService;
举个例子,SmsService 接口有两个实现类: SmsServiceImpl1和 SmsServiceImpl2,且它们都已经被 Spring 容器所管理。
// 报错,byName 和 byType 都无法匹配到 bean
@Autowired
private SmsService smsService;
// 正确注入 SmsServiceImpl1 对象对应的 bean
@Autowired
private SmsService smsServiceImpl1;
// 正确注入 SmsServiceImpl1 对象对应的 bean
// smsServiceImpl1 就是我们上面所说的名称
@Autowired
@Qualifier(value = "smsServiceImpl1")
private SmsService smsService;
我们还是建议通过 @Qualifier 注解来显式指定名称而不是依赖变量的名称。
2 @Autowired -> byType
@Resource属于 JDK 提供的注解,默认注入方式为 byName。如果无法通过名称匹配到对应的 Bean 的话,注入方式会变为byType。
@Resource 有两个比较重要且日常开发常用的属性:name(名称)、type(类型)。
- 如果仅指定
name属性则注入方式为byName - 如果仅指定
type属性则注入方式为byType - 如果同时指定
name和type属性(不建议这么做)则注入方式为byType+byName。
// 报错,byName 和 byType 都无法匹配到 bean
@Resource
private SmsService smsService;
// 正确注入 SmsServiceImpl1 对象对应的 bean
@Resource
private SmsService smsServiceImpl1;
// 正确注入 SmsServiceImpl1 对象对应的 bean(比较推荐这种方式)
@Resource(name = "smsServiceImpl1")
private SmsService smsService;
3.6 Bean 的作用域有哪些?
可以通过@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)注解配置Bean的作用域。
Spring 中 Bean 的作用域通常有下面几种:
- singleton : IoC 容器中只有唯一的 bean 实例。Spring 中的 bean 默认都是单例的,是对单例设计模式的应用。
- prototype : 每次获取都会创建一个新的 bean 实例。也就是说,连续
getBean()两次,得到的是不同的 Bean 实例。 - request (仅 Web 应用可用): 每一次 HTTP 请求都会产生一个新的 bean(请求 bean),该 bean 仅在当前 HTTP request 内有效。
- session (仅 Web 应用可用) : 每一次来自新 session 的 HTTP 请求都会产生一个新的 bean(会话 bean),该 bean 仅在当前 HTTP session 内有效。
- application/global-session (仅 Web 应用可用):每个 Web 应用在启动时创建一个 Bean(应用 Bean),该 bean 仅在当前应用启动时间内有效。
- websocket (仅 Web 应用可用):每一次 WebSocket 会话产生一个新的 bean。
3.7 Bean 的生命周期?
- Bean 容器找到配置文件中 Spring Bean 的定义。
- Bean 容器利用 Java Reflection API 创建一个 Bean 的实例。
- 如果涉及到一些属性值 利用
set()方法设置一些属性值。 - 如果 Bean 实现了
BeanNameAware接口,调用setBeanName()方法,传入 Bean 的名字。 - 如果 Bean 实现了
BeanClassLoaderAware接口,调用setBeanClassLoader()方法,传入ClassLoader对象的实例。 - 如果 Bean 实现了
BeanFactoryAware接口,调用setBeanFactory()方法,传入BeanFactory对象的实例。 - 与上面的类似,如果实现了其他
*.Aware接口,就调用相应的方法。 - 如果有和加载这个 Bean 的 Spring 容器相关的
BeanPostProcessor对象,执行postProcessBeforeInitialization()方法 - 如果 Bean 实现了
InitializingBean接口,执行afterPropertiesSet()方法。 - 如果 Bean 在配置文件中的定义包含 init-method 属性,执行指定的方法。
- 如果有和加载这个 Bean 的 Spring 容器相关的
BeanPostProcessor对象,执行postProcessAfterInitialization()方法 - 当要销毁 Bean 的时候,如果 Bean 实现了
DisposableBean接口,执行destroy()方法。 - 当要销毁 Bean 的时候,如果 Bean 在配置文件中的定义包含 destroy-method 属性,执行指定的方法。

4 Spring MVC的工作原理
Spring MVC 下我们一般把后端项目分为 :
- Controller 层(控制层,返回数据给前台页面)
- Service 层(处理业务)
- Dao 层(数据库操作)
- Entity 层(实体类)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g9gk7VfU-1687247653133)(【Springboot】关于SpringBoot的那些事儿/image-20230618224601649.png)]](https://img-blog.csdnimg.cn/627be395cbe942cdad8426303fb56ded.png)
-
用户发送
Request请求, 被前置控制器DispatcherServlet接收。DispatcherServlet:核心的中央处理器,接收请求、分发请求、响应结果,返回结果可以是json、String等数据类型,也可以是页面。
-
DispatcherServlet根据请求信息调用HandlerMapping,HandlerMapping根据 url 去匹配查找能处理的Handler(即Controller控制器) ,并会将请求涉及到的拦截器和Handler一起封装。-
mappedHandler = this.getHandler(processedRequest);HandlerExecutionChain handler = mapping.getHandler(request);
-
-
DispatcherServlet调用HandlerAdapter适配器执行Handler。- 使用适配器就可以执行多种不同的
Handler啦。
- 使用适配器就可以执行多种不同的
-
Handler完成对用户请求的处理后,会返回一个ModelAndView对象给DispatcherServlet。-
ModelAndView包含了数据模型以及相应的视图的信息。 -
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
-
-
视图解析器
ViewResolver根据ModelAndView来解析实际的View,返回给DispatherServlet。view = mv.getView(); -
DispaterServlet渲染View并返回给请求者(浏览器)view.render(mv.getModelInternal(), request, response);
下图展示了调用某个Controller时的栈,可以看到上述提及的各个类。
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6iVFLOp9-1687247653133)(【Springboot】关于SpringBoot的那些事儿/image-20230618212657147.png)]](https://img-blog.csdnimg.cn/ed8bcd21bb6d4d7392f3ec04a920b6a0.png)














![[PyTorch][chapter 43][时间序列表示方法1]](https://img-blog.csdnimg.cn/6203bc9d3ade432c91fc63c5e3768157.png)




