原创

Java面试题-Spring(持续更新)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lyhkmm/article/details/79986958

什么是Spring?

  1. Spring的核心是一个轻量级(Lightweight)的容器(Container)。
  2. Spring是实现IoC(Inversion of Control)容器和非入侵性(No intrusive)的框架。
  3. Spring提供AOP(Aspect-oriented programming)概念的实现方式。
  4. Spring提供对持久层(Persistence)、事物(Transcation)的支持。
  5. Spring供MVC Web框架的实现,并对一些常用的企业服务API(Application Interface)提供一致的模型封装。
  6. Spring提供了对现存的各种框架(Structs、JSF、Hibernate、Ibatis、Webwork等)相整合的方案。

什么是IOC、DI?

       Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想,Spring的核心。所谓IoC,对于spring框架来说,就是由spring来负责控制对象的生命周期和对象间的关系。
  Java中的Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。
  IoC的一个重点是在系统运行中,动态的向某个对象提供它所需要的其他对象。这一点是通过DI(Dependency Injection,依赖注入)来实现的。
  DI—Dependency Injection,即“依赖注入”:组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。
  那么DI是如何实现的呢?
  Java 1.3之后一个重要特征是反射(reflection),它允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性,spring就是通过反射来实现注入的。
  IOC容器的初始化过程
  资源定位,即定义bean的xml-------》载入--------》IOC容器注册,注册beanDefinition
  IOC容器的初始化过程,一般不包含bean的依赖注入的实现,在spring IOC设计中,bean的注册和依赖注入是两个过程,,依赖注入一般发生在应用第一次索取bean的时候,但是也可以在xm中配置,在容器初始化的时候,这个bean就完成了初始化。
  三种注入方式,构造器、接口、set注入,我们常用的是set注入
       bean是如何创建:工厂模式

AOP

       面向切面编程是对面向对象编程(oop)的补充

aop框架具有的两个特征

       各个步骤之间的良好隔离性 ;
       源代码无关性 。

AOP的实现原理

       代理

主要功能

日志记录,性能统计,安全控制,事务处理,异常处理等等。

主要意图

       将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。

什么是SpringMvc?

       是基于Spring的MVC框架。

Spring初始化流程

  1. Spring web应用,部署在web容器中,web容器提供其一个全局的上下文环境,这个上下文就是ServletContext,其为后面的Spring IoC容器提供宿主环境
  2. 在web.xml中会提供有contextLoaderListener。在web容器启动时,会触发容器初始化事件
  3. 此时contextLoaderListener会监听到这个事件,其contextInitialized方法会被调用,在这个方法中,spring会初始化一个启动上下文,这个上下文被称为根上下文,即WebApplicationContext,
  4. WebApplicationContext是一个接口类,确切的说,其实际的实现类是XmlWebApplicationContext。这个就是spring的IoC容器,其对应的Bean定义的配置由web.xml中的context-param标签指定。
  5. 在这个IoC容器初始化完毕后,spring以WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE为属性Key,将其存储到ServletContext中,便于获取
  6. contextLoaderListener监听器初始化完毕后,开始初始化web.xml中配置的Servlet,这个servlet可以配置多个,以最常见的DispatcherServlet为例。
  7. DispatcherServlet实际上是一个标准的前端控制器,用以转发、匹配、处理每个servlet请求。DispatcherServlet上下文在初始化的时候会建立自己的IoC上下文,用以持有Spring mvc相关的bean。
  8. DispatcherServlet默认使用WebApplicationContext(ContextLoaderListener初始化产生)中的ServletContext中获取之前的根上下文
  9. 有了这个根上下文之后,再初始化自己持有的上下文。这个DispatcherServlet初始化自己上下文的工作在其initStrategies方法中可以看到,大概的工作就是初始化处理器映射、视图解析等。
  10. 这个servlet自己持有的上下文默认实现类也是xmlWebApplicationContext。初始化完毕后,spring以与servlet的名字相关(此处不是简单的以servlet名为Key)的属性为属性Key,也将其存到ServletContext中,以便后续使用。
  11. 这样每个servlet就持有自己的上下文,即拥有自己独立的bean空间,同时各个servlet共享相同的bean,即根上下文(第2步中初始化的上下文)定义的那些bean。

