一文看懂Spring核心概念和源码解读

2023-05-27 0 1,092

# 该文看懂Spring核心理念基本概念和源代码阐释

## 责任编辑产品目录

一、Spring架构的组件共同组成二、Spring的核心理念基本原理三、Spring的三大核心理念USB:BeanFactory和ApplicationContext四、Spring罐子中的Bean五、科枫Bean的缓存安全可靠和mammalian难题(重点项目)六、Spring的会话七、Spring架构中加进的程序语言八、Spring架构的该事件类别

## 一、Spring架构的组件共同组成

一文看懂Spring核心概念和源码解读

1. 核心理念组件

1. 核心理念罐子(Core Container)

2. AOP(Aspect Oriented Programming)

3. 电子设备全力支持(Instrument)

4. 统计数据出访及软件系统(Data Access/Integratioin)

5. Web

6. 统计数据流推送(Messaging)

7. Test等组件。

2. Spring的缺点

1. 低入侵式

2. DI监督机制增加组件谐振性

3. AOP

4. 可扩展性

## 二、Spring的核心理念基本原理

Spring架构最核心理念的基本原理:IOC 和 AOP。IOC让互相合作的组件维持致密的谐振,而AOP程式设计容许把遍及于应用领域各层的机能析出逐步形成可宠信的机能组件。

### 1. 控制反转 IOC

1. 罐子控制创建对象,降低对象之间谐振性,利于机能复用

2. 创建对象不需要new,而是利用JAVA反射监督机制根据配置文件动态创建对象和管理对象

3. Spring中三种注入方式:

1. 构造器注入2. setter方法注入3. 基于注解注入(@Autowire)

### 2. 面向切面 AOP

1. AOP的理解

抽取并封装多个对象的公共行为和逻辑成一个可宠信的组件`切面(Aspect)`

一文看懂Spring核心概念和源码解读

2. 静态代理(AspectJ)和动态代理(Spring AOP)

1. `静态代理`:AspectJ是静态代理的增强,编译时将AspectJ植入Java字节码中,运用时就是增强后的代理对象2. `动态代理`:动态代理不会修改Java字节码,是每次运行时在内存中临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法

3. Spring AOP动态代理的两种方式(JDK和CGLIB)

1. `JDK`:JDK动态代理只提供USB的代理,不全力支持类的代理。
一文看懂Spring核心概念和源码解读
2. `CGLIB`:是一个代码生成的类库,可以在运行时动态的生成指定类的一个子类对象,并覆盖其中特定方法并添加增强代码,从而实现AOP。
一文看懂Spring核心概念和源码解读
3. GLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。
一文看懂Spring核心概念和源码解读

4. AOP的核心理念基本概念

一文看懂Spring核心概念和源码解读

1. `切面(Aspect)`:被抽取的公共组件,可能会横切多个对象。 在Spring AOP中,切面可以使用通用类(基于模式的风格) 或者在普通类中以 @AspectJ 注解来实现。

一文看懂Spring核心概念和源码解读

2. `连接点(Join point)`:指方法,在Spring AOP中,一个连接点 总是 代表一个方法的执行。

3.`通知(Advice)`:在切面的某个特定的连接点(Join point)上执行的动作。通知有各种类别,其中包括“around”、“before”和“after”等通知。许多AOP架构,包括Spring,都是以拦截器做通知模型, 并维护一个以连接点为中心的拦截器链。

一文看懂Spring核心概念和源码解读
一文看懂Spring核心概念和源码解读

4. `切入点(Pointcut)`:切入点是指 我们要对哪些Join point进行拦截的定义。通过切入点表达式,指定拦截的方法,比如指定拦截add*、search*。

一文看懂Spring核心概念和源码解读

5. `引入(Introduction)`:(也被称为内部类别声明(inter-type declaration))。声明额外的方法或者某个类别的字段。Spring容许引入新的USB(以及一个对应的实现)到任何被代理的对象。例如,你可以使用一个引入来使bean实现 IsModified USB,以便简化缓存监督机制。

6. `目标对象(Target Object)`: 被一个或者多个切面(aspect)所通知(advise)的对象。也有人把它叫做 被通知(adviced) 对象。 既然Spring AOP是通过运行时代理实现的,这个对象永远是一个 被代理(proxied) 对象。

7. `织入(Weaving)`:指把增强应加进目标对象来创建新的代理对象的过程。Spring是在运行时完成织入。

8. 切入点(pointcut)和连接点(join point)匹配的基本概念是AOP的关键,这使得AOP不同于其它仅仅提供拦截机能的旧技术。 切入点使得定位通知(advice)可独立于OO层次。

