前言
此内容是笔者通过B站的视频总结而来。原视频链接地址:6、Bean Factory与FactoryBean有什么区别_哔哩哔哩_bilibili
1.谈谈springIOC的理解,原理与实现
回答涉及到的点:
控制反转:是一种理论思想,原来的对象是由使用者来进行控制的,有了spring之后,可以把整个对象交给spring来帮助我们进行管理的。
DI:依赖注入,把对应的属性值注入到具体的对象中,在spring的应用:@Autowired,populateBean完成属性值的注入。
源码非常熟悉的时候的回答要涉及的点:
容器:具体存放对象,使用map结构来进行存储的,在spring中一般存在三级缓存,singletonObject存放完成的bean对象,我们一般取对象都会从singletonObject中进行获取。整个bean的生命周期,从创建到销毁的过程,都是由容器来进行管理的,这里可以引出一个bean的生命周期。
1.容器的创建过程,(容器最上层是一个根接口BeanFactory,实际我们用的最多的就是DefaultListableBeanFactory )向beanFactory中进行设置一些参数(BeanPostProcessor,Aware接口的子类)等等属性。
2.加载解析bean对象,准备创建bean对象的定义对象beanDefintion(xml或者注解的解析过程)
3.beanFactoryPostProcessor的处理,这里spring 提供了很多得扩展点,例如,处理占位符得PlaceHolderConfigurationSupport,ConfigurationClassPostProcessor
4,beanFactoryPostProcessor的的注册功能,方便后续对bean对象进行完成的具体的扩展功能
5.通过反射的方式将BeanDefinition对象实例化成具体的bean对象
6.bean对象的初始化过程(填充属性,调用aware子类的方法,调用beanPostProcessor的前置处理方法,调用init-method方法,调用beanPostProcessor的后置处理方法)
7.生成完成的bean对象,通过getBean对象可以直接获取
8.销毁过程
这是我对IOC的整体理解,您看下有什么问题,可以指点我一下。
源码不熟悉的回答方式:
具体的细节 我记不清楚,但是spring的bean都是通过反射来进行生成的,同时包含了很多的扩展点,比如最常用的对BeanFactory的扩展(对占位符号的处理),除此之外,ioc中最核心的也就是填充具体的bean的属性和生命周期()
2.spring IOC的底层实现
回答的时候要涉及一些方法的名字:createBeanFactory,getBean,doGetBean,createBean,doCreateBean,populateBean,initializingBean
1.先通过createBeanFactory创建出来一个Bean工厂(DefaultListableBeanFactory)
2.开始循环创建对象,因为容器中的bean都是单例,所以优先通过getBean,doGetBean方法从容器中进行查找,找不的话,到第3步
3.通过createBean,doCreateBean方法,以反射的方式创建对象,一般情况下使用的是无参的构造方法(getDelcaredConstructor,newInstance)
4.进行对象属性的填充populateBean
5.进行其他的初始化操作(initializingBean)
3.Bean的生命周期
1.实例化bean:通过反射的方式创建bean对象
2.填充bean的属性:populateBean 循环依赖的问题(三级缓存)
3.调用Aware接口的相关方法:invokeAwareMethod(完成BeanName,BeanFactory,BeanClassLoader对象的属性设置)
4.调用BeanPostProcessor的前置方法,使用比较多的有: ApplicationContextPostProcessor 设置ApplicationContext,Environment,ResourceLoader等对象
5.调用initmethod方法,判断是否实现了initialzingBean接口,如果实现了,调用afterPropertiesSet方法,没有则不进行调用
6.调用BeanPostProcessor的后置方法,spring的Aop就是在此处实现的,AbstractAutoProxyCreator
7.获取到完整的对象,可以通过getBean的方式来进行对象的获取
8.销毁流程,判断是否实现了DispoableBean接口,实现了调用destoryMethod方法
4.spring是如何解决循环依赖的问题
循环依赖问题的由来,A依赖B,B依赖A 就是循环依赖,
1.先创建A对象,实例化A对象,此时A对象中的b属性为空,填充属性b
2.从容器中查找B对象,如果找到了,就不会存在循环依赖的问题,找不到B对象,创建B对象,实例化B对象, 此时B对象中的a属性值为空,填充属性a
这样的话就会形成了依赖,但是我们仔细分析会发现,此时的A对象是存在的,但是不是一个完整的状态,只完成了实例化,未完成初始化。那么我们是不是可以把A对象进行提前暴露,让B对象提前引用这个还没有完整的A对象,所以解决问题的核心在于将实例化和初始化分开,这就是解决循环依赖问题的关联。
此时容器中就需要保存对象的两种状态,完成实例化但未完成初始化,完整状态,因为都在容器中进行存储,所以就要使用不同的map结构来进行存储,所以就会有一级缓存和二级缓存,一级缓存中存放的是成品对象,二级缓存中存放的是半成品对象
那为啥会有三级缓存,三级缓存的value类型是一个ObjectFactory,是一个函数式接口,存在意义是保证是在整个容器运行的过程中,只能有一个同名的bean对象。
如果一个对象要被代理的话,会先优先生成一个普通的对象,但普通对象和代理对象是不能同时出现在容器中的,因此当一个对象需要被代理的时候,就需要使用代理对象覆盖之前的普通对象,在实际调用的过程中,是没有办法确定什么时候对象被调用的,所以就要求某个对象被调用的时候,优先判断此对象是否需要被代理,类似一种回调机制的实现,因此传入lamba表达式的时候,通过lamba表达式来执行对象的覆盖过程,getEarlyBeanReference(),
因此所有的bean对象在创建的时候,优先放到三级缓存种,在后续的使用过程中,如果需要被代理则返回代理对象,如果不需要被代理,则直接返回普通对象。
缓存的放置时机和删除时机
三级缓存:createInstance之后 addSingleFactory
二级缓存:第一次从三级缓存中确定对象是代理对象还是普通对象,同时删除三级缓存 getSingleton
一级缓存:生成完整对象之后放到一级缓存,删除二级缓存和三级缓存 addSingleton
5.Bean Factoy和FactoryBean有什么区别
相同点:都是用来创建bean对象的
不同点:使用BeanFactoy创建对象的时候,必须遵循严格的生命流程,如果想要简单的自定义某个对象的创建,同时将创建好的对象将给spring管理,那么就需要实现FactoryBean接口
6.spring用到设计模式
单例模式 bean的创建都是单例
原型模式:指定作用域为prototype
工厂模式:BeanFactory
模板方法模式:postProcessBeanFactory,onRefresh,initPropertyValue
策略模式:xmlBeanDefinitionReader,PropertiesBeanDefinitionReader
观察者模式:listener, event事件
适配器模式:一些以为Adapter
装饰者模式:BeanWrapper
责任链模式:使用aop的时候先生成一个拦截器链
代理模式:动态代理
7.spring的AOP的底层实现原理
aop的概念,应用场景:事务,日志等,实现原理 动态代理
bean的创建过程中有一个步骤可以对bean进行扩展实现,aop本身就是一个扩展功能,所以在beanPostProcessor的后置处理方法中来进行实现
1.代理对象的创建过程,advice,切面,切点
2.通过jdk或者cglib的方式来生成代理对象
3.在执行方法调用的时候,会调用到生成的字节码文件中,直接会找到DynamicAdvisedInterceptor中的intercept方法开始进行执行
8.spring的事务是如何回滚的
问题等同于 spring的事务管理是如何实现的?
spring的事务是由AOP实现的,首先要生成具体的代理对象,按照aop的整套流程来执行具体的操作逻辑,正常情况下是要通过通知来完成核心功能,但是事务不是通过事务来实现的,而是通过TransactionInterceptor来实现的。然后调用invoke来实现具体的逻辑
1.先做准备工作,解析各个方法上事务相关的属性,根据具体的属性,是否开启新的事务,
2.当需要开启的时候,获取数据库链接,关闭自动提交功能,开启事务
3.执行具体的sql操作
4.在操作的过程中,如果执行失败了,那么会通过completeTransactionAfterThrowing来完成事务的回滚操作,回滚的具体逻辑是通过doRollBack方法实现的,实现的逻辑也是先获取连接,通过链接对象来回滚
5.如果执行过程中,没有任何意外情况发生,通过completeTransactionAfterReturning来完成事务的提交操作,提交的具体逻辑是通过doCommit方法实现的,实现的逻辑也是先获取连接,通过链接对象来提交
6.当事务执行完毕之后,需要清除线相关的事务信息 cleanTransationInfo
9.spring事务的传播特性
传播特性有几种?7种
Rquired,Requires_new,nested,support,not_support,never,mandatory
A方法调用B方法,AB方法都有事务,并且传播特性不同,那么A如果有异常的话,B怎么办,B如果有异常,A怎么办?
事务的传播特性是指不同方法的嵌套调用的时候,事务应该如何进行处理,是用同一个事务,还是不同的事务,当出现异常的时候,是回滚还是提交。
1.事务的不同分类 可以分为三类,支持当前事务,不支持当前事务,嵌套事务
2.如果外层方法是required,内层方法是required,requires_new,nested
3.如果外层方法是requires_new,内层方法是required,requires_new,nested
4.如果外层方法是nested,内层方法是required,requires_new,nested