SpringMvc整个的执行流程:

  1. 发起请求到前端控制器(DispatcherServlet );
  2. DispatcherServlet 请求 HandlerMapping查找Handler(可以根据xml、注解进行查找);
  3. HandlerMapping 向前 DispatcherServlet返回Handler;
  4. DispatcherServlet 调用 HandlerAdapter 执行Handler;
  5. HandlerAdapter 执行 Handler;
  6. Handler执行完给处理器适配器返回ModelAndView;
  7. 处理器适配器向前端控制器返回ModelAndView (ModelAndView 是SpringMvc的底层对象包括model和view);
  8. 前端控制器请求视图解析器去解析视图,根据逻辑视图名解析成真正的视图(jsp);
  9. 前端控制器进行视图渲染
**前端控制器:** DispatcherServlet
**处理器映射器:** HandlerMapping
**处理器适配器:** HandlerAdapter

SpringMvc 和Struts2区别

       Struts2是类级别的拦截, 一个类对应一个request上下文,SpringMVC是方法级别的拦截,一个方法对应一个request上下文,而方法同时又跟一个url对应,所以说从架构本身上SpringMVC就容易实现restful url,而struts2的架构实现起来要费劲,因为Struts2中Action的一个方法可以对应一个url,而其类属性却被所有方法共享,这也就无法用注解或其他方式标识其所属方法了。
  由上边原因,SpringMVC的方法之间基本上独立的,独享request response数据,请求数据通过参数获取,处理结果通过ModelMap交回给框架,方法之间不共享变量,而Struts2搞的就比较乱,虽然方法之间也是独立的,但其所有Action变量是共享的,这不会影响程序运行,却给我们编码 读程序时带来麻烦,每次来了请求就创建一个Action,一个Action对象对应一个request上下文。
  由于Struts2需要针对每个request进行封装,把request,session等servlet生命周期的变量封装成一个一个Map,供给每个Action使用,并保证线程安全,所以在原则上,是比较耗费内存的。
   拦截器实现机制上,Struts2有以自己的interceptor机制,SpringMVC用的是独立的AOP方式,这样导致Struts2的配置文件量还是比SpringMVC大。
  SpringMVC的入口是servlet,而Struts2是filter(这里要指出,filter和servlet是不同的。以前认为filter是servlet的一种特殊),这就导致了二者的机制不同,这里就牵涉到servlet和filter的区别了。
  SpringMVC集成了Ajax,使用非常方便,只需一个注解@ResponseBody就可以实现,然后直接返回响应文本即可,而Struts2拦截器集成了Ajax,在Action中处理时一般必须安装插件或者自己写代码集成进去,使用起来也相对不方便。
  SpringMVC验证支持JSR303,处理起来相对更加灵活方便,而Struts2验证比较繁琐,感觉太烦乱。
  spring MVC和Spring是无缝的。从这个项目的管理和安全上也比Struts2高(当然Struts2也可以通过不同的目录结构和相关配置做到SpringMVC一样的效果,但是需要xml配置的地方不少)。
   设计思想上,Struts2更加符合OOP的编程思想, SpringMVC就比较谨慎,在servlet上扩展。
  SpringMVC开发效率和性能高于Struts2。
  SpringMVC可以认为已经100%零配置。
##如果1个接口有2个不同的实现, 那么怎么来Autowire指定某一个实现?
  @Qualifier(“ServiceName”)
  qualifier的意思是合格者,通过这个标示,表明了哪个实现类才是我们所需要的,我们修改调用代码,添加@Qualifier注解,需要注意的是@Qualifier的参数名称必须为我们之前定义@Service注解的名称之一!
##Spring的声明式事务 @Transaction注解一般写在什么位置? 抛出了异常会启动回滚吗?有没有办法控制不触发回滚?
   @Transactional 可以作用于接口、接口方法、类以及类方法上。当作用于类上时,该类的所有 public 方法将都具有该类型的事务属性,同时,我们也可以在方法级别使用该标注来覆盖类级别的定义。
  @Transactional 注解可以作用于接口、接口方法、类以及类方法上,但是 Spring 建议不要在接口或者接口方法上使用该注解,因为这只有在使用基于接口的代理时它才会生效。
  另外, @Transactional 注解应该只被应用到 public 方法上,这是由 Spring AOP 的本质决定的。如果你在 protected、private 或者默认可见性的方法上使用 @Transactional 注解,这将被忽略,也不会抛出任何异常。

@autowired 与new 区别

       new出来的对象无法调用@Autowired注入的Spring Bean,否则报空指针异常,
  @Autowired注入Spring Bean,则当前类必须也是Spring Bean才能调用它,不能用new xxx()来获得对象,这种方式获得的对象无法调用@Autowired注入的Bean。
原文来自:lyhkmm.com

正文到此结束
Loading...