java框架高频面试题1(Spring面试题)

目录

一、谈谈Spring IOC得理解,原理与实现

总:

1.1、注解@Autowired和@Resource有什么区别?

1.2、 BeanFactory和ApplicationContext有什么区别?

1.3、描述一下bean的生命周期

1.4 谈一下spring IOC的底层实现

1.5、Spring是如何解决循环依赖的问题的?

三级缓存,提前暴露对象,aop

为什么需要三级缓存?

如果一个对象需要被代理,或者说需要生成代理对象,那么要不要优先生成一个普通对象?

1.6 Spring 中的 bean 的作用域有哪些?

二、Spring的AOP的底层实现原理

2.1使用动态代理

(1)JoinPoint: 连接点(所有可以被增强的方法)

(2)Pointcut: 切入点(具体项目中真正已经被增强的方法:方法上添加@Pointcut注解,配置切入点)

(2)Aspect: 切面(存放通知的类:@Aspect指定哪个类是切面)

(3)Advice: 通知/增强 (具体用于增强方法的代码)

 三、Spring中的事务

3.1 注解方式配置声明式事务(@Transcation):

3.2 @Transactional注解:

3.3 Spring的事务是如何回滚的?spring的事务管理是如何实现的?

Spring中用到的设计模式?


一、谈谈Spring IOC得理解,原理与实现

总:

控制反转:它只是理论思想,原来的对象是我们创建的;有了spring之后,可以把整个对象交给spring来帮我们进行管理,这样就可以解耦。

它的具体实现是DI:依赖注入,把对应的属性的值注入到具体的对象中,@Autowired,@Resource,populateBean方法来完成属性值的注入(赋值)。

