关于ssm常问面试题


1. 说说你对spring的理解

    Spring有两大特性:控制反转IOC 和 面向切面编程AOP,解决了传统代码的高耦合性与代码不可复用的问题,能很方便的整合各种开源框架,是一个非侵入式的,高效的开源框架。
    
    IOC:控制反转,将创建对象的权利交给Spring,由Spring帮我们管理Bean。在面向对象的编程过程中,要想使用某个对象,就需要先实例化这个对象,需要我们用new XXX(),若该对象不存在就会报错。而在Spring中,我们不需要显式的去new,解决了代码的高耦合性。

    AOP:面向切面编程,它是一种思想,是横向的。OOP:面向对象编程,是纵向的。先说说纵向的编程思想,举例:在JAVA中,有一个类A有一个方法,类B也想使用,那么怎么解决呢,就需要类B去继承类A,如果类C也想使用,那么需要去继承类A或类B。而横向编程的思想就是:将类A的公共方法提取出来,哪些类需要,就横切穿插进去,这就是AOP面向切面的横向编程思想,解决了代码的不可复用性。

2. 说说Spring的核心容器

    Spring的主要功能是通过其核心容器来实现的。Spring提供了两种核心容器,分别为BeanFactory与ApplicationContext。

    BeanFactory:是基础类型的IOC容器,提供了完整的IOC服务支持。简单来说,就是一个管理Bean的工厂,主要负责初始化各种Bean,并调用他们的生命周期方法。
                采用延迟加载策略来初始化Bean,即在真正用到Bean(调用getBean())的时候才去实例化Bean,减小了服务器的压力,但是若Bean的某一属性并没有注入成功或Bean配置错误等,那么真正用到这个Bean时才报错,这不便于我们及时发现错误。

    ApplicationContext:是BeanFactory的子接口,也被称为应用上下文。它不仅包含了BeanFactory的所有功能,还添加了对国际化,资源访问,事件传播等方面的支持。
                在项目初始化启动的时候,就去实例化所有Bean,相当于一来就来了次自检,这样便于我们及时发现错误。

3. Bean的实例化方式有哪些

    Bean:需要被Spring容器管理的对象。
    实例化方式:
      1. 构造器实例化      通过对Bean的构造方法来实例化。
      2. 静态工厂实例化    要求开发者创建一个静态工厂的方法来创建Bean的实例,其Bean配置中的class属性所指定的不再是Bean实例的实现类,而是静态工厂类,同时还需要使用factpry-methond属性来指定所创建的静态工厂方法。
      3. 实例工厂实例化    要求开发者创建一个工厂类,工厂类用普通方法创建Bean实例,同时Bean配置中不再是通过class属性指向实例化类,而是通过factory-bean属性指向配置的实例工厂,然后用factory-method属性指定工厂中创建实例的那个方法。
      4. 注解实例化        @Controller @Service @Repository @Component[可作用于任何层次]

4. Bean的作用域

    Spring中Bean的实例定义了七种作用域。
    1. singleton      默认作用域,无论多少个Bean引用它,都会指向同一个实例对象。
    2. prototype      每次获取的实例对象都是一个新实例。
    3. request
    4. session
    5. globalSession
    6. application
    7. websocket

5. Bean依赖注入的方式有哪些

    依赖注入:将一个Bean注入到另一个对象中。
    注入方式:
        基于XML:
            构造器注入    在实例化Bean时,使用的子标签来定义构造方法的参数。
            setter注入    在实例化Bean是,使用的子标签来为各个属性进行注入值。【需要为被注入的属性提供setter方法】
        基于注解
            @Autowired    默认按照类型进行注入
            @Resource      默认按照实例名注入,有两个属性,name和type。可以自己按需指定。
            @Qualifier      与Autowired配合使用,会将默认的按类型注入改为按实例名注入,实例名由@Qualifier的参数指定。【一般用于由多个同类型Bean时】
            
            @AutoWired与@Qualifier的理解:https://blog.csdn.net/weixin_43351375/article/details/101014896

6. 说说你对SpringAop的理解

    AOP:面向切面编程,是对OOP的一种补充。AOP采用横向抽取机制,将分散在各个方法中的重复代码抽取出来,然后在程序编译或运行时,再将这些抽取的代码应用到需要的地方。这就是AOP横向编程思想。
虽然传统的OOP通过继承或组合的方式也能达到代码的重用,但如果需要实现某个功能(如日志记录),需要将代码编写到各个方法中,一旦想关闭或对其修改,就需要对所有相关方法进行修改。

    目前常用的AOP框架有 SpringAOP与AspectJ。

    SpringAOP:纯Java代码实现,在运行期间通过代理方式向目标类织入增强的代码。
    AspectJ:一个基于Java语言的AOP框架。


    SpringAOP:
        Spring中的AOP代理,可以是JDK动态代理(默认),也可以是CGLIB动态代理。
        
        JDK动态代理:
            通过Proxy类来实现,通过调用其newProxyInstance()方法来创建代理对象。对于使用业务接口的类,Spring默认会使用JDK动态代理。
                newProxyInstance():参数1:当前类加载器  参数2:被代理后的对象  参数3:代理类本身
            代理类需要实现InvocationHandler接口,并编写代理方法invoke()。
                invoke():参数1:被代理后的对象  参数2:将要被执行的方法  参数3:执行方法时需要的参数

        JDK动态代理的实现:
            https://blog.csdn.net/jiankunking/article/details/52143504
            
        =================================================

        CGLIB动态代理:
            JDK动态代理有一定的局限性————使用动态代理的对象必须实现一个或多个接口。
            对于没有实现接口的类进行代理,那么可以使用CGLIB代理。
            
            底层采用字节码技术,对指定的目标类生成一个子类,通过对子类进行增强,从而达到对目标对象的增强。
            代理类需要实现MethodInterceptor接口,并实现方法intercept()。
                intercept():参数1:指定父类生成的代理对象  参数2:拦截的方法  参数3:拦截方法的参数数组  参数4:方法的代理对象,用于执行父类的方法

        CGLIB动态代理的实现:
            https://www.cnblogs.com/leifei/p/8263448.html

        //////////////////////////////////
        Spring种的AOP代理默认就是使用JDK动态代理的方式来实现的。具体就不贴代码了。

        ----------------------------------
        Spring种的通知类型:
            前置通知
            后置通知
            环绕通知
            异常通知
            最终通知

