自动装配
自动装配关心的是解析bean之间的依赖关系
依赖注入
引用的对象不需要自己负责创建或查找所依赖的对象,而是通过外部系统(如Spring容器)来提供依赖的实例。它将对象与其依赖解耦,使得对象更加可重用
依赖注入是通过IoC(Inversion of Control,控制反转)容器实现的
依赖注入的方式
构造函数注入
字段注入
区别:
- 字段注入将依赖直接注入到目标类的字段上,而构造函数注入将依赖注入到目标类的构造函数的参数中。
- 字段注入可以在任何时候发生,包括在目标类实例化之前。而构造函数注入要求在实例化目标类时立即注入依赖,确保对象在创建后即可使用。
AOP名词
切点 :需要被拦截的方法
切面 :用于增强的切面类
配置拦截表达式
创建代理对象:当应用程序启动时,Spring AOP 会为切点所在的类创建代理对象。代理对象包含了切面的逻辑,并在切点执行时拦截并执行相关通知。
当程序执行到切点时,代理对象会拦截方法调用,并按照切面定义的通知顺序执行相应的逻辑(前置通知、后置通知、异常通知等)
一Spring功能特性
spring 5开始要求jdk8
1核心特性
- IoC容器 (IoC Container)
- spring 事件 (Events)
- 资源管理 (Resources)
- 国际化 (il8n)
- 校验 (Validation)
- 数据绑定 (Data Binding)
- 类型转换 (Type Conversion)
- spring 表达式
- 面向切面编程
Spring Framework 有哪些核心模块?
- spring-core: Spring 基础 API模块,如资源管理,泛型处理
- spring-beans: Spring Bean 相关,如依赖查找,依赖注入
- spring-aop : Spring AOP 处理,如动态代理,AOP 字节码提升
- spring-context :事件驱动、注解驱动,模块驱动等
- spring-expression: Spring 表达式语言模块
- spring-aspects 是对aspect的支持
- spring-jcl 统一日志。
- spring-jms 消息中间件
- spring-web
- spring-webflux
- spring-webmvc
- spring-websocket
- 上面四个是web模块
只需要依赖需要的模块即可
2数据存储
3web技术
4框架整合与测试
spring编程模型
面向对象编程
契约接口:Aware、BeanPostProcessor
设计模式:观察者模式、组合模式、模板模式
对象继承:Abstract* 类
面向切面编程
动态代理: JdkDynamicAopProxy
字节码提升:ASM、CGLib、Aspectu...
面向模块编程
Maven Artifacts
OSGI Bundles
Java 9 Automatic Modult
Spring @Enable* 注解
面向函数编程
Lambda
面向元编程
注解:模式注解 (@Component、@Service、 @Respository ..)
配置:Environment 抽象、Property Sources、 BeanDefinition
泛型:Generic TypeResolver、ResolvableType ..
函数驱动
函数接口:ApplicationEventPublisher
Reactive: Spring WebFlux
模块驱动
Maven Artifacts
OSGI Bundles
Java 9 Automatic Modules
Spring @Enable*
spring设计模式
观察者
spring event事件
通过事件的方式让,监听器回调
组合
模版方法
jdbcTempla te
Ioc 主要实现策略
依赖注入构造器。setter,参数、接口、
Ioc 容器的职责
通用职责
- 依赖处理: 依赖查找 、 依赖注入
- 生命周期管理: 容器、托管的资源 (Java Beans 或其他资源)
- 配置: 容器、外部化配置、托管的资源 (Java Beans 或其他资源)
先了解Spring大致需要做哪些事?
一、把xml或者注解也可以是Json能描述Bean信息的文件读取
对此类统一的读取可以抽象一层Bean读取接口
二、 就是应该用什么来存对象,那就用Map容器。
用对象的名字当key,对象当value
三、根据bean的描述来创建Bean对象用什么方式,可以用反射
四、bean有些对象的属性该怎么填充,特殊的可以用Bean初始化(innit)初始化方法,像是普通属的可以set方式填充。
五、在引入扩展的时候(bean描述到Bean工厂之前)应该有一些后置处理器做扩展BeanFactoryPostProcessor可以有一堆可以没有。在这里可以做 比如${}里的内容做替换的事情
注:bean描述到bean工厂之后,实例化对象开始就属于Bean的生命周期了
补充下Bean的生命周期:实例化对象、普通的属性填充、执行aware回调方法、对BeanAop代理增强before 、特殊的属性填充用户自定义的init、增强after、销毁。
补充下BeanPostProcessor是AOP增强用的有before和after两个方法(源码里默认有JDK和CGlilb两种代理)、BeanFactoryPostProcessor是bean描述提交给bean工厂之间的扩展。
补充下:Environment接口,能在程序运行期间获得系统环境变量/属性。
补充下:观察者模式:能在spring生命周期不同阶段做不同的处理工作。观察者模式(监听器、监听事件、广播器)
补充下:Spring的重要方法:reflash,reflash包含了13个方法
refresh方法里的13个方法是Spring核心逻辑
一、prepareRefresh:刷新前的准备工作:设置容器启动时间、设置容器关闭、激活标志位、记录日志、创建监听器集合、创建刷新前的监听事件集合
二、创建Bean工厂、加载配置文件、执行beanFactoryPostProcessor方法、注册beanFactoryPostProcessor方法、初始化事件监听多路广播器、
工厂:实例化所有非懒加载的单例Bean、create创建Bean(里面通过clazz对象反射获取构造器,构造器对象来创建对象 )
对bean的属性填充,会递归初始化依赖的Bean、然后是特殊的属性填充:执行init方法
执行aware方法、beanPostprocessor的before方法、用户自定义init、beanPostprocessor的after方法
三级缓存?
DefaultSingletonRegistry类里面
二级缓存Map:earlySingletonObjects
三级缓存Map< ,ObjectFactory<?>>:singletonFactories。ObjectFactory<T>是函数式接口可以传入lambda表达式/匿名类接口。通过调用getObject方法执行具体逻辑
一级缓存ConcurrentHashMap:singletonObjects
解决循环依赖的关键在于,实例化和初始化分开
只用一级缓存不能解决循环依赖,如果只用一级缓存,成品与半成品都放在了一级缓存,取到半成品的话是不能使用的,所以要把半成品与成品分开存放。
为什么要三级缓存,二级行不行
如果保证所有的Bean都不调用getEarlyBeanReference表达式,只使用二级没问题
getEarlyBeanReference方法干什么的,为了循环依赖的同时还要AOP的
这个方法会遍历所有的BeanPostProcessor增强接口,如果需要代理,返回是代理对象。
通过函数式接口调用的时候包裹原来的对象就会返回代理对象
三级缓存放lambda表达式调用的时候覆盖原对象的引用返回代理对象。
初始化设置属性的三种方式?
一、set重点:可以解决循环依赖的问题 (先有的对象,在给对象属性赋值)
二、构造方法:不能解决循环依赖(找不到对象,对象没有事先存在、不能返回对象的引用赋值)懒加载应该可以解决
三、工厂方法(不重要)
创建Bean的相关方法
getBean-> doGetBean->createBean->doGreateBean
getBean先去一级缓存查找
三级缓存value是函数式接口里面的getObject方法写的时候就是调用createBean方法。
这个lambda表达式在调用getObject时才会执行
找对象有没有的时候是先看一级缓存有没有,在看二级,在看三级缓存
一级缓存放初始化好的对象
二级缓存放半成品对象
三级缓存放lambda表达式
在二级放入后应该给三级缓存K/V删除
同样,一级缓存放入对象后也给二级缓存删掉
对Spring的理解?
大范围->小细节
Spring用来存储管理Bean对象。从创建Bean对象到Bean的销毁都由Bean来管理。
Bean的描述可以从配置文件,或者注解方式。
把Bean的描述,封装成Bean Definition。
解析Bean Definition。
反射创建对象。
初始化对象。
对beanAOP增强。
Spring框架里面有很多map
Bean也是用HashMap存的
配置文件解析?
Bean的注解和XML解析不一样
但是在形成Definition前,会用BeanDefinitionReader统一约束。
BeanDefinition 形成对象,会用反射的方式。反射更灵活。
配置文件的属性替换?
BeanDefinition也是map
BeanDefinition里面的属性值是占位符。
Definition形成对象的时候,具体属性值是什么时候替换的
替换前是用占位符
BeanFactory?
BeanFactorybean容器的根接口
里面的子类实现用反射创建对象