一文看懂Spring核心概念和源码解读

5. AOP的应用领域场景

一文看懂Spring核心概念和源码解读

6. AOP的实战场景

一文看懂Spring核心概念和源码解读
一文看懂Spring核心概念和源码解读
一文看懂Spring核心概念和源码解读
一文看懂Spring核心概念和源码解读
一文看懂Spring核心概念和源码解读
一文看懂Spring核心概念和源码解读
一文看懂Spring核心概念和源码解读
一文看懂Spring核心概念和源码解读

7. 使用SpringAop的注意事项

一文看懂Spring核心概念和源码解读

参考[探秘Spring AOP](https://www.imooc.com/learn/869)课程截图

一文看懂Spring核心概念和源码解读
一文看懂Spring核心概念和源码解读
一文看懂Spring核心概念和源码解读
一文看懂Spring核心概念和源码解读
一文看懂Spring核心概念和源码解读
一文看懂Spring核心概念和源码解读
一文看懂Spring核心概念和源码解读

### 三、Spring的三大核心理念USB:BeanFactory和ApplicationContext

BeanFactory和ApplicationContext是Spring的三大核心理念USB,都可以当做Spring的罐子。其中ApplicationContext是BeanFactory的子USB。

1. ApplicationContext 是 BeanFactory 的子USB,机能更全

1. BeanFactory是Spring里面最底层的USB,包含了各种Bean的定义,读取bean配置文档,管理bean的加载、实例化,控制bean的生命周期,维护bean之间的依赖关系。ApplicationContext是BeanFactory的派生USB,除了提供BeanFactory所具有的机能外,还提供了更完整的架构机能:2. 继承MessageSource,因此全力支持国际化。3. 统一的资源文件出访方式。4. 提供在监听器中注册bean的该事件。5. 同时加载多个配置文件。6. 载入多个(有继承关系)上下文 ,使得每一个上下文都专注于一个特定的层次,比如应用领域的web层。

2. 加载方式

1. `BeanFactroy` 采用的是延迟加载形式来注入Bean,即只有在使加进某个Bean时(调用getBean()),才对该Bean进行加载实例化。这样,我们就不能发现一些存在的Spring的配置难题。如果Bean的某一个属性没有注入,BeanFacotry加载后,直至第一次使用调用getBean方法才会抛出异常2. `ApplicationContext` 是在罐子启动时,一次性创建了所有的Bean。这样,在罐子启动时,我们就可以发现Spring中存在的配置错误,这样有利于检查所依赖属性是否注入。 ApplicationContext启动后预载入所有的单实例Bean,通过预载入单实例bean ,确保当你需要的时候,你就不用等待,因为它们已经创建好了。

相对于基本的BeanFactory,ApplicationContext 唯一的不足是占用内存空间。当应用领域程序配置Bean较多时,程序启动较慢。

3. 创建方式

1. BeanFactory 通常以程式设计的方式被创建。2. ApplicationContext 除了程式设计方式,还能以声明的方式创建,如使用ContextLoader。

4. 注册方式

BeanFactory和ApplicationContext都全力支持BeanPostProcessor、BeanFactoryPostProcessor的使用,但两者之间的区别是:BeanFactory需要手动注册,而ApplicationContext则是自动注册。

### 四、Spring罐子中的Bean

#### 1. Bean的作用域

1. `singleton(科枫)`,在spring罐子中仅存在一个Bean实例,Bean以科枫方式存在,bean作用域范围的默认值。

2. `prototype(原型)`,每次从罐子中调用Bean时,都返回一个新的实例,即每次调用getBean()时,相当于执行newXxxBean()。

3. `request`,每次HTTP请求都会创建一个新的Bean,该作用域仅适用于web的WebApplicationContext环境。

4. `session`,同一个HTTP Session共享一个Bean,不同Session使用不同的Bean。该作用域仅适用于web的WebApplicationContext环境。

5. `globalSession`,同一个全局 Session 共享一个 bean,用于 Portlet, 该作用域仅用于 WebApplication 环境。

#### 2. Bean注入的几种方式

1. 基于注解 @Autowired 的自动装配(最常用)

1. authwire3个属性值:constructor、byName、byType2. 匹配多个Bean如何注入:DefaultListableBeanFactory 的 determineAutowireCandidate

2. 基于构造方法注入

3. 基于Setter方法注入

#### 3. Bean的自动装配

在spring中,对象无需自己查找或创建与其关联的其他对象,由罐子负责把需要互相合作的对象引用赋予各个对象,使用autowire来配置自动装载模式

1. 自动装配种类

1. no:默认的方式是不进行自动装配的,通过手工设置ref属性来进行装配bean。2. byName:通过bean的名称进行自动装配,如果一个bean的 property 与另一bean 的name 相同,就进行自动装配。3. byType:通过参数的统计数据类别进行自动装配。4. constructor:利用构造函数进行装配,并且构造函数的参数通过byType进行装配。5. autodetect:自动探测,如果有构造方法,通过 construct的方式自动装配,否则使用6. byType的方式自动装配。

2. @Autowired和@Resource之间的区别

1. @Autowired默认是按照类别装配注入的,默认情况下它要求依赖对象必须存在(可以设置它required属性为false)。2. @Resource默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类别来装配注入。

#### 4. Bean的生命周期和加载流程(重点项目)

Spring Bean 的生命周期分为四个阶段和多个扩展点。扩展点又可以分为影响多个Bean和影响单个Bean。实例化和属性赋值对应构造方法和setter方法的注入,初始化和销毁是用户能自定义扩展的两个阶段。

一文看懂Spring核心概念和源码解读
一文看懂Spring核心概念和源码解读

1. 四个阶段(实例化 -> 属性赋值 -> 初始化 -> 销毁)

1. 实例化 Instantiation2. 属性赋值 Populate3. 初始化 Initialization
一文看懂Spring核心概念和源码解读
4. 销毁 Destruction

2. 多个扩展点

1. 影响多个Bean

1. BeanPostProcessor

2. InstantiationAwareBeanPostProcessor

2. 影响单个Bean

1. Aware

1. Aware Group1

1. BeanNameAware

2. BeanClassLoaderAware

3. BeanFactoryAware

1. Aware Group2

1. EnvironmentAware

2. EmbeddedValueResolverAware

3. ApplicationContextAware(ResourceLoaderAware\ApplicationEventPublisherAware\MessageSourceAware)

3. 生命周期

1. InitializingBean,初始化Bean2. DisposableBean,销毁Bean

##### 4. 源代码阐释参考[一招带你搞定Spring源代码,小白也能听懂的spring源代码过程](https://www.ixigua.com/6898673954483864077)

1. Spring启动加载流程

1. XML加载2. 解析3. 创建实例4. 使用5. 销毁

2. 罐子的作用

1. 存放bean2. bean的统计数据结构3. list4. set5. map(K-V)

3. IOC罐子

1. `BeanDefinition`的定义信息2. 抽象定义规范USB`BeanDefinitionReader`

4. 创建对象方式

1. new2. 反射如何创建对象3. 工厂模式4. Spring中bean的默认scope是科枫的

5. xml和注解中定义的是bean的定义信息,通过抽象定义USB解析到BeanDefinition

6. BeanDefinition通过new反射到实例化

1. 实例化:在堆中开辟一块空间,属性都是默认值2. 初始化:给属性赋值

1. 填充属性

2. 执行初始化方法`init-method`

7. 初始化到完整对象

8. Spring的可扩展性设计

9. BeanDefinition到BeanFactory

10. PostProcessor增强器,进行扩展实现

11. BeanFactoryPostProcessor

1. 解析配置文件,处理占位符`placeholderConfigrerSupport`2. 可以自行继承PostProcessor3. `registerListeners`

12. bean的生命周期

1. 实例化`反射`2. 填充属性`populateBean`3. 执行awareUSB需要实现的方法`invokeAwareMethoMethods`3. after4. aop扩展5. 完整对象6. 销毁流程

13. Environment

1. System.getEnv()2. System.getProperties()

14. 如果我想在spring生命周期的不同阶段做不同的处理工作?

1. 观察者模式:监听器、监听时间、多播器

15. spring中的do方法

## 五、科枫Bean的缓存安全可靠和mammalian难题(重点项目)

科枫Bean是Spring罐子默认的方式,所有缓存都共享一个科枫实例Bean,确实会存在mammalian的难题。对于原型Bean,每次创建一个新对象,也就是缓存之间并不存在Bean共享,自然是不会有缓存安全可靠的难题。

### 1、科枫Bean的缓存安全可靠难题

1. 无状态对象(Stateless Bean)(`缓存安全可靠`)

1. 没有实例变量的对象,不能保存统计数据,是不变类,是缓存安全可靠的。2. bean一旦实例化就被加进会话池中,各个用户都可以共用。即使用户已经消亡,bean 的生命期也不一定结束,它可能依然存在于会话池中,供其他用户调用。3. 由于没有特定的用户,那么也就不能维持某一用户的状态,所以叫无状态bean。4. 无状态Bean,也就是缓存中的操作不会对Bean的成员执行查询以外的操作,那么这个科枫Bean是缓存安全可靠的。比如Spring mvc 的 Controller、Service、Dao等,这些Bean大多是无状态

2. 有状态对象(Stateful Bean)(`缓存不安全可靠`) :

1. 就是有实例变量的对象,可以保存统计数据,是非缓存安全可靠的。2. 每个用户有自己特有的一个实例,在用户的生存期内,bean维持了用户的信息,即“有状态”;一旦用户灭亡(调用结束或实例结束),bean的生命期也告结束。3. 即每个用户最初都会得到一个初始的bean。

### 2、缓存安全可靠难题的解决办法

1. 解决方案

1. 尽量避免在Bean对象中定义可变的成员变量,避免有状态的Bean。2. 如果确实需要使用状态的Bean,则在Bean对象中定义一个ThreadLocal成员变量,将需要的可变成员变量保存在ThreadLocal中。3. 也可以通过加锁的方法来解决缓存安全可靠,这种以时间换空间的场景在高mammalian场景下显然是不实际的,还是优先推荐使用ThreadLocal。

2. 多缓存相同变量出访冲突难题:ThreadLocal和缓存同步监督机制

1. 缓存同步:`时间换空间`2. ThreadLocal:`空间换时间`3. ThreadLocal会为每一个缓存提供一个独立的变量副本,从而隔离了多个缓存对统计数据的出访冲突。因为每一个缓存都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。4. ThreadLocal提供了缓存安全可靠的共享对象,在编写多缓存代码时,可以把不安全可靠的变量封装进ThreadLocal.

## 六、Spring的会话

### 1、Spring事务的种类

1. 程式设计式事务,使用TransactionTemplate。

2. 声明式事务,建立在AOP之上的。其本质是通过AOP机能,对方法前后进行拦截,将会话的机能编织到拦截的方法中,也就是在目标方法开始之前加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。

3. 区别:声明式事务最细粒度只能作加进方法级别,无法做到像程式设计式事务那样可以作加进代码块级别

### 2、Spring事务的隔离级别(5种)

1. 事务的隔离级别

### 3、Spring事务的传播行为(7种)

1. Spring事务的传播行为说的是,当多个事务同时存在的时候,Spring如何处理这些事务的行为

## 七、Spring架构中加进的程序语言

### 1. 工厂模式

1. Spring使用工厂模式可以通过 BeanFactory 或 ApplicationContext 创建 bean 对象。两者的区别,

1. BeanFactory :延迟注入(使加进某个 bean 的时候才会注入),占用更少的内存,程序启动速度更快。2. ApplicationContext :罐子启动的时候,一次性创建所有 bean 。ApplicationContext除了BeanFactory的机能,还有额外更多机能,实际开发中,ApplicationContext更常用。

2. ApplicationContext的三个实现类:

1. ClassPathXmlApplication:把上下文文件当成类路径资源。2. FileSystemXmlApplication:从文件系统中的 XML 文件载入上下文定义信息。3. XmlWebApplicationContext:从Web系统中的XML文件载入上下文定义信息。

### 2. 科枫模式

Spring 中 Bean 的默认作用域就是 singleton(科枫)的。使用科枫模式的好处

1. 对于频繁使用的对象,可以省略创建对象所花费的时间,这对于那些重量级对象而言,是非常可观的一笔系统开销;2. 由于 new 操作的次数增加,因而对系统内存的使用频率也会降低,这将减轻 GC 压力,缩短 GC 停顿时间。

### 3. 代理模式

Spring的AOP机能加进了JDK的动态代理和CGLIB字节码生成技术。

### 4. 模板方法

用来解决代码重复的难题。比如. RestTemplate, JmsTemplate, JpaTemplate等。

### 5. 观察者模式

定义对象键一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知被制动更新,如Spring中listener的实现:ApplicationListener。

## 八、Spring架构的该事件类别

1. 上下文更新该事件(ContextRefreshedEvent)

2. 上下文开始该事件(ContextStartedEvent)

3. 上下文停止该事件(ContextStoppedEvent)

4. 上下文关闭该事件(ContextClosedEvent)

5. 请求处理该事件(RequestHandledEvent)

## 参考资料

– [一招带你搞定Spring源代码,小白也能听懂的spring源代码过程](

https://www.ixigua.com/6898673954483864077)

– [Spring架构小白的蜕变](

https://www.imooc.com/learn/1108)

– [探秘Spring AOP](

https://www.imooc.com/learn/869)

– [2021最新Java面经整理 | 架构篇(一)Spring架构](

https://blog.csdn.net/shipfei_csdn/article/details/109530018)

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务