Spring相关框架面试

* 如有错误请指正

1、SpringMvc

  1. SpringMvc的工作原理图

  2. SpringMVC工作流程描述

      1、客户端发送请求到前端控制器。

      2、前端控制器DispatcherServlet根据请求查找对应的处理器映射器HandleMapping。

      3、处理器映射器根据用户请求,找到对应的处理器执行链并返回给前端控制器。

      4、前端控制器请求处理器适配器执行对应的Handler,即处理器方法。

      5、Handler处理器执行完毕后,返回处理器适配器一个ModelAndView对象。

      6、处理器适配器接收到返回的ModelAndView后,返回给前端控制器。

      7、前端控制器接收到ModelAndView后,请求视图解析器,对视图进行解析。

      8、视图解析器根据view匹配对应的视图,然后返回给前端控制器。

      9、前端控制器结合视图和Model中的数据进行视图渲染。

      10、前端控制器响应客户端请求。

2、Spring

  1. 谈谈Spring的了解

    1. 简单来说Spring是一个轻量级的框架,它的主要核心内容为Spring IOC和Spring AOP。(详细请往下)
  2. Spring IOC

    1. 谈谈你对ioc的了解
      1. spring ioc控制反转,在之前也叫做DI(依赖注入),本身是一个容器,用来装配管理bean对象。
      2. 简单来说在之前对象的实例化由自己控制,有了ioc之后,统一交给了spring容器来管理,在需要使用时,由spring容器进行实例化创建,这就叫控制反转,而实例化的所有对象就是spring beans。
    2. 依赖注入的方式
      1. 通过构造方法进行注入。
      2. 通过setter注入。
      3. 通过接口注入。
    3. Spring中有多少种IOC容器
      1. Spring提供了两种IOC容器,分别为BeanFacotry和ApplicationContext。
      2. BeanFactory由Spring-beans项目提供,ApplicationContext由Spring-context提供。(在源码中可以查到)
      3. ApplicationContext容器包括 BeanFactory 容器的所有功能。
      4. ApplicationContext是BeanFactory的子接口,ApplicationContext提供了更完整的功能:
        1. 继承了MessageSource,支持国际化。
        2. 统一的资源文件访问方式(ResourceLoader & ResourcePatternResolver)。
        3. 提供在监听器中注册bean事件 。
        4. 同时加载多个配置文件。
      5.  两者之间的区别:
        1. BeanFactory采用的是延迟加载形式来注入Bean,即只有在使用到Bean的时候,才对该Bean进行实例化。
        2. ApplicationContext是在容器启动时,一次性创建了所有的bean。
        3. ApplicationContext相对来说占用内存,启动慢,但是可以监测到对应的依赖是否注入。而BeanFactory只有在调用的时候,如果有异常才会抛出。
    4. 简述IOC机制
      1. IOC实现原理简单来说就是工厂模式和反射机制实现的。
  3. Spring AOP

    1. 谈谈你对aop的了解
      1. aop面向切面编程,是一种编程思想,对oop的一种补充,能在不改变原有业务逻辑的情况下,增强横切逻辑代码,常见使用场景有事务管理、日志。。
      2. aop主要内容为:Aspect(切面)、PointCut(切点)和Advice(通知)等。
    2. Advice(通知)
      1. 通知包含了Before(前置通知)、After(后置通知)、After Returning(返回后通知)、After Throwing(抛出异常后通知)和Around(环绕通知)。
      2. Before,在JoinPonit之前执行,通常使用注解@Before表示。
      3. After,在JoinPonit之后执行,通常使用注解@After表示。
      4. After Returning,在JoinPonit正常执行完成后,通常使用注解@AfterReturning表示。
      5. After Throwing,在JoinPonit执行出现异常后,通常使用注解@AfterThrowing表示。
      6. Around,在JoinPonit之前和之后各执行一次,通常使用注解@Around表示。
    3. Aop实现方式
      1. 静态代理:
      2. 动态代理:基于jdk和cglib。
    4. 如何使用AOP
      1. 基于xml方式实现。
      2. 基于注解方式实现。
      3. 目前通常使用的是注解方式,通过使用@Aspect注解。
  4. Spring Bean

    1. spring bean的生命周期。
    2. spring bean的作用域
      1. Spring 框架支持以下五个作用域,分别为 singleton、prototype、request、session 和 global sessio。
      2. singleton:在spring IoC容器仅存在一个单例Bean实例,默认值。
      3. prootype:每次请求都返回一个新的bean。
      4. request:每次 HTTP 请求都会产生一个新的 Bean 实例,并且该 Bean 仅在当前 HTTP 请求内有效。
      5. session:每一个的 Session 都会产生一个新的 Bean 实例,同时该 Bean 仅在当前 HTTP Session 内有效,同一个HTTP Session共享一个Bean,不同Session使用不同的Bean。
      6. global sessio:在spring5中已经废弃,一般用于Portlet应用环境,该作用域仅适用于WebApplicationContext环境。
      7. 详细描述:
        1. 在BeanDefinition接口中,拥有singleton和prototype两种作用域。
        2.  1 public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
           2 
           3     /**
           4      * Scope identifier for the standard singleton scope: {@value}.
           5      * <p>Note that extended bean factories might support further scopes.
           6      * @see #setScope
           7      * @see ConfigurableBeanFactory#SCOPE_SINGLETON
           8      */
           9     String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
          10 
          11     /**
          12      * Scope identifier for the standard prototype scope: {@value}.
          13      * <p>Note that extended bean factories might support further scopes.
          14      * @see #setScope
          15      * @see ConfigurableBeanFactory#SCOPE_PROTOTYPE
          16      */
          17     String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
          18 }
        3. 当启动容器时,便会往BeanFactory中注册多个Scope。
        4.  1 public abstract class WebApplicationContextUtils {
           2     
           3    public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory,
           4             @Nullable ServletContext sc) {
           5 
           6         beanFactory.registerScope(WebApplicationContext.SCOPE_REQUEST, new RequestScope());
           7         beanFactory.registerScope(WebApplicationContext.SCOPE_SESSION, new SessionScope());
           8         if (sc != null) {
           9             ServletContextScope appScope = new ServletContextScope(sc);
          10             beanFactory.registerScope(WebApplicationContext.SCOPE_APPLICATION, appScope);
          11             // Register as ServletContext attribute, for ContextCleanupListener to detect it.
          12             sc.setAttribute(ServletContextScope.class.getName(), appScope);
          13         }
          14 
          15         beanFactory.registerResolvableDependency(ServletRequest.class, new RequestObjectFactory());
          16         beanFactory.registerResolvableDependency(ServletResponse.class, new ResponseObjectFactory());
          17         beanFactory.registerResolvableDependency(HttpSession.class, new SessionObjectFactory());
          18         beanFactory.registerResolvableDependency(WebRequest.class, new WebRequestObjectFactory());
          19         if (jsfPresent) {
          20             FacesDependencyRegistrar.registerFacesDependencies(beanFactory);
          21         }
          22     }
          23 }
        5. 其他作用域处理逻辑
        6. public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
          
          protected <T> T doGetBean(
                      String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
                      throws BeansException {
          //创建bean实例
                          // Create bean instance.
                          if (mbd.isSingleton()) {
                              //singleton,单例
                              sharedInstance = getSingleton(beanName, () -> {
                                  try {
                                      return createBean(beanName, mbd, args);
                                  } catch (BeansException ex) {
                                      // Explicitly remove instance from singleton cache: It might have been put there
                                      // eagerly by the creation process, to allow for circular reference resolution.
                                      // Also remove any beans that received a temporary reference to the bean.
                                      destroySingleton(beanName);
                                      throw ex;
                                  }
                              });
                              beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                          } else if (mbd.isPrototype()) {
                              //prototype创建一个新的实例
                              // It's a prototype -> create a new instance.
                              Object prototypeInstance = null;
                              try {
                                  beforePrototypeCreation(beanName);
                                  prototypeInstance = createBean(beanName, mbd, args);
                              } finally {
                                  afterPrototypeCreation(beanName);
                              }
                              beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                          } else {
                              //既不是singleton也不是prototype
                              String scopeName = mbd.getScope();
                              if (!StringUtils.hasLength(scopeName)) {
                                  throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
                              }
          
                              //通过scope的名称获取注册的实例,Scope接口的实现类,在
                              // org.springframework.web.context.support.WebApplicationContextUtils.registerWebApplicationScopes注册的
                              Scope scope = this.scopes.get(scopeName);
                              if (scope == null) {
                                  throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                              }
                              try {
                                  Object scopedInstance = scope.get(beanName, () -> {
                                      beforePrototypeCreation(beanName);
                                      try {
                                          return createBean(beanName, mbd, args);
                                      } finally {
                                          afterPrototypeCreation(beanName);
                                      }
                                  });
                                  beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                              } catch (IllegalStateException ex) {
                                  throw new ScopeNotActiveException(beanName, scopeName, ex);
                              }
                          }
          } 
    3. spring中单例bean的线程安全
      1. 对于单例bean来说,所有线程共享一个bean,所以存在资源竞争。如果是无状态的bean,那么就不存在线程安全的问题。如果是有状态的bean,spring一般提供了ThreadLocal去解决线程安全的问题,比如:RequestContextHolder、TransactionSynchronizationManager、LocaleContextHolder等。
      2. 无状态bean(Stateless Bean):bean一旦实例化就被加进会话池中,各个用户都可以共用;即使用户已经消亡,bean 的生命期也不一定结束,它可能依然存在于会话池中,供其他用户调用;是线程安全的。
      3. 有状态bean(Stateful Bean):有数据存储功能,每个用户有自己特有的一个实例,在用户的生存期内,bean 保持了用户的信息,即“有状态”;一旦调用结束或实例结束,bean 的生命期也将结束,是非线程安全的。
  5. Spring中使用了哪些设计模式

    1. 工厂设计模式:Spring使用工厂模式通过BeanFactory或ApplicationContext获得bean对象
    2. 单例设计模式:Spring中bean的默认工作域是单例的(singleton)。
    3. 代理设计模式:Spring Aop功能的实现。
    4. 模板方法模式:Spring中的JdbcTemplate
    5. 包装器设计模式:
    6. 观察者模式:Spring 事件驱动模型就是观察者模式。
    7. 适配器模式:Spring AOP 的增强或通知(Advice)使用到了适配器模式、spring MVC 中也是用到了适配器模式适配Controller
  6. Spring自动装配

    1. Spring自动装配支持5种模式
      1. no – 缺省情况下,自动配置是通过“ref”属性手动设定。
      2. byName – 根据属性名称自动装配。如果一个bean的名称和其他bean属性的名称是一样的,将会自装配它。
      3. byType – 按数据类型自动装配。如果一个bean的数据类型是用其它bean属性的数据类型,兼容并自动装配它。
      4. constructor – 它通过调用类的构造函数来注入依赖项。它有大量的参数。
      5. autodetect – 如果找到默认的构造函数,使用“自动装配用构造”; 否则,使用“按类型自动装配”。
  7. Spring注解

    1. @Component、@Controller、@Repository、@Service的区别:
      1. @Component将Java类标记成Bean,是一个通用型的注解。
      2. @Controller是SpringMVC的一个控制器注解。
      3. @Repository是用于Dao层的注解,和mybatis提供的@Mapper注解一样用dao层。
      4. @Service是用于服务层的注解。
    2. @Autowired和@Qualifier
      1. @Autowired默认注入方式为byType,对应属性required默认为true,默认情况下必须要求依赖对象必须存在。如果要允许null值,可以设置它的required属性为false。
      2. @Qualifier通常和@Autowired一起使用,当有多个实现时,通过@Qualifier注解来显式指定name值,指明要使用哪个具体的实现类。
      3. 和@Autowired有同样功能的@Resource注解。
        1. @Autowired注解是Spring提供的,而@Resource注解是J2EE本身提供的
        2. @Autowird注解默认通过byType方式注入,而@Resource注解默认通过byName方式注入
  8. Spring事务的隔离级别

    1. spring的事务隔离级别是有五种的,比数据库是多一种的。
      1. DEFAULT(默认):这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别。另外四个与JDBC的隔离级别相对应。
      2. READ_UNCOMMITTED(读未提交)
      3. READ_COMMITTED(读已提交)
      4. REPEATABLE_READ(可重复读)
      5. REPEATABLE_READ(可重复读)
  9. Spring事务的传播特性

    1. REQUIRED:默认的传播特性,业务方法需要在一个事务中运行,如果一个方法已经处在一个事务中那么就加入到这个事务中,否则就会创建一个事务。(如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。)
    2. NEVER:指定的业务方法绝对不能在事务范围内运行,如果业务方法在某个事务中执行,就会抛异常,只有业务方法没有任何事务才正常执行。(以非事务方式执行,如果当前存在事务,则抛出异常。 )
    3. MANDATORY:该属性指定业务方法只能在一个已经存在的事务中执行,业务方法不能自己发起自己的事务,如果业务方法不存在事务,容器就抛异常。(支持当前事务,如果当前没有事务,就抛出异常。)
    4. SUPPORTS:如果业务方法中已经在某个事务中被调用,则方法就成为事务的一部分,如果外部业务方法没有开启事务,supports该方法也会在没有事务的环境中执行。(支持当前事务,如果当前没有事务,就以非事务方式执行。)
    5. NOT_SUPPORTED:如果该业务方法在一个事务中被调用,那么当前的事务会被挂起,执行该业务方法,方法执行完毕唤醒被挂起的事务,如果业务方法不在一个事务中执行,该方法也不会开事务。不管是否在有无事务的环境中执行都不开启事务。(以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。)
    6. REQUIRES_NEW:不管是否存在事务,业务方法总会自己开启一个事务,如果在已有事务的环境中调用,已有事务会被挂起,新的事务会被创建,直到业务方法调用结束,已有事务才被唤醒。(新建事务,如果当前存在事务,把当前事务挂起。)
    7. NESTED:如果业务方法在一个事务中执行,就在这个事务中嵌套,如果没有事务按着required执行,开启单独的事务,这种事务有多个事务的保存点,内部事务的回滚对外部事务没有影响。(支持当前事务,新增Savepoint点,与当前事务同步提交或回滚。)

 

posted @ 2021-07-06 20:50  浮or沉  阅读(62)  评论(0编辑  收藏  举报