面试准备:Spring/Spring MVC常见面试题汇总

1.Spring框架有什么优点?

  1. 轻量:低侵入式设计,代码污染极低
  2. Spring的DI机制降低了业务对象替换的复杂性,提高了组件之间的解耦,方便集成,通过配置和简单的对象注入即可集成其他框架,如 Mybatis、Hibernate、Shiro…
  3. Spring的AOP支持允许将一些通用任务如安全、事务、日志等进行集中式管理,从而提供了更好的复用
  4. Spring的ORM和DAO提供了与第三方持久层框架的良好整合,并简化了底层的数据库访问
  5. Spring并不强制应用完全依赖于Spring,开发者可自由选用Spring框架的部分或全部

2.什么是AOP?

AOP:Aspect Oriented Programming,面向切面编程。
"切面"就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,利于可操作性和可维护性。

3. 实现AOP的方式?Spring AOP是怎么实现的?

  • 静态AOP:

在编译期,切面直接以字节码的形式编译到目标字节码文件中。 在编译的时候将AOP逻辑织入到代码中,需要专有的编译器和织入器。

优点:被织入的类性能不受影响。
缺点:不够灵活

  • 动态AOP(JDK动态代理):

在运行期,目标类加载后,为接口动态生成代理类,将切面植入到代理类中。Java从1.3引入动态代理。实现原理是为被代理的业务接口生成代理类,将AOP逻辑写入到代理类中,在运行时动态织入AOP,使用反射执行织入的逻辑。
主要实现方式依赖java.lang.reflect包下的InvocationHandler和Proxy类。

优点:Java标准库原生支持,使用简单,无需引用额外的包。相对于静态AOP更灵活。
缺点:带代理的类必须是接口,灵活性受到一些限制;使用反射会影响一些性能。

  • 动态代码字节生成(CGLib):

在运行期,目标类加载后,动态构建字节码文件生成目标类的子类,将切面逻辑加入到子类中。
CGLib是动态代码字节生成的实现,它封装字节码生成工具Asm,原理是在运行期间目标字节码加载后,生成目标类的子类,将切面逻辑加入到子类中,所以使用Cglib实现AOP 不需要基于接口

优点:没有接口也可以织入,灵活性高。
缺点:扩展类的实例方法为final时,则无法进行织入


Spring AOP 中的代理使用逻辑:

  • 如果目标对象实现了接口,默认情况下会采用 JDK 的动态代理实现 AOP;
  • 如果目标对象没有实现了接口,则采用 CGLIB 库,Spring 会自动在 JDK 动态代理和 CGLIB 动态代理之间转换。

4.动态代理实现方式?

参考:Java设计模式——代理模式

为什么动态代理仅支持接口,是因为Java不支持多继承。
具体可以查看Proxy类的实现方式

那些动态生成的代理类的继承关系图,它们已经注定有一个共同的父类叫Proxy。Java的继承机制注定了这些动态代理类们无法实现对class的动态代理,原因是多继承在Java中本质上就行不通。

5.PageHelper实现方式?

参考结合源码理解PageHelper

6.什么是IoC?什么是DI?

IoC,Inversion of Control(控制反转)。

控制反转(IOC)是把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理。

这样对象与对象之间是松耦合、便于测试、功能可复用(减少对象的创建和内存消耗),使得程序的整个体系结构可维护性、灵活性、扩展性变高。
优点:

  1. 依赖注入把应用的代码量降低。
  2. 它使应用容易测试,单元测试不再需要单例和JNDI查找机制。
  3. 最小的代价和最小的侵入性使松散耦合得以实现。
  4. IOC容器支持加载服务时的饿汉式初始化和懒加载。
  • spring 提供了三种主要的方式来配置 IoC 容器中的 bean
    基于 XML 文件配置
    基于注解配置
    基于注解 + java 代码显式配置

DI(Dependency Injection)依赖注入,是 IoC 容器装配、注入对象的一种方式。

通过依赖注入机制,简单的配置即可注入需要的资源,完成自身的业务逻辑,不需要关心资源的出处和具体实现。

DI注入的方式:
spring支持setter注入和构造器注入,通常是由构造器注入来注入必须的依赖关系,对于可选的依赖关系,则setter注入是更好的选择。setter注入需要类提供无参构造器或者无参的静态工厂来创建对象。