7. AspectJ

    AspectJ:一个AOP框架,实现AOP的方式有两种,基于XML方式与基于注解的方式。【这里只介绍注解,XML用的太少了】
    
    @Aspect
    @Pointcut
    @Before
    @AfterReturning
    @Around
    @AfterThrowing
    @After
    @DeclareParents

    AspectJ做AOP日志管理:https://www.cnblogs.com/jelly12345/p/14950731.html

8. Spring对于事物的管理

    Spring提供了专门的API做事物处理,简化了传统的事物管理流程,在一定程度上减少了开发者的工作量。

    Spring中的事物管理分为两种方式,传统的编程式事物管理与声明式事务管理。【编程式事务管理就是编写代码来管理事务,需要定义事物的开始,提交和异常时的回滚,这里不讲解此种】

    声明式事物管理:
        是通过AOP实现的,主要思想就是将事物管理作为一个切面代码单独编写,然后通过AOP技术横切织入到代码中。
      
        实现方式:
          1. 基于XML
          2. 基于注解【这里只讲注解方式】

        注解方式:
            @Transational()
            常用参数说明:
                isolation:指定事物的隔离级别
                propagation:指定事物的传播行为
                read-only:指定事物是否只读
                rollbackFor:指定事物遇到特定异常时强制回滚
                timeout:指定事物的超时时长

9. Spring对于事物管理中的传播行为

    传播行为:指当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行。【说得通俗一点就是多个具有事务控制的service的相互调用时所形成的复杂的事务边界控制】

    传播行为详解:https://blog.csdn.net/weixin_39625809/article/details/80707695

10. Spring对于事物管理中的隔离级别

    在mysql中,隔离级别主要是:1. 读未提交  2. 读已提交  3. 可重复度  4. 串行化

    而在Spring中,多了一种隔离级别:default(默认)
        default:意思是使用数据库本身使用的隔离级别。?Spring建议的是使用DEFAULT,就是数据库本身的隔离级别,配置好数据库本身的隔离级别,无论在哪个框架中读写数据都不用操心了。

Mybatis的mapper中如何传递多个参数

    方法1:xml里面用#{0},#{1}....
    方法2:@Param注解
    方法3:封装成Map对象
    方法4:封装成JavaBean对象

.
    collection
    open
    close
    speparator
    index      指定一个名称,用于标识当前迭代次数
    item

    
    delete from user where id in
    
      #{id}
    
  

SpringMVC工作流程

    1)用户发送请求至前端控制器 DispatcherServlet。
    2)DispatcherServlet 收到请求调用 HandlerMapping 处理器映射器。
    3)处理器映射器找到具体的处理器(可以根据 xml 配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给 DispatcherServlet。
    4)DispatcherServlet 调用 HandlerAdapter 处理器适配器。
    5)HandlerAdapter 经过适配调用具体的处理器(Controller,也叫后端控制器)。
    6)Controller 执行完成返回 ModelAndView

SpringMvc 的控制器是不是单例模式,如果是,有什么问题,怎么解决

    是单例模式,所以在多线程访问的时候有线程安全问题。
    
    解决方法:
        1)不要再成员位置定义成员变量
        2)如果非要定义成员变量,在类上用@Scope("prototype")=========================每次获取Bean的时候会有一个新的实例,当请求数越多,性能会降低,因为每次回创建新的实例。
        3)使用ThreadLocal

SpringBoot怎么整合拦截器与过滤器 【拦截器与过滤器的区别】 注意这里不讲解 SpringMVC整合拦截器,只讲SpringBoot整合拦截器与过滤器

    SpringBoot整合拦截器:
        (1)实现HandlerInterceptor,重写如下方法
          preHandle(HttpServletRequest request, HttpServletResponse response, java.lang.Object handler)  方法前执行
              
          post(HttpServletRequest request, HttpServletResponse response, java.lang.Object handler, ModelAndView modelAndView)  方法后执行,视图解析之前

          afterCompletion(HttpServletRequest request, HttpServletResponse response, java.lang.Object handler, java.lang.Exception ex)  整个请求完成之后执行

        (2)编写拦截器配置类
          @Configuration
          public class WebMvcConfiguration implements WebMvcConfigurer {
              @Autowired
              private LogInterceptor logInterceptor;

              //配置拦截器
              @Override
              public void addInterceptors(InterceptorRegistry registry) {
                  //指定拦截器,指定拦截路径
                  registry.addInterceptor(logInterceptor).addPathPatterns("/**");
              }
          }

    ================================

    SpringBoot整合过滤器:
        https://blog.csdn.net/m0_37989911/article/details/99241066

    ********************************

    过滤器与拦截器的区别:
        ①拦截器是基于java的反射机制的,而过滤器是基于函数回调。
        ②拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
        ③拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
        ④拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
        ⑤在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
        ⑥拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。

SpringBoot自动装配原理与一些相关面试题

    https://www.cnblogs.com/itlihao/p/14973077.html