JavaEE:Spring 面试总结一览

Posted 小乔不掉发

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaEE:Spring 面试总结一览相关的知识,希望对你有一定的参考价值。

一、Spring:

Spring 是基于模块化设计的,他让 Java 开发更加便捷、安全、高效

  • Spring Framework(最基础、最核心)(其他框架都依赖于他)

子模块简介:
在这里插入图片描述

Core Container(核心容器)

简介:

spring-corespring-beans 模块,这两个模块提供了整个Spring框架最 基础的设施

  • IoC (Inversion of Control,控制反转) 和 DI (Dependency Injection,依赖注入)。
  • 这部分功能相当于所有Spring 框架运行的基础,以前我们操作对象都需要手动的 new 对象,由对象的作用域决定对象的生命周期。使用Spring后,由框架提供了统一的容器来实例化、管理这些对象,并自动组织对象与对象间的关系。这种容器称为IoC容器,有些地方也叫Spring Bean容器、Spring容器。
  • 对象之间的复杂关系(体现在代码中就是 对象中成员变量引用了另一个对象),也交给了容器来进行设置

1、IoC / DI:

(1)背景:

  • 大多数应用程序都是由两个或是更多的类通过彼此的合作来实现企业逻辑,这使得每个对象都需要获取与其合作的对象(也就是它所依赖的对象)的引用。如果这个获取过程要靠自身实现,那么这将导致代码高度耦合并且难以维护和调试

(2)概念

  • IOC (Inversion of Control,控制反转) ,是面向对象编程中的一种设计原则。主要是通过第三方IoC容器,对Bean对象进行统一管理,及组织对象之间的依赖关系。获得依赖对象的过程,由 原本程序自己控制,变为了 IoC容器来主动注入,控制权发生了反转,所以叫做IoC,控制反转(对象的创建)
  • DI (Dependency Injection,依赖注入):就是由 IoC 容器在运行期间,动态地将某种依赖关系注入到对象之中(对象赋值)
  • 依赖注入(DI)控制反转(IoC) 是从不同的角度的描述的同一件事情,就是指 :
    通过引入 IoC 容器,利用依赖关系注入的方式,实现对象之间的解耦

(3)实现方法

  • DI 是 IoC 的实现方式之一
  • DI 的实现方式主要有两种:
    • 构造方法注入
    • 属性注入

(4)实现原理

  • 反射 + ASM字节码框架(字节码框架操作字节码更为高效,功能更强大)

2、Bean容器 / Ioc容器:

Spring容器 主要是对 IoC 设计模式的实现,主要是使用容器来统一管理Bean对象,和对象之间的依赖关系

创建容器的 API:

  • BeanFactory(顶级接口):最底层的容器接口,只提供了最基础的容器功能
    (Bean 的实例化和依赖注入,使用懒加载的方式, beans 只有在我们通过 getBean() 方法直接调用它们时才进行实例化)
  • ApplicationContext(应用上下文),是上面接口的子接口
    (预加载,每一个 bean 都在 ApplicationContext 启动之后实例化)

3、Bean的作用域:

Spring 容器在初始化一个 Bean 的实例时,同时会指定该实例的作用域(至少前两个要知道)

  • (1)singleton:唯一 bean 实例,Spring 中的 bean 默认都是单例的。
  • (2)prototype:每次请求都会创建一个新的 bean 实例。(原型模式)
  • (3)request:每一次 HTTP 请求都会产生一个新的 bean,该bean仅在当前 HTTP request内有效。
  • (4)session:每一次 HTTP 请求都会产生一个新的 bean,该bean仅在当前 HTTP session内有效。
  • (5)application:在一个应用的 Servlet 上下文生命周期中,产生一个新的 bean
  • (6)websocket:在一个 WebSocket 生命周期中,产生一个新的 Bean

4、Bean的生命周期:

在这里插入图片描述

  • (1)实例化Bean:通过反射调用构造方法实例化对象。
  • (2)依赖注入:装配 Bean 的属性
  • (3)实现了 Aware 接口的 Bean:执行接口方法
  • (4)Bean对象 初始化前:循环调用实现了 预初始化方法
  • (5)Bean对象 初始化:顺序执行@PostConstruct注解方法、InitializingBean接口方法、init-method方法
  • (6)Bean对象 初始化后:循环调用实现了 后初始化方法
  • (7)关闭容器:执行Bean对象的销毁方法

5、FactoryBean 和 BeanFactory 的区别:

  • BeanFactory 是Spring容器的顶级接口,所有Bean对象都是通过BeanFactory也就是Bean容器来进行管理
  • FactoryBean 是实例化一个Bean对象的工厂类,实现了 FactoryBean 接口的Bean,根据该Bean的ID从BeanFactory中获取的实际上是FactoryBean中 getObject() 方法返回的对象,而不是FactoryBean本身,如果要获取FactoryBean对象,请在id前面加一个&符号来获取

6、Spring 容器大概的执行流程:

(1)创建容器

(2)加载 xml 配置文件 -- 包扫描

(Spring 通过 xml 配置文件,来定义Bean,但是定义Bean的方式需要通过包扫描的方式注册到容器中)

(3)包扫描下的类,带 Spring 框架的注解类,都会注册到容器中

  • ① 注册 Bean 的方式 1: 在 上使用注解 @Controller , @Service , @Repository , @Component 。需要保证该类会被 Spring 扫描到,这种定义方式默认会注册一个名称为 类名首字母小写 的Bean对象到容器中
  • ② 注册 Bean 的方式 2: 当前类被 Spring 扫描到时,可以在 方法上 使用 @Bean 注解,通过方法返回类型,也可以定义、注册Bean对象,默认使用方法名作为Bean的名称
  • ③ 注册 Bean 的方式 3:在类被Spring扫描到时,使用 @Configuration 注解,可以注册一个配置类到容器中。配置类一般用来自定义配置某些资源