7.IoC实现原理?

参考初始化应用上下文这节。

IoC的实现原理就是工厂模式加反射机制

8.spring有哪些主要模块?

Spring框架的七大模块

1.Spring Core
框架的最基础部分,提供 IoC 容器,对 bean 进行管理。

2.Spring Context
基于 bean,提供上下文信息,扩展出JNDI、EJB、电子邮件、国际化、校验和调度等功能。

3.Spring DAO
提供了JDBC的抽象层,它可消除冗长的JDBC编码和解析数据库厂商特有的错误代码,还提供了声明性事务管理方法。

4.Spring ORM
提供了常用的“对象/关系”映射APIs的集成层。 其中包括JPA、JDO、Hibernate、MyBatis 等。

5.Spring AOP
提供了符合AOP Alliance规范的面向方面的编程实现。

6.Spring Web
提供了基础的 Web 开发的上下文信息,可与其他 web 进行集成。

7.Spring Web MVC
提供了 Web 应用的 Model-View-Controller 全功能实现。

9.spring中的bean是线程安全的吗?

Spring 不保证 bean 的线程安全。
默认 spring 容器中的 bean 是单例的。当单例中存在竞态条件,即有线程安全问题。

10.spring支持几种bean的作用域?

  • singleton:单例模式,在整个Spring IoC容器中,使用 singleton 定义的 bean 只有一个实例
  • prototype:原型模式,每次通过容器的getbean方法获取 prototype 定义的 bean 时(将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法),都产生一个新的 bean 实例

只有在 Web 应用中使用Spring时,request、session、global-session 作用域才有效

  • request:对于每次 HTTP 请求,使用 request 定义的 bean 都将产生一个新实例,即每次 HTTP 请求将会产生不同的 bean 实例。
  • session:同一个 Session 共享一个 bean 实例。
  • global-session:同 session 作用域不同的是,所有的Session共享一个Bean实例。

11.spring mvc运行流程?

参考:DispatchServlet处理流程
参考:Rest处理流程

12.@RequestMapping的作用是什么?

@RequestMapping 是一个注解,用来标识 http 请求地址与 Controller 类的方法之间的映射。

13.@Autowired的作用是什么?

@Autowired 是一个注释,它可以对类成员变量、方法及构造函数进行标注,让 spring 完成 bean 自动装配的工作。
@Autowired 默认是按照类去匹配,配合 @Qualifier 指定按照名称去装配 bean。

14.什么是spring boot?为什么要用?

spring boot 基于 spring 框架的快速开发整合包。
好处:

编码变得简单
配置变得简单
部署变得简单
监控变得简单

15.spring boot核心配置文件是什么?

Spring Boot 有两种类型的配置文件,application 和 bootstrap 文件
Spring Boot会自动加载classpath目前下的这两个文件,文件格式为 properties 或 yml 格式

*.properties 文件是 key=value 的形式
*.yml 是 key: value 的形式
*.yml 加载的属性是有顺序的,但不支持 @PropertySource 注解来导入配置,一般推荐用yml文件,看下来更加形象

bootstrap 配置文件是系统级别的,用来加载外部配置,如配置中心的配置信息,也可以用来定义系统不会变化的属性.bootstatp 文件的加载先于application文件
application 配置文件是应用级别的,是当前应用的配置文件

16.spring boot有哪些方式可以实现热部署?

以后再详解。

17.什么是Spring的内部bean?

当一个bean仅被用作另一个bean的属性时,它能被声明为一个内部bean,内部bean通常是匿名的,它们的Scope一般是prototype。

如:

	<!-- 利用setter注入Dog -->  
    <bean id="d1" class="com.yang.Dog">  
        <property name="name" value="lala"></property>  
        <property name="age" value="9"></property>  
        <property name="style" value="Hashiqi"></property>  
    </bean>  
    <!--利用构造器注入person-->  
    <bean id="d2" class="com.yang.person">  
        <constructor-arg index="0" value="andreny"></constructor-arg>  
        <constructor-arg index="1" value="15454"></constructor-arg>  
        <constructor-arg index="2" value="teacher"></constructor-arg>  
    </bean>  
    
    <bean id="m1" class="com.yang.myshow">  
        <!--内部bean-->
        <property name="dog" ref="d1"></property>  
        <!--内部bean-->
        <property name="p" ref="d2"></property>  
    </bean>  