容器:存储对象,使用map结构来存储,通过BeanFactoryApplicationContext两个接口来创建Bean。整个bean的生命周期,从创建使用销毁的过程全部都是由容器来管理的(bean的生命周期)​  spring中的bean都是通过反射的方式生成的(constructor,newinstance),ioc中最核心的也就是填充具体bean的属性(初始化

在spring中一般存在三级缓存,singletonObjects存放完整的bean对象,earlysingletonObjects存放半成品对象,singletonFactory用来存放Lambda表达式和对象名称的映射。

1.1、注解@Autowired和@Resource有什么区别?

  • @Autowird默认的注入方式为byType,也就是根据类型匹配。当有多个实现时,则通过byName注入,也可以通过配合@Qualifier注解来显式指定name值,指明要使用哪个具体的实现类
  • @Resource默认通过byName注入,如果没有匹配则通过byType注入。同时@Resource还有两个重要的属性:name和type,用来显式指定byName和byType方式注入。

1.2、 BeanFactory和ApplicationContext有什么区别?

  • BeanFactory是访问spring容器的根接口,提供基本的IOC和DI功能。
  • 而ApplicationContext实现了该接口,对该接口做了一些扩展,提供了更多的api的调用。所以一般情况下使用ApplicationContext更多。

1.3、描述一下bean的生命周期

spring容器帮助我们去管理对象,从对象的产生到销毁都是由容器来控制的,其中主要是实例化和初始化的过程:

  1. 实例化Bean,通过反射的方式生成对象,有一个createBeanInstance是专门用来生成对象的。
  2. bean对象创建完,它的属性值都是默认值,所以需要填充bean的属性:通过populateBean()来填充属性,会存在循环依赖的问题(三级缓存)
  3. 向bean对象中设置容器属性:invokeAwareMethods方法来将容器对象设置到具体的bean对象中。
  4. 调用BeanPostProcessor中的前置处理方法:使用比较多的有(ApplicationContextPostProcessor设置ApplicationContext,Environment,ResourceLoader,EmbeddValueResolver等对象)
  5. 调用invokeInitmethods方法来完成初始化方法的调用,判断是否实现了InitializingBean接口,如果有,调用afterPropertiesSet方法,
  6. 调用BeanPostProcessor的后置处理方法,Bean初始化完成spring的aop就是在此处实现的,实现接口名字AbstractAutoProxyCreator
  7. 通过getBean的方式来进行对象的获取
  8. 对象使用完毕,容器关闭对象就会销毁 ①判断是否实现了DispoableBean接口②调用destroyMethod方法

1.4 谈一下spring IOC的底层实现

底层实现:工作原理,过程,数据结构,流程,设计模式,设计思想

你对他的理解和你了解过的实现过程

反射,工厂,设计模式,关键的几个方法

createBeanFactory , getBean ,doGetBean , createBean , doCreateBean,createBeanInstance(getDeclaredConstructor(),newinstance),populateBean

  1. 先通过createBeanFactory 创建一个Bean工厂(DefaultListableBeanFactory)
  2. 开始循环创建对象,因为容器中的bean默认都是单例的,所以优先通过getBean,doGetBean从容器中查找,找不到的话,
  3. 通过createBean,doCreateBean方法,以反射的方式创建对象,一般情况下使用的是无参的构造器(getDeclaredConstructor(),newinstance)
  4. 进行对象的属性填充populateBean
  5. 进行其他的初始化操作(initializingBean)

1.5、Spring是如何解决循环依赖的问题的?

三级缓存,提前暴露对象,aop

:什么是循环依赖问题,A依赖B,B依赖A

:先说明bean得创建过程:实例化,初始化(填充属性)

  1. 先创建A对象,实例化A对象,此时A对象中的b属性为空
  2. 从容器中查找B对象,如果找到了,直接赋值不存在循环依赖问题(不通),找不到直接创建B对象
  3. 实例化B对象,此时B对象中的a属性为空,填充属性a
  4. 从容器中查找A对象,找不到,直接创建

此时,如果仔细琢磨的话,会发现A对象,是存在的,只不过此时的A对象不是一个完整的状态,只完成了实例化但是未完成初始化,如果在程序调用过程中,拥有了某个对象的引用,能否在后期给他完成赋值操作,可以优先把非完整状态的对象优先赋值,等待后续操作来完成赋值,相当于提前暴露了某个不完整对象的引用,所以解决问题的核心在于实例化和初始化分开操作,这也是解决循环依赖问题的关键,

当所有的对象都完成实例化和初始化操作之后,还要把完整对象放到容器中,此时在容器中存在对象的几种状态,完成实例化=但未完成初始化,完整状态,因为都在容器中,所以要使用不同的map结构来进行存储,此时就有了一级缓存和二级缓存,如果一级缓存中有了,那么二级缓存中就不会存在同名的对象,因为他们的查找顺序是1,2,3这样的方式来查找的。一级缓存中放的是完整对象,二级缓存中放的是非完整对象,

为什么需要三级缓存?

三级缓存的value类型是ObjectFactory,是一个函数式接口

存在的意义是保证在整个容器的运行过程中同名的bean对象只能有一个。

如果一个对象需要被代理,或者说需要生成代理对象,那么要不要优先生成一个普通对象?

要,普通对象和代理对象是不能同时出现在容器中的,因此当一个对象需要被代理的时候,就要使用代理对象覆盖掉之前的普通对象,在实际的调用过程中,是没有办法确定什么时候对象被使用,所以就要求某个对象被调用的时候,优先判断此对象是否需要被代理,类似于一种回调机制的实现,因此传入lambda表达式的时候,可以通过lambda表达式来执行对象的覆盖过程,getEarlyBeanReference()

因此,所有的bean对象在创建的时候要优先放到三级缓存中,在后续的使用过程中,如果需要被代理则返回代理对象,如果不需要被代理,则直接返回普通对象

1.6 Spring 中的 bean 的作用域有哪些?

  • singleton : 唯一 bean 实例,Spring 中的 bean 默认都是单例的。
  • prototype : 每次请求都会创建一个新的 bean 实例。
  • request : 每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP request内有效。 session : :在一个HTTP Session中,一个Bean定义对应一个实例。该作用域仅在基于web的 Spring ApplicationContext情形下有效。
  • global-session: 全局session作用域,仅仅在基于portlet的web应用中才有意义,Spring5已经没有了。Portlet是能够生成语义代码(例如:HTML)片段的小型Java Web插件。它们基于portlet容器,可以像servlet一样处理HTTP请求。但是与 servlet 不同,每个 portlet 都有不同的会话

二、Spring的AOP的底层实现原理

AOP就是面向切面编程(在不修改源码的情况下,对已有方法进行增强)就是将程序中重复利用的代码抽取成一个工具类,在使用的时候用动态代理的方法进行增强。可用于权限认证、日志、事务处理等。

2.1使用动态代理

  • JDK动态代理: JDK的proxy通过实现接口来实现扩展功能。
  • Cglib动态代理: 它底层使用的是字节码的增强技术,可以生成目标类的一个子类。去实现一个代理的功能。但是它要求目标类必须能被继承,即不能是final类。
  • Cglib在创建对象的过程中速度比较慢,但是在运行时效率更高一些。

(1)JoinPoint: 连接点(所有可以被增强的方法)

类里面哪些方法可以被增强,这些方法称为连接点. 在spring的AOP中,指的是业务层的类的所有现有的方法。

(2)Pointcut: 切入点(具体项目中真正已经被增强的方法:方法上添加@Pointcut注解,配置切入点)

在类里面可以有很多方法被增强,但是实际开发中,我们只对具体的某几个方法而已,那么这些实际增强的方法就称之为切入点

(2)Aspect: 切面(存放通知的类:@Aspect指定哪个类是切面)

(3)Advice: 通知/增强 (具体用于增强方法的代码)

比如给某个切入点(方法) 扩展了校验权限的功能,那么这个校验权限即可称之为增强或者是通知

  1. 前置通知(@Before注解): 在被增强的方法之前执行.
  2. 后置通知(@AfterReturning注解): 在被增强的方法之后执行. 特点: 可以得到被增强方法的返回值
  3. 异常通知(@AfterThrowing注解): 在被增强的方法执行出现异常的时候执行. 如果方法没有异常,不会执行. 特点:可以获得异常的信息
  4. 最终通知(@After注解): 指的是无论是否有异常,总是被执行的。
  5. 环绕通知(@Around注解):在方法之前和方法之后执行. 特点:可以阻止目标方法执行

 三、Spring中的事务

3.1 注解方式配置声明式事务(@Transcation):

  1. 配置事务管理者
  2. 加载事务注解驱动
  3. 在代码中使用@Transactional注解来标注,哪个方法需要使用事务

3.2 @Transactional注解:

(1)rollbackFor 表示该事务遇到什么就回滚,默认是遇到所有的异常都回滚
(2)noRollbackFor 表示该事务遇到什么不回滚
(3)timeout 表示事务的超时时间,默认为-1
(4)readOnly 表示该事务是只读事务,所以配置了readOnly的事务属性的方法中不能进行数据库的增删改操作
(5) isolation 表示该事务的隔离级别:

  1.  READ_UNCOMMITTED 读取到未提交的事务
  2.  READ_COMMITTED 读取到已提交的事务
  3.  REPEATABLE_READ 可重复读
  4. SERIALIZABLE 串行化

3.3 Spring的事务是如何回滚的?spring的事务管理是如何实现的?

总:spring的事务是由aop来实现的,首先要生成具体的代理对象,然后按照aop的整套流程来执行具体的操作逻辑,正常情况下要通过通知来完成核心功能,但是事务不是通过通知实现的,而是通过一个TransactionInterceptor来实现的,然后调用invoke来实现具体的逻辑。

分:

  1. 先做准备工作,解析各个方法上事务相关的属性,根据具体的属性来判断是否开始新事务
  2. 当需要开启的时候,获取数据库连接,关闭自动提交功能,开启事务
  3. 执行具体的sql逻辑操作
  4. 在操作过程中,如果执行失败了,那么会通过completeTransactionAfterThrowing看来完成事务的回滚操作,回滚的具体逻辑是通过doRollBack方法来实现的,实现的时候也是要先获取链接对象,通过连接对象来回滚。
  5. 如果执行过程中,没有任何意外情况的发生,那么通过commitTransactionAfterReturning来完成事务的提交操作,提交的具体逻辑是通过doCommit方法来实现的,实现的时候也要获取链接,通过链接对象来提交
  6. 当事务执行完毕之后需要清除相关的事务信息cleanupTransactionInfo

如果想要聊的更加细致的话,需要知道TransactionInfo,TransactionsStatus

Spring中用到的设计模式?

单例模式:bean默认都是单例的

工厂模式:BeanFactory

代理模式:动态代理

原型模式:指定作用域为prototype

模板模式:postProcessBeanFactory,onRefresh,initPropertyValue

策略模式:XmlBeanDefinitionReader,PropertiesBeanDefinitionReader

观察者模式:listener,event,multicast

适配器模式:Adapter

装饰者模式:BeanWrapper

责任链模式:使用aop的时候会生成一个拦截器

委托者模式:delegate

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值