概览

image.png

  1. IOC : 通过反射机制实例化对象,而不需要手动new 一个对象。
  2. DI : 一个类的属性包含其他类,可以由spring通过反射和注解直接给这个属性赋值。
  3. AOP: 切面和切点。在程序运行某个方法的时候,不更改原始逻辑, 由程序动态的执行某些功能,被检测的执行方法就是切点。

Bean 加载流程

  1. Spring 框架通过ResourceLoader 加载项目的xml 配置文件
  2. 读取xml 的配置信息, 变成对象存储,暂未实例化。
  3. 通过bean 工厂处理器对bean 做实例化。 存储到map 集合中,默认是单例。
  4. 通过bean ID 获取对象。

部分源码方法

  1. prepareRefresh() : 准备刷新,加载外部的properties 属性文件。
  2. prepareBeanFactory(beanFactory): 加载bean 工厂
  3. postProcessBeanFactory(beanFactory): 读取配置文件中所有的bean 标签, 但是没有实例化。
  4. finishBeanFactoryInitialization(beanFactory): 完成bean 工厂的初始化
  5. finishRefresh(): 完成容器的刷新。

    Spring IOC

    http://www.imooc.com/wiki/springlesson/iocxml.html
    image.png
    Spring 有两个容器,包括BeanFactory 和 ApplicationContext。
    BeanFactory 是Spring 的顶层接口, ApplicationContext 是它的子接口。
    BeanFactory 提供了配置框架和基本功能,并在 ApplicationContext 中增加了更多针对企业的功能。
    BeanFactory 和 ApplicationContext 的区别: 创建对象的时间点不一样。
    ApplicationContext: 只要读取配置文件就立马创建对象。
    BeanFactory: 什么时候使用,什么时候创建对象。

    bean 标签属性列表:

    截屏2022-06-05 上午11.52.51.png
    id 和 name 用来唯一标识一个bean
    通过class 标签中定义的类全路径来制定创建哪个对象, 一般有两种方法:

  6. 反射。当然不要忘记提供无参数的构造方法(类中默认有无参构造,但是如果自定义了有参构造,默认的无参不会提供)。 因为Spring在初始化bean 的时候会调用无参构造函数

  7. 工厂模式 ,需要借助于 factory-bean 和 factory-method 两个属性,这种方式不常用,我们可以了解下。

    Spring DI

image.png
依赖注入是把一个类的依赖属性注入到这个类中,这个依赖必须已经被Spring 初始化为bean, ref 为bean 的名字。 value 字段可以直接赋值。 依赖注入是依托类中的set 方法实现的。 property name 必须要和setter 方法的名字保持一致。

多种注入类型

http://www.imooc.com/wiki/springlesson/dimuiltytype.html
map, list, array

常用注解方法

  • @Autowired : 此注解自动按照类型注入。从容器中寻找符合依赖类型的实例,当使用该注解注入属性时,set 方法可以省略。但是因为按照类型匹配,如果容器中有多个匹配的类型,会抛出异常,需要指定引入的实例 id。如果找不到匹配的实例,那么也会抛出异常;
  • @Qualifier: 此注解不能单独使用,它的作用是在按照类型注入的基础之上,再按照 Bean 的 id 注入。所以如果是使用了 @Autowire 注解自动注入,但是容器中却有多个匹配的实例,可以搭配此注解,指定需要注入的实例 id; (需要指定bean 的 id)

注意,@Qualifier 不能单独使用,要搭配@Autowired

  • @Resource 此注解的作用是指定依赖按照 id 注入,还是按照类型注入。当只使用注解,但是不指定注入方式的时候,默认按照 id 注入,找不到再按照类型注入。@Resource(name = “”) or @Resource(type = “”)

Bean 的生命周期

image.png

  • Spring 对bean 实例化,默认是单例。
  • Spring 对 bean 进行依赖注入。
  • 如果bean 实现了BeanNameAware 接口, Spring 将bean 的ID 传给setBeanName() 方法
  • 如果bean 实现了 BeanFactoryAware 接口,Spring 将调用setBeanFactory 方法将beanFactory 注入到bean 中
  • 如果 bean 实现了 ApplicationContextAware 接口,它的 setApplicationContext() 方法将被调用,将应用上下文的引用传入到 bean 中;
  • 如果 bean 实现了 BeanPostProcessor 接口,它的 postProcessBeforeInitialization 方法将被调用;
  • 如果 bean 实现了 InitializingBean 接口,Spring 将调用它的 afterPropertiesSet 接口方法,类似地如果 bean 使用了 init-method 属性声明了初始化方法,该方法也会被调用;
  • 如果 bean 实现了 BeanPostProcessor 接口,它的 postProcessAfterInitialization 接口方法将被调用;
  • 此时 bean 已经准备就绪,可以被应用程序使用了,他们将一直驻留在应用上下文中,直到该应用上下文被销毁;
  • 若 bean 实现了 DisposableBean 接口,Spring 将调用它的 distroy() 接口方法。同样地,如果 bean 使用了 destroy-method 属性声明了销毁方法,则该方法被调用;

    bean 的作用范围 scope

    singleton : 在spring上下文中只存在着一个bean 。
    prototype: 每次从上下文中获取bean 都创建一个。

    Spring AOP

    术语

  1. Joint Point 连接点

