Spring
spring简介
spring是一个轻量级的(核心jar包小),非侵入式的一站式(指同时拥有数据持久层,web层,服务层)为了简化企业级开发的框架,
spring的核心是IOC,AOP
IOC: IOC 容器是具有依赖注入功能的容器,负责对象的实例化、对象的初始化,对 象和对象之间依赖关系配置、对象的销毁、对外提供对象的查找等操作,对象 的整个生命周期都是由容器来控制。我们需要使用的对象都由 ioc 容器进行管 理,不需要我们再去手动通过 new 的方式去创建对象,由 ioc 容器直接帮我 们组装好,当我们需要使用的时候直接从 ioc 容器中直接获取就可以了。
AOP: 面向切面编程(是对面向对象编程的补充,不是spring特有), 通过一个代理对象(代理模式),在不修改原来代码的情况下,对目标类进行功能的增强,使得类与类之间的耦合度降低了. 简化了开发步骤.
BeanFactory 和 ApplicationContext
BeanFactory 和 ApplicationContext都是接口
BeanFactory 接口是spring框架的顶层的接口,用来定义如何获取bean,判断等功能.
DefaultListableBeanFactory实现BeanFactory 接口,是主要的创建bean的工厂类.
ApplicationContext 接口间接的继承BeanFactory 接口,并且扩展一些新的功能.
区别
BeanFactory 面向spring框架,比较底层
ApplicationContext 由于又实现许多的接口,增加了额外的功能
实现了BeanFactory接口的工厂,是懒加载,获取bean时才会创建对象.
实现了ApplicationContext 接口的工厂,是在启动时加载所有的类,创建对象.
SpringBean的生命周期
什么是bean
Spring Framework 的官方文档翻译一下:
在Spring中,构成应用程序骨干并由Spring IoC容器管理的对象称为bean。bean是由Spring IoC容器实例化、组装和管理的对象。
bean 是由 Spring IoC 容器实例化、组装和管理的对象。
生命周期:
对于普通的 Java 对象,当创建对象后该对象就能够使用了。一旦该对象不再被使用,则由 Java 自动进行垃圾回收。而 Spring 中的对象是 bean,bean 和普通的 Java 对象没啥大的区别,只不过 Spring 不再自己去 new 对象了,而是由 IOC 容器去帮助我们实例化对象并且管理它,我们需要哪个对象,去问 IOC 容器要即可。IOC 其实就是解决对象之间的耦合问题,Spring Bean 的生命周期完全由容器控制。
Bean 的生命周期
这里我们说的 Spring Bean 的生命周期主要指的是 singleton bean(单例bean),对于 prototype 的 bean(原型bean) ,Spring 在创建好交给使用者之后则不会再管理后续的生命周期。
我们也来复习下 Spring 中的 bean 的作用域有哪些?
singleton : 唯一 bean 实例,Spring 中的 bean 默认都是单例的。
prototype : 每次请求都会创建一个新的 bean 实例。
request : 每一次 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 request 内有效。
session : 每一次 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 session 内有效。
而对于 Spring Bean 的生命周期来说有以下四个过程:
- 实例化 Instantiation
- 属性赋值 Populate
- 初始化 Initialization
- 销毁 Destruction(是在容器关闭时调用的)
细化
1.instantiate bean 对象实例化
2.populate properties 属性赋值
3.1 如果 Bean 实现 BeanNameAware 执行 setBeanName
3.2 如果 Bean 实现 BeanFactoryAware 或者 ApplicationContextAware 设 置工厂 setBeanFactory 或者上下文对象 setApplicationContext 对象. 初始化 .........
3.3 如果存在类实现 BeanPostProcessor(AOP) ,执行 postProcessBeforeInitialization
3.4 如果 Bean 实现 InitializingBean 执行 afterPropertiesSet 如果配置了自己的初始化方法<bean init-method="init"> 则执行自己写的初始化方法
3.5 如果存在类实现 BeanPostProcessor(AOP) ,执行 postProcessAfterInitialization
4.完整的 bean 创建好,将 bean 对象放入到容器中,可以使用
5.销毁 如果 Bean 实现 DisposableBean 执行 destroy 如果配置了自己的销毁方法<bean destroy-method="customerDestroy"> 指定销毁方法 customerDestroy
Spring 中的bean 是线程安全的吗?
结论: 不是线程安全的
Spring容器中的Bean是否线程安全,容器本身并没有提供Bean的线程安全策略,因此可以说Spring容器中的Bean本身不具备线程安全的特性,但是具体还是要结合具体scope(作用域)单例与原型Bean分别进行说明。
原型Bean
对于原型Bean,每次请求都会创建一个新对象,也就是线程之间并不存在Bean共享,自然是不会有线程安全的问题。
单例Bean
对于单例Bean,所有线程都共享一个单例实例Bean,因此是存在资源的竞争。
如果单例Bean,是一个无状态Bean(有状态,可以用来存储数据的;无状态的: 没有存储数据 Service,Dao 层只是方法调用 ),也就是线程中的操作不会对Bean的成员执行查询以外的操作,那么这个单例Bean是线程安全的。比如Spring mvc 的 Controller、Service、Dao等,这些Bean大多是无状态的。
springBean循环依赖问题
但是循环依赖在spring中 就会出现问题, spring中并不是简单的new出对象,而是经过bean的生命周期。在bean的依赖注入阶段A需要注入B,由于B还没有被创建,要先去创建B,但是B中又需要注入A,A又因为无法注入B而无法完成创建(有点类似死锁)就卡在了这里,无法进行。
spring解决循环依赖问题
spring运用三级缓存解决该问题
singletonObjects: 一级缓存,用于保存实例化、注入、初始化完成的 bean.实例earlySingletonObjects: 二级缓存,用于保存实例化完成的 bean 实例,提前曝露对象.singletonFactories: 三级缓存,用于保存创建 bean 的工厂对象
当A中需要B时, 那么先从A会从一级缓存中去找B,如果没有,然后到二级缓存中找B,也没有,就去三级缓存中,找到B对应的工厂,创建出B对象(原始对象,半成品)把B对象放到了二级缓存中,将三级缓存中的工厂对象删除。然后完成A的创建后再去依赖注入完成B的创建。创建完成后会将A,B放入一级缓存。
Servlet 的过滤器与 Spring 拦截器区别
过滤器 Filter 是在请求进入容器后,但在进入 servlet 之前进行预处理,需要服务器来进行控制。
spring常见注解
springBoot自动装配
在springboot程序启动时,spring是如何知道应该加载哪些组件,不应该加载哪些组件?
在@EnableAutoConfiguration 中有一个 @Import({AutoConfigurationImportSelector.class})注解,其中包含 AutoConfigurationImportSelector 类. AutoConfigurationImportSelector导入并选择需要加载组件,读取 meta-info/spring.factories 文件中所有组件的自动配置类,只需加载我们在pom.xml中配置的组件配置类,把meta-info/spring.factories多余的组件剔除
AutoConfigurationImportSelector 类中关键方法,