18.描述Spring框架中bean的生命周期?

1、Spring容器 从XML 文件中读取bean的定义,并实例化bean。
2、Spring根据bean的定义填充所有的属性。
3、如果bean实现了BeanNameAware 接口,Spring 传递bean 的ID 到 setBeanName方法。
4、如果Bean 实现了 BeanFactoryAware 接口, Spring传递beanfactory 给setBeanFactory 方法。
5、如果有任何与bean相关联的BeanPostProcessors,Spring会在postProcesserBeforeInitialization()方法内调用它们。
6、如果bean实现IntializingBean了,调用它的afterPropertySet方法,如果bean声明了初始化方法,调用此初始化方法。
7、如果有BeanPostProcessors 和bean 关联,这些bean的postProcessAfterInitialization() 方法将被调用。
8、如果bean实现了 DisposableBean,它将调用destroy()方法。

19.spring中如何注入数组/集合?

Spring提供以下几种集合的配置元素:
<list>类型用于注入一列值,允许有相同的值。
<set>类型用于注入一组值,不允许有相同的值。
<map> 类型用于注入一组键值对,键和值都可以为任意类型。
<props>类型用于注入一组键值对,键和值都只能为String类型。

<beans>
  <bean id="at" class="test.array.ArrayTest">
    <property name="names">
      <list>
        <value>aaa</value>
        <value>bbb</value>
      </list>
    </property>
  </bean>
</beans>

20.Spring中有哪几种方法获取HttpSession对象?

	@RequestMapping("/session")
    public Map test(HttpSession session, String otherParam) {
        ...
    }

或者

    @RequestMapping("/session")
    public String setSession(HttpServletRequest request, HttpServletResponse response){
        HttpSession session = request.getSession();
        ...
   }

21.ApplicationContext有哪几种实现方式?

有以下3种实现方式:

1、FileSystemXmlApplicationContext :从文件系统加载IoC配置文件
2、ClassPathXmlApplicationContext:从文件系统加载IoC配置文件
3、WebXmlApplicationContext:通过WebApplicationContextUtils获取

        //加载单个xml文件
        ApplicationContext ctx = new FileSystemXmlApplicationContext("bean.xml");
        //加载多个xml文件
        String[] locations = new String[]{"bean1.xml", "bean2.xml", "bean3.xml"};
        ctx = new FileSystemXmlApplicationContext(locations);
 
        //加载单个xml文件
        ctx = new ClassPathXmlApplicationContext("bean.xml");
        //加载多个xml文件
        locations = new String[]{"bean1.xml", "bean2.xml", "bean3.xml"};
        ctx = new ClassPathXmlApplicationContext(locations);
 
        
        ServletContext servletContext = request.getSession().getServletContext();
        ctx = WebApplicationContextUtils.getWebApplicationContext(servletContext);

22.Spring里面用了哪些设计模式?

工厂模式、单例模式、代理模式、适配器模式、观察者模式…
参考:https://www.cnblogs.com/hwaggLee/p/4510687.html

23.列举几种spring的自动装配方式?

有五种自动装配的方式,可以用来指导Spring容器用自动装配方式来进行依赖注入。
(1)no:默认的方式是不进行自动装配,通过显式设置ref 属性来进行装配。
(2)byName:通过参数名 自动装配,Spring容器在配置文件中发现bean的autowire属性被设置成byname,之后容器试图匹配、装配和该bean的属性具有相同名字的bean。
(3)byType:通过参数类型自动装配,Spring容器在配置文件中发现bean的autowire属性被设置成byType,之后容器试图匹配、装配和该bean的属性具有相同类型的bean。如果有多个bean符合条件,则抛出错误。
(4)constructor:这个方式类似于byType, 但是要提供给构造器参数,如果没有确定的带参数的构造器参数类型,将会抛出异常。
(5)autodetect:首先尝试使用constructor来自动装配,如果无法工作,则使用byType方式。

发布了431 篇原创文章 · 获赞 329 · 访问量 17万+

猜你喜欢

转载自blog.csdn.net/No_Game_No_Life_/article/details/105387969