(4)装配、依赖注入(能被扫描到的,带 Spring 注解的类)

  • ① 属性注入:在属性上使用 @Autowired,会将容器中的 Bean 对象装配进来
  • ② 构造方法注入:在构造方法上使用 @Resource ,将容器中的 Bean 对象注入方法参数

执行细节:

一个类,多个 id 注册到容器中,不能通过类型获取

  • 通过 id 获取:

User user = (User) context.getBean(“u1”);

  • 通过 类型获取:

User user2 = context.getBean(User.class);

二、AOP:

  • 1、概念:AOP(Aspect-Oriented Programming):面向 切面 编程
    为什么要有?
    (业务代码是竖向执行代码,新的需求需要业务代码中要插入代码,这时候侵入性比较高)
    (切面:多个业务代码以一条线在某一个具体的业务分层上切一刀,这一刀独立的完成统一业务管理)
    对 多个业务代码(系统的业务) 横切来实现统一的业务管理,而不用侵入 业务代码 本身。
  • 2、使用场景:日志记录,事务管理,性能统计,安全控制,异常处理等
  • 3、优点:代码解耦,统一业务功能对具体业务无侵入性,这样可扩展性更好,灵活性更高
  • 4、spring aop 的 实现方式
    SpringAOP是采取动态代理的方式,具体是基于 JDK 和 CGLIB 两种:
    • JDK 动态代理:需要被代理类实现接口,使用 InvocationHandler 和 Proxy (api)动态的生成代理类
    • CGLIB 动态代理:需要被代理类能被继承,不能被final修饰。使用 MethodInterceptor 来对方法拦截。CGLIB底层是基于ASM字节码框架,在运行时动态生成代理类
  • 5、spring aop 的 注解:(问到了可以回答一些)
    • @Aspect 定义切面,并注册到容器中
    • @Pointcut 定义好切点方法后,可以对目标方法进行拦截
    • 前置通知:@Before:通知方法会在目标方法调用之前执行。
    • 后置通知:@After:通知方法会在目标方法返回或者抛出异常后调用。
    • 返回之后通知:@AfterReturning:通知方法会在目标方法返回后调用。
    • 抛异常后通知:@AfterThrowing:通知方法会在目标方法抛出异常后调用。
    • 环绕通知:@Around:通知包裹了被通知的方法,在被通知的方法通知之前和调用之后执行自定义的行为
    • 目标方法在通知事件发生时,调用通知方法

三、SpringMVC:

  • 1、基础介绍:
    SpringMVC 主要是通过前端控制器 controller 中的注解来完成请求处理的。
    前段请求从 web.xml 中 servlet 的配置开始,根据 servlet 拦截的 url-parttern,来进行请求转发控制

  • 2、工作流程:
    组件:

    • 前端控制器:控制中心、组件间解耦合(无需开发\\配置即可)
    • 处理映射器:匹配 URL 是否存在(无需开发\\配置即可)
    • 处理适配器:适配查找具体处理器(无需开发\\配置即可)
    • 处理器:不同URL 处理逻辑不同(需要开发)
    • 视图解析器:查找 view 实例对象(无需开发\\配置即可)
    • 视图:web页面(JSP、freemark、pdf等类型视图)(需要开发)
      在这里插入图片描述
      具体步骤:
  • 1、用户向服务器发送请求到 前端控制器(Servelt DispatcherServlet )

  • 2、前端控制器 请求 处理器映射器(HandlerMapping)查找 Handler(可以根据xml配置、注解进行查找)

  • 3、HandlerMapping 向前端控制器返回 Handler,HandlerMapping 会把请求映射为HandlerExecutionChain对象

  • 4、前端控制器 调用 处理器适配器 去执行Handler

  • 5、处理器适配器HandlerAdapter将会根据适配的结果去执行Handler

  • 6、Handler 执行完成给 适配器 返回 ModelAndView

  • 7、处理器适配器向前端控制器返回 视图

四、Mybatis:

1、 #{} 和 ${} 的区别:

  • #{变量名} :是 预处理替换 的方式,本质是 jdbc 中 占位符的替换。如传入字符串,会替换为带单引号的值,可以 安全性更好(防止 sql 注入)
  • ${变量名} :是 字符串的替换 ,只是对 sql 字符串进行拼接 。如传入字符串,会直接替换为字符串值,不加单引号

2、 一对一、一对多关联:

(1)使用 < association>标签,表示 一对一 的结果映射:

  • property 属性:指定 Article 中对应的属性,即用户。
  • resultMap 属性:指定关联的结果集映射,将基于该映射配置来组织用户数据。
  • columnPrefix 属性:绑定一对一对象时,是通过 columnPrefix+association.resultMap.column 来映射结果集字段。association.resultMap.column是指 < association> 标签中 resultMap属性,对应的结果集映射中,column字段

(2)一对多 关系需要使用< collection>标签,使用方法和 < association>类似

以上是关于JavaEE:Spring 面试总结一览的主要内容,如果未能解决你的问题,请参考以下文章

JavaEE:Spring 面试总结一览

JavaEE:Spring 面试总结一览

框架 | Spring面试题总结

038期JavaEE面试题:Spring Cloud

031期JavaEE面试题:Spring

032期JavaEE面试题:Spring