Spring面试题
谈谈Spring IOC的理解,原理与实现?
-
控制反转:
- 理论思想,原来的对象是由使用者来控制,有了Spring之后,可以把整个对象交给Spring来帮我们进行管理。
- DI:依赖注入,把对应的属性的值注入到具体的对象中。
-
容器:
- 存储对象,使用map结构来存储,在spring中一般存在三级缓存,singletonObjects存放完整的bean对象,整个bean的生命周期,从创建到使用到销毁的过程全部是由容器来管理。
-
具体实现
-
容器的创建过程(beanFactory、DefaultListableBeanFactory),向Bean工厂中设置一些参数(BeanPostProcessor、Aware接口)等等属性。
-
加载解析bean对象,准备要创建的bean对象的定义对象beanDefinition(xml或者注解的解析过程)。
-
beanFactoryPostProcessor的处理,此处是扩展点,PlaceHolderConfigurSupport、ConfigurationClassPostProcessor。
-
BeanPostProcessor的注册功能,方便后续对bean对象完成具体的扩展功能。
-
通过反射的方式将BeanDefinition对象实例化成具体的bean对象。
-
bean对象的初始化过程(填充属性、调用aware子类的方法,调用BeanPostProcessor前置处理方法,调用init-method方法、调用BeanPostProcessor后置处理方法)。
-
生成完整的bean对象,通过getBean方法可以直接获取。
-
销毁过程。
-
谈一下Spring IOC的底层实现
-
先通过createBeanFactory创建出一个Bean工厂(DefaultListableBeanFactory)。
-
开始循环创建对象,因为容器中的bean默认都是单实例的,所以优先通过getBean,doGetBean从容器中查找。
-
找不到的话,通过createBean,doCreateBean方法,以反射的方式创建对象,一般情况下使用的都是无参的构造方法(getDeclaredConstructor,newInstance)
-
进行对象的属性填充populateBean
-
进行其他的初始化操作(initializingBean)
描述一下bean的生命周期
-
实例化bean:反射的方式生成对象、
-
填充bean的属性:populateBean()、循环依赖的问题
-
调用aware接口相关的方法:invokeAwareMethod(完成BeanName、BeanFactory、BeanClassLoader对象的属性设置)
-
调用BeanPostProcessor中的前置处理方法:使用比较多的有(ApplicationContextPostProcessor、设置ApplicationContext、Environment、ResourceLoader、EmbeddValueResolver等对象)
-
调用initmethod方法:invokeInitmethod(),判断是否实现了initializingBean接口,如果有,调用afterPropertiesSet方法,没有就不调用
-
调用BeanPostProcessor中的后置处理方法:spring的aop就是在此处实现的,AbstractAutoProxyCreator,注册Destuction相关的回调方法
-
获取到完整的对象,可以通过getBean的方式来进行对象的获取
-
销毁流程:
-
判断是否实现了DispoableBean接口
-
调用destroyMethod方法
Spring AOP的底层实现原理
- bean的创建过程中有一个步骤可以对bean进行扩展实现,aop本身就是一个扩展实现,所以在BeanPostprocessor的后置处理方法中来实现。
- 代理对象的创建过程
- 通过jdk或者cglib的方式来生成代理对象
- 在执行方法调用的时候,对调节到生成的字节码文件中,直接回找到DynamicAdvisoredInterceptor类中的intercept方法,从此方法开始执行
- 根据之前定义好的通知来生成执行器链
- 从拦截器链中依次获取每一个通知开始进行执行,在执行过程中,为了方便找到下一个通知是哪个,会有一个CglibMethodInvocation的对象,找的时候是从-1的位置依次开始查找并执行的
Spring的事务是如何进行回滚的
- Spring的事务是由aop来实现的,首先要生成具体的代理对象,然后按照aop的整套流程来执行具体的操作逻辑,正常情况下要通过通知来完成核心功能,但是事务不是通过通知来实现的,而是通过一个TransactionIntercepter来实现的,然后调用invoke来事项具体的逻辑
- 先做准备工作,解析各个方法上事务相关的属性,根据具体的属性来判断是否开启新事务
- 当需要开启的时候,获取数据库连接,关闭自动提交功能,开启事务
- 执行具体的sql逻辑
- 在操作过程中,如果执行失败了,那么会通过completeTranscationAfterThrowing来完成事务的回滚操作,回滚的具体逻辑是通过doRollBack方法来实现的,实现的时候也要先获取连接对象,通过连接对象来回滚。
- 如果执行过程中没有任何意外情况的发生,那么通过commitTransactionAfterReturning来完成事务的提交操作,提交的具体逻辑是通过doCommit方法来实现的,实现的时候也要先获取连接对象,通过连接对象来提交。
- 当事务执行完毕后需要清除相关的事务信息cleanupTransactionInfo
谈一下Spring事务传播?
- 事务的传播特性指的是不同方法的嵌套调用过程中,事务应该如何进行处理,是用同一个事务还是不同的事务,当出现异常的时候会回滚还是提交,两个方法之间的相互影响。
谈谈对Spring Bean的理解
-
什么是Spring Bean
- Spring是通过声明式配置的方式来定义Bean的,所有创建Bean需要的前置依赖或者参数都是通过配置文件先声明,Spring启动以后会解析这些声明号的配置内容。
-
定义Spring Bean有哪些方式
- 基于XML的方式配置
- 基于注解扫描的方式配置:通过配置@ComponentScan声明需要扫描的基础包路径,提供4种内置的注解来声明bean,@Controller、@Service、@Repository、@Component
- 基于Java类的配置:@Configuration、@Bean
-
Spring容器如何加载Bean
- spring将这些配置内容都转化为BeanDefinition对象,BeanDefinition对象几乎保存了配置文件中声明的所有内容,再将BeanDefinition存到一个beanDefinitionMap中,以beanName作为key,BeanDefinition作为value
Spring Bean的定义包含哪些内容?
-
Spring Bean声明式配置内容
- beanClass对应的配置是class,指向一个具体存在的java类
- lazyInit对应的配置是lazy-init,用于指定Bean实例是否延时加载
- dependsOn对应的配置是depengds-on,用于定义Bean实例化的依赖关系
-
Spring如何解析配置文件
Spring MVC的执行流程
- 配置阶段
- 主要是完成对xml配置和注解配置
- 从web.xml开始,配置DispatcherServlet的url匹配规则和Spring主配置文件的加载路径,然后就是