目录
7、BeanFactoryPostProcessor和BeanPostProcessor区别
7.1、BeanFactoryPostProcessor(修改配置)
8、BeanFactory和ApplicationContext区别
1、Bean生命周期
可分8个阶段。实例化 ---->属性赋值---->初始化前---->初始化---->初始化后---->使用---->销毁前---->销毁。
(1)实例化
- --对于BeanFactory容器(懒加载),用户请求一个未初始化bean时,容器会调用createBean进行实例化;
- --对于ApplicationContext容器(预加载),容器启动结束后,自动获取BeanDefinition对象中的信息,实例化所有bean。
(2)属性赋值
Spring将 配置 或 注解 中定义的属性值赋值给Bean的响应属性。也叫设置对象属性和依赖注入(通过构造方法注入、setter方法注入等方式实现)。
(3)初始化前 回调(如有定义):属性赋值完成后Spring调用初始化前回调方法,如处理Aware接口,以便拿到Spring容器的资源
(4)初始化:如果Spring在配置文件配置了 init-method 属性,会自动调用它配置的初始化方法。
(5)初始化后 回调(如有定义):实现InitialzingBean接口,并实现afterPropertiesSet()方法。
(6)使用:初始化所有流程结束,Bean可以被使用,即可执行业务逻辑。
(7)销毁前 回调(如有定义):例如实现DisposableBean接口的destroy()方法
(8)销毁:在销毁前回调之后,Spring刚好执行额外的销毁操作,如调用Bean的destroy-method属性指定的销毁方法
2、Bean加载流程
Spring IoC像流水线上的机器,Bean像产品。既然要生产产品,机器要先运行。所以:
Bean的加载可分为2个阶段:Spring容器启动阶段、Bean获取阶段。
2.1、容器启动阶段(Spring容器启动流程)
(注:注意分清一个是bean加载流程一个是bean启动流程)
可以归纳为3个步骤:
(1)初始化Spring容器
加载配置元信息,通过BeanDefinitionReader读取器读取不同配置元信息,将这些元信息bean处理成Spring可以理解的BeanDefinition对象并注册到BeanDefinationRegistry。
(2)实例化bean对象
通过BeanFactory工厂,从BeanDefinationRegistry键值对拿到BeanDefinition,用来生成Bean对象(常用的实现类是XmlBeanFactory )
(3)注册bean后置处理器
通过BeanFactoryPostProcessor工厂获取的BeanPostProcessor后置处理器对bean增强或者修改
2.2、Bean的获取阶段
对象懒加载:直到对象实例化之前都是以BeanDefinationRegistry中的一个个的BeanDefination形式存在,Spring只有在第一次依赖对象的时候才开启实例化。
对象预加载:容器启动阶段完成后有一个步骤finishBeanFactoryInitialization(),在这一步将立即启动Bean的实例化阶段,调用所有依赖对象getBean实例化所有配置的Bean,完成类的加载
(1)doGetBean()获取
在创建Bean对象之前先去缓存或者BeanFactory查看是否存在Bean, 存在则返回,不存在则进行创建爱Bean流程。
(2)getSingleton()从缓存获取单例Bean
Bean默认单例在容器中只会被创建一次,后续获取从单例缓存拿。单例缓存是公共变量,每次对他操作都要上锁。
(3)getObjectForBeanInstance()从Bean的实例中获取
2.3、Bean的实例化阶段
(1)加载类:通过类加载器,加载bean到内存。
(2)创建bean实例:类加载到内存后,JVM虚拟机通过有参或无参构造方法创建实例。
(3)分配内存:JVM为bean分配内存,内存可以装属性和方法
(4)属性赋值:初始化属性,包括使用默认值或者构造方法参数进行赋值
(5)执行构造方法:JVM调用构造方法进行额外的初始化操作,包括初始化依赖对象等
(6)返回实例:JVM返回已经实例化的bean对象
3、Bean 作用域(scope)
(1)singleton: 单例bean,每个容器只有一个bean实例(默认)-------线程不安全
(2)prototype: 为每一个bean请求创建一个实例 ------线程安全(线程之间不存在bean共享)
(3)request:为每一个request请求创建一个实例,请求结束bean失效且被垃圾回收
(4)session: 同一个session会话共享一个实例,不同会话使用不同实例
(5)global-session: 全局作用于,所有会话共享一个实例
4、Bean(Spring) 装配
指的是Spring框架中将组件bean组装在一起的过程
4.1、bean装配方式
(1)xml配置:xml配置文件使用<bean>定义bean
(2)注解配置:如@Component、@Service声明Bean,使用@Autowired进行自动装配
(3)java配置类:如@Configuration注解配置类,@Bean注解来定义Bean,并使用@Autowired进行自动装配
4.2、bean自动装配的几种方式
(1)byName自动装配:Spring会自动装配与属性名相同的Bean
(2)byType自动装配:Spring会自动装配与属性类型相同的Bean
(3)构造函数自动装配
(4)@Autowired、@Resource注解自动装配
4.3、@Autowied和@Resource区别
(1)来源不同:@Autowied由Spring提供,@Resource由SDK提供,如果不使用Spring框架只能用@Resource
(2)装配方式不同:@Autowied默认按type装配,@Resource默认按name装配
(3)装配顺序不同:@Autowied默认先按byType匹配,如果发现找到多个bean又按byName匹配,如果还有多个则抛出异常;@Resource默认byName查找,找不到再byType
(4)依赖注入支持不同(3种方式),@Autowied支持属性注入、构造方法注入、Setter注入。而@Resource只支持属性注入和Setter注入
5、Bean 延迟加载
指在Spring容器启动时不立即初始化Bean,而是在需要使用该Bean时才进行初始化。可使用@Lazy注解作用在类上,那这个类不会在Spring容器启动时立马加载,而是在用到时再初始化这个类bean到容器。
6、Bean 依赖注入
参考:深入理解Spring:AOP和IOC中-依赖注入的几种方式
7、BeanFactoryPostProcessor和BeanPostProcessor区别
7.1、BeanFactoryPostProcessor(修改配置)
在Spring容器加载Bean的定义后,在Bean实例化之前执行的。允许对Bean定义进行修改,如修改Bean的属性值等操作
7.2、BeanPostProcessor(实时处理)
在Spring容器实例化Bean之后,在Bean的初始化方法之前执行的。允许对Bean实例进行实时处理,如AOP代理的创建、事物管理、资源处理。
8、BeanFactory和ApplicationContext区别
(1)加载方式区别
BeanFactory是延时加载(懒加载)机制,容器启动时不会加载bean,要用时才加载并实例化,所以无法提前发现spring存在的配置问题;
ApplicationContext是容器启动时一次性加载所有bean。
(2)功能区别
BeanFactory是Spring中最底层的接口,是IOC的核心,其功能包含了各种Bean的定义、加载、实例化、依赖注入和生命周期的管理;
ApplicationContext接口是BeanFactory的子类,具有BeanFactory所有的功能,额外支持国际化、资源文件访问等。
9、Bean 线程安全保障
默认单例bean不是线程安全的(大多数据时候bean是无状态的如dao所以线程安全,有状态则必须手动保障线程安全了如自定义model实体)
(1)使用线程安全的数据结构
如ConcurrentHashMap
(2)避免共享状态
如果需要存储状态,可以使用ThreadLocal来保障每个线程拥有独立的状态
(3)使用同步机制
在需要保障线程安全的方法或代码块中,使用synchronized关或者ReentrantLock
(4)使用原子操作
(5)使用线程安全的作用域。如prototype