文章目录
Spring 常用注解: https://blog.csdn.net/xyc1211/article/details/119318980
Spring Core
IOC原理
- 思想
把所有对象都当做Bean, 放在一个容器里管理
通过配置 Bean 及 Bean 之间的依赖关系,
然后利用 Java 语言的反射功能实例化 Bean 并建立 Bean 之间的依赖关系。
- 原理
Spring 启动时读取应用程序提供的 Bean 配置信息,并在 Spring 容器中生成一份相应的 Bean 配
置注册表 BeanDefinitionRegistry ,然后根据这张注册表实例化 Bean,装配好 Bean 之间的依赖关系,为上层应用提供准
备就绪的运行环境。其中 Bean 缓存池为 HashMap 实现
Spring Bean 生命周期
- Bean 容器找到配置文件中 Spring Bean 的定义。
- Bean 容器利用 Java Reflection API 创建一个Bean的实例。
- 如果涉及到一些属性值 利用
set()
方法设置一些属性值。 - *.Aware接口实现方法调用, 让bean能够感知获取到自己的一些属性
- 如果 Bean 实现了 BeanNameAware 接口,调用 setBeanName()方法,传入Bean的名字。Bean就能获取自己的名字
- 如果 Bean 实现了 BeanClassLoaderAware 接口,调用 setBeanClassLoader()方法,传入 ClassLoader对象的实例。Bean就能获取自己的ClassLoader对象实例
- … …如果实现了其他 *.Aware接口,就调用相应的方法。
- 如果有和加载这个 Bean 的 Spring 容器相关的 BeanPostProcessor 对象,执行postProcessBeforeInitialization() 方法
- 如果Bean实现了InitializingBean接口,执行afterPropertiesSet()方法。
- 如果 Bean 在配置文件中的定义包含 init-method 属性,执行指定的方法。
- 如果有和加载这个 Bean的 Spring 容器相关的 BeanPostProcessor 对象,执行postProcessAfterInitialization() 方法
- 当要销毁 Bean 的时候,如果 Bean 实现了 DisposableBean 接口,执行 destroy() 方法。
- 当要销毁 Bean 的时候,如果 Bean 在配置文件中的定义包含 destroy-method 属性,执行指定的方法。
bean配置源
- 在XMl中进行显示配置
- 在Java中进行显示配置
- 隐式的bean发现机制和自动装配
- *组件扫描(component scanning):Spring会自动发现应用上下文中所创建的bean。
- *自动装配(autowiring):Spring自动满足bean之间的依赖。
注册管理Bean : BeanFactory
bean容器的基本接口, 注册管理所有Bean的一个工厂
BeanFactory
- ListableBeanFactory
- HierarchicalBeanFactor
- ConfigurableBeanFactory
- AutowireCapableBeanFactory
-
ApplicationContext
面向开发- ApplicationContext常用实现类:
- ClassPathXmlApplicationContext
从类路径下的xml配置文件中加载 bean配置 - FileSystemXmlApplicationContext
从系统盘符中的xml配置文件中加载 bean配置 - AnnotationConfigApplicationContext
从java的配置类中的java注解加载 bean配置 - AnnotationConfigWebApplicationContext
从java的配置类中的java注解加载 bean配置,专门为web应用准备的 - XmlWebApplicationContext
从web应用下的xml配置文件加载 bean配置
- ClassPathXmlApplicationContext
- ApplicationContext常用实现类:
-
WebApplicationContext
面向Web开发
从相对于 Web 根目录的路径中装载配置文件完成初始化, 可以获得ServletContext 的引用
实例化Bean: FactoryBean
-
默认实现方式
通过反射机制,利用<bean>的class属性指定实现类实例化Bean -
问题
在某些情况下实例化Bean过程比较复杂,如果按照传统的方式,则需要在中提供大量的配置信息。配置方式的灵活性是受限的 -
解决方案
采用编码的方式可能会得到一个简单的方案。
Spring为此提供了一个org.springframework.bean.factory.FactoryBean的工厂类接口,
可以通过实现该接口定制实例化Bean的逻辑。
FactoryBean接口对于Spring框架来说占用重要的地位,
Spring自身就提供了70多个FactoryBean的实现
Spring Bean 作用域
- singleton(单例)
唯一 bean 实例,bean 默认都是单例的。多线程下不安全- bean线程安全常见的有两种解决办法:
- 在Bean对象中尽量避免定义可变的成员变量(不太现实)。
- 在类中定义一个ThreadLocal成员变量,将需要的可变成员变量保存在 ThreadLocal 中(推荐的一种方式)。
- bean线程安全常见的有两种解决办法:
- prototype(原型)
每次请求都会创建一个新的 bean 实例。 - request(http)
一次 Http 请求中,容器会返回该 Bean 的同一实例 - session (http)
在一次 Http Session 中,容器会返回该 Bean 的同一实例 - global session(http)
在一个全局的 Http Session 中,容器会返回该 Bean 的同一个实例。
基于portlet的web应用中才有意义, Spring5取消
DI 依赖注入
都是通过 方法 或 属性反射 注入
- 构造器方法 支持注解+xml
- setter方法 支持注解+xml
- 静态工厂方法 只支持xml
- 实例工厂方法 只支持xml,需要首先new工厂类
- 自动装配
- byName
- byType
- 构造函数自动装配(与byType非常相似)
循环依赖问题
https://blog.csdn.net/hollis_chuang/article/details/114504849
https://blog.csdn.net/a745233700/article/details/110914620
-
三种循环依赖
第一种情况:自己依赖自己的直接依赖
第二种情况:两个对象之间的直接依赖
第三种情况:多个对象之间的间接依赖 -
五种循环依赖场景
bean获取原理过程
解决思路:先实例化双方(不注入),再相互注入依赖,最后初始化
只有 单例对象 通过setter循环依赖 的场景, 可以通过 三级缓存 解决
构造器循环依赖 创建实例时就要注入【不能解决】
多实例循环依赖 没有用缓存,每次都会生成一个新对象【不能解决】
dependsOn的实例 如果有循环依赖则抛异常【不能解决】
- 单例, setter依赖
@Service
public class TestService1 {
@Autowired
private TestService2 testService2;
public void test1() {
}
}
@Service
public class TestService2 {
@Autowired
private TestService1 testService1;
public void test2() {
}
}
bean仓库 三级缓存:
相互依赖只要二级缓存就能解决
因为bean处理器 还包含AOP处理器,初始化后 还要创建proxy代理对象 所以需要三级缓存
- singletonObjects 一级缓存,保存
初始化完成 的bean实例
- earlySingletonObjects 二级缓存,保存
实例化完成 的bean实例
- singletonFactories 三级缓存,保存
bean创建工厂
Spring APO 原理
JDKProxy 和 Cglib代理
JDKProxy
只能代理 实现了接口的类
Cglib
可以代理 未实现任何接口的类
Spring MVC 原理
WEB服务器把 客户端Http 请求全转给 控制器 DispatcherServlet
DispatcherServlet 根据请求寻找处理器 Controller
Controller处理后返回ModelAndView
给客户端