腾讯面试题:Spring
- 1.谈一谈spring IOC的理解,原理与实现?
- 2.谈一谈Spring IOC的底层实现?
- 3.描述下Bean的生命周期
- 4.Spring如何解决循环依赖问题?
- 5.BeanFactory 和FactoryBean有什么区别?
- 6.Spring 中用到哪些设计模式?
- 7.Spring的AOP底层实现原理?
- 8.Spring的事物原理?
- 9.Spring的事物传播机制?
1.谈一谈spring IOC的理解,原理与实现?
- 控制反转:以前的对象是由使用者自己创建并控制的,而有了Spring后,把整个对象都交给Spring管理
- DI:依赖注入,把对象对应的属性注入到具体的对象中,例如@Autowired
- 容器:存储对象,是使用map结果存储,3级缓存,singletonObjects存放的是完整的bean对象。整个bean的生命周期,从创建,使用,销毁的全部过程都由容器管理
原理实现
- 容器的创建(beanFactory,DefaultListableBeanFactory)
- 向bean工厂设置参数等属性(BeanPostProcessor,Aware接口)
- 加载解析bean对象,准备要创建的bean对象的定义对象beanDefinition(xml或者注解的解析过程)
- beanFactoryPostProcessor的扩展处理
- BeanPostProcessor的注册,方便后续对bean的扩展
- 通过反射的方式把BeanDefinition实例化具体的bean对象
- bean对象的初始化(填充属性,调用aware子类方法,调用前置处理器(applicationContext,resourceLoader)initMethod方法,以及后置处理器(AOP))
- bean对象初始化完成,getBean方法可以直接获取
- bean对象使用完成,销毁对象
2.谈一谈Spring IOC的底层实现?
- 先通过createBeanFactory创建Bean工厂(DefaultListableBeanFactory)
- 开始循环创建对象,因为容器中都是单例,所以先根据getBean doGetBean来获取对象,如果找不到
- 就通过createBean,DoCreateBean方法以反射的方式创建对象,使用的是无参构造方法(getDeclaredConstructor 和new instance)
- 对象属性填充 populateBean
- 进行其他初始化操作initializingBean
3.描述下Bean的生命周期
- 实例化bean,反射的方式创建对象
- 填充bean的属性,populateBean,循环依赖的问题(三级缓存)
- 调用aware接口,对象属性invokeAwareMethod
- 调用beanPostProcessor 前置处理器(设置applicationContext,enviroment ,resourceLoader)
- 调用init-method方法,invokeInitMethod()
- 调用beanPostProcessor后置处理器(Spring APO就是在这里实现)
- 获取到完整bean对象,通过getBean获取对象
- 使用完成之后,销毁对象distoryMethod
4.Spring如何解决循环依赖问题?
A对象里面有个b属性,B对象里面有个a属性,闭环调用
我们都知道bean对象的创建是 先实例化,然后在初始化(属性填充)
- 先创建A对象,实例化A对象,但此时的b属性为空
- 从容器中找B 对象,如果找到了,直接复制给b属性(这时就不存在循环依赖问题)
- 如果找不到B对象,此时实例化B对象,填充a属性
- 从容器中找A对象,此时A对象是存在的,只不过是不是完整状态,意思就是只完成实例化,未完成初始化的一个对象,这是就造成的闭环,那么怎么解决这个问题呢?
当所有对象都完成实例化和初始化操作后,容器中就有2个状态的对象,一个是完整对象,一个是完成实例化但未完成初始化 的对象,此时就需要2个map来存储,也就是一级缓存和二级缓存,一个是成品,一个是半成品
那么为什么有三级缓存?
三级缓存的value类型是ObjectFactory是一个函数式接口,是保证整个容器中的bean对象有且仅有1个
如果一个对象需要被代理,那么肯定是要先生成普通对象,然后再生成代理对象的,这样的话就有2个一样的对象的,这里就需要另外一个map来存放代理对象,但是在实例调用过程中,是不知道这个对象到底需不需要被代理,那么怎么办?此时可以用回调机制,在创建对象的时候先判断这个对象是否需要被代理,如果需要代理,就从三级缓存获取代理对象,如果不需要,就直接从一级缓存里面获取普通对象,然后把二级和三级删除
5.BeanFactory 和FactoryBean有什么区别?
- 相同点:都是用来创建bean对象的
- 不同点:使用beanFactory必须要遵循完整的生命周期流程 来创建对象,太复杂麻烦了,如果想要简单点,想自定义创建对象,就可以使用factoryBean来创建,他里面有3个方法
- isSingleTon:是否单例对象
- getObjectType:获取返回对象类型
- getObject:自定义创建对象(new,代理,反射等等方式都可以)
6.Spring 中用到哪些设计模式?
- 单例模式:bean都是单例的
- 工厂模式:beanFactory
- 原型模式:作用域protoType
- 模板模式:父类提供一个模板方法,具体实现交给子类Template
- 代理模式:AOP动态代理Proxy
- 观察者模式:事件监听对象Listener event
- 策略模式:就是比较器,就是封装if else 等逻辑判断
- 适配器模式:Adapter
7.Spring的AOP底层实现原理?
AOP实际上是IOC的一个扩展功能,现有IOC然后才有AOP,在IOC实现中,有个BeanPostProcessor后置处理器
- 代理对象的创建 advice,切面,切点
- 通jdk或者cglid方式生成代理对象
- 在执行方法调用的时候,执行intercept方法
- 根据之前定义好的通知来生成拦截器
- 从拦截器中一次获取每一个通知,并执行
8.Spring的事物原理?
spring的事物是由AOP来实现的,首先要生成代理对象,然后按照整套流程来执行具体的操作逻辑,要通过通知来实现核心功能,但是事物不是通过通知来实现的,而是通过一个TransactionInterceptor来实现的,然后调用invoke方法
- 准备工作,获取方法上的事物相关属性,根据配置属性来判断是否开启事物
- 当需要开启事物时,获取数据库连接,并关闭自动提交,开启事物
- 执行具体的sql操作
- 在方法执行过程中,如果报错失败了,就会通过completeTransactionAfterThrowing 来完成事物回滚操作的,具体通过doRollBack方法,拿到数据库连接进行回滚操作con.callback
- 如果方法执行正常,就通过commitTransactionAfterReturning来完成事物提交,通过doCommit方法实现,拿到数据库连接进行提交con.commit
- 事物执行完成后,需要清楚事物信息 ,cleaupTransactionInfo
9.Spring的事物传播机制?
事物A 方法里面调用了一个事物B方法,就是事物嵌套,如果B执行是吧,A怎么办?
spring中使用@Transactional进行声明式事务
一般required,required_new,nested用的最多,这个只需要理解就行