指被拦截到的点,spring 里指方法, 可以看作正在访问的或者等待访问的那些需要被增强功能的方法, Spring 只支持方法类型的连接点。

  1. PointCut 切入点

切入点是一个规则,定义了我们需要对哪些方法进行拦截

  1. Advice 通知

前置通知 (无错误异常),后置通知(无错误异常),最终通知(有异常),异常通知,环绕通知。

  1. Target 目标

指代理的目标对象,即连接点所在类的代理对象

  1. Aspect 切面

功能类,作为整合AOP的切入点和通知

  1. Weaving 织入

是一种动作描述,在程序运行时将增强的功能代码根据通知放到对应的位置

  1. Proxy

一个类被代理增强后,产生的结果就是代理类。

代理模式

代理模式的具体表现为:创建带有现有对象的代理对象,以便向外界提供功能接口, 代理对象可以在客户端和目标对象之间起到中介的作用。即为被代理对象执行一些附带的,额外的功能。
image.png

  1. aop:aspectj-autoproxy: 此注解表示开启代理模式

    常用注解

    @Aspect, @Pointcut, @Before, @AfterReturning, @After, @AfterThrowing
    用于开启事务。

    Spring MVC

    常用注解

  2. @RestController 和 @Controller 的区别: https://www.cnblogs.com/east7/p/10462279.html

前者可以返回json对象,不能返回指定页面。后者可以返回页面,但是返回json 对象需要@ResponseBody 注解

  1. 地址请求映射: http://www.imooc.com/wiki/springmvclesson/sm05.html
  2. 绑定请求包中的数据: http://www.imooc.com/wiki/springmvclesson/sm06.html

@RequestParam, 请求格式类似 http://localhost:8888/saveUser? userName=abc&password=123456

  1. @RequestMapping(value="/saveUser")
  2. public String save(@RequestParam("userName") String userName,@RequestParam("password") password){}

@CookieValue ()
@RequestHeader
@PathVariable ( 采用占位符来存储路径变量 )

  1. @RequestMapping("/user/{userId}")
  2. public String getUserById(@PathVariable("userId") String userId){
  3. }

核心组件

http://www.imooc.com/wiki/springmvclesson/sm03.html
前端控制器, 用户控制器, 映射器, 适配器, 视图解析器

数据模型组件

Model/ModelMap/ModelAndView

Spring 事务

在类上标注@Transactional 可以开启申明式事务。

Spring 异常处理

将所有的异常抛到控制层统一处理,控制层使用面向切面编程统一处理。
@ControllerAdvice(annotations = ControllerClass.class)
@RestControllerAdvice(annotations = RestController.class)
@ExceptionalHandler({ExceptionClass.class})
http://www.imooc.com/wiki/springbootlesson/except.html

Spring 定时任务

  1. /**
  2. * 任务类
  3. */
  4. @Component
  5. public class MySpringTask {
  6. /**
  7. * 在每分钟的00秒执行
  8. */
  9. @Scheduled(cron = "0 * * * * ?")
  10. public void jump() throws InterruptedException {
  11. System.out.println("心跳检测:" + new Date());
  12. }
  13. /**
  14. * 在每天的00:00:00执行
  15. */
  16. @Scheduled(cron = "0 0 0 * * ?")
  17. public void stock() throws InterruptedException {
  18. System.out.println("置满库存:" + new Date());
  19. }
  20. }

@EnableScheduling, @Scheduled

Cron 表达式

Cron 表达式并不难理解,从左到右一共 6 个位置,分别代表秒、时、分、日、月、星期,以秒为例:

  • 如果该位置上是 0 ,表示在第 0 秒执行;
  • 如果该位置上是 * ,表示每秒都会执行;
  • 如果该位置上是 ? ,表示该位置的取值不影响定时任务,由于月份中的日和星期可能会发生意义冲突,所以日、 星期中需要有一个配置为 ? 。

按照上面的理解,cron = “0 ?” 表示在每分钟的 00 秒执行、cron = “0 0 0 ?” 表示在每天的 00:00:00 执行。

Quartz 定时任务

Quartz 定时任务需要通过 Job 、 Trigger 、 JobDetail 来设置。

  • Job:具体任务操作类
  • Trigger:触发器,设定执行任务的时间
  • JobDetail:指定触发器执行的具体任务类及方法
  1. /**
  2. * 定时任务配置
  3. */
  4. @Configuration
  5. public class QuartzConfig {
  6. /**
  7. * 配置JobDetail工厂组件,生成的JobDetail指向discountJob的execute()方法
  8. */
  9. @Bean
  10. MethodInvokingJobDetailFactoryBean jobFactoryBean() {
  11. MethodInvokingJobDetailFactoryBean bean = new MethodInvokingJobDetailFactoryBean();
  12. bean.setTargetBeanName("discountJob");
  13. bean.setTargetMethod("execute");
  14. return bean;
  15. }
  16. /**
  17. * 触发器工厂
  18. */
  19. @Bean
  20. CronTriggerFactoryBean cronTrigger() {
  21. CronTriggerFactoryBean bean = new CronTriggerFactoryBean();
  22. // Corn表达式设定执行时间规则
  23. bean.setCronExpression("0 0 8 ? * 7");
  24. // 执行JobDetail
  25. bean.setJobDetail(jobFactoryBean().getObject());
  26. return bean;
  27. }
  28. }