• 关于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的构造方法来实例化。<bean id = "userService" class = "com.lihao.service.impl.UserServiceImpl">
          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时,使用<bean>的子标签<constructor-arg>来定义构造方法的参数。
                setter注入    在实例化Bean是,使用<bean>的子标签<property>来为各个属性进行注入值。【需要为被注入的属性提供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对象
    

    <foreach常用属性

        collection
        open
        close
        speparator
        index      指定一个名称,用于标识当前迭代次数
        item
    
       <delete id="deleteBatch"> 
        delete from user where id in
        <foreach collection="array" item="id" index="index" open="(" close=")" separator=",">
          #{id}
        </foreach>
      </delete>
    

    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
    
  • 相关阅读:
    第一个springboot程序,初识springboot
    创建一个简单的springBoot项目的两种方式
    vue过程中遇到的Uncaught (in promise) TypeError: Cannot read property '$message' of undefined
    springboot redis的db动态切换没有作用
    docker redis chown: changing ownership of '.': Permission denied
    axios url携带参数问题(params与data的区别)
    docker安装mysql8.0并挂载到主机
    android与服务器的登录验证与安全设计
    团队冲刺10 5.11
    构建之法01
  • 原文地址:https://www.cnblogs.com/itlihao/p/15825885.html
Copyright © 2020-2023  润新知