Java面试题-Spring(三)
1.Spring的IOC和AOP机制
IOC是控制反转,AOP是面向切面编程。
主要用到的是设计模式有工厂模式和代理模式。
IOC就是典型的工厂模式,通过SessionFactory去注入实例。
AOP就是典型的代理模式的体现。
代理模式就是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。
Spring的IOC容器是Spring的核心,Spring AOP是Spring框架的重要组成部分。
在传统的程序设计中,当调用者需要被调用者的协助时,通常由调用者来创建被调用者的实例。但在Spring里创建被调用者的工作不再由调用者来完成,因此控制反转(IOC);创建被调用者实例的工作通常会由Spring容器来完成,然后注入调用者,因此也被称为依赖注入(DI),依赖注入和控制反转是同一个概念。
面向切面编程(AOP)是以另一个角度来考虑程序结构,通过分析程序结构的关注点来完善面对对象编程(OOP)。OOP将应用程序分解成各个层次的对象,而AOP将程序分解成多个切面。Spring AOP只实现了方法级别的连接点,在J2EE应用中,AOP拦截到方法级别的操作就已经足够。在Spring中,未来使IOC方便地使用健壮、灵活的企业服务,需要利用Spring AOP实现为IOC和企业服务之间建立联系。
IOC:控制反转
将对象交给容器管理,只需要在Spring配置文件中配置相应的Bean,以及设置相关的属性,让Spring容器来生成类的实例对象以及管理对象。在Spring容器启动的时候,Spring会把在配置文件中配置的Bean都初始化好,然后在需要调用的时候,就把它已经初始化好的那些Bean分配给需要调用的这些Bean的类(假设这个类名是A),分配的方法就是调用A的Setter方法来注入,而不需要在A里面new这些Bean。
AOP:面向切面编程
AOP可以说是对OOP的补充和完善。OOP引入封装、继承和多态性来建立一种对象层次结构,用以模拟公共行为的一个集合。当我们需要为分散的对象引入公共行为的时候,OOP就显得无能为力。也就是说,OOP允许定义从上到下的关系,但并不适合定义从左到右的关系。在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。将程序中的交叉业务逻辑(比如安全、日志、事务等),封装成一个切面,然后注入到目标对象(具体业务逻辑)中去。
实现AOP的技术,主要分为两大类:一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。
2.Spring中Autowired和Resource关键字的区别
@Resource和@Autowired都是做bean的注入时使用,其实@Resource并不是Spring的注解,它的包是javax.annotation.Resource,需要导入,但是Spring支持该注解的注入。
- 共同点
两者都可以写在字段和setter方法上。两者如果都写在字段上,那么就不需要再写setter方法。 - 不同点
- @Autowired
@Autowired为Spring提供的注解,需要导入包org.springframework.beans.factory.annotation.Autowired;只按照byType注入
@Autowired注解是按照类型(byType)装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置它的required的属性为false。如果我们想要使用按照名称(byName)来装配,可以结合@Qualifier注解一起使用。 - @Resource
@Resource默认按照ByName自动注入,由J2EE提供,需要导入包javax.annotation.Resource。
@Resource有两个重要的属性:name和type,而Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以,如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不制定name也不制定type属性,这时将通过反射机制使用byName自动注入策略。
@Resource装配顺序:
- 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常。
- 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常。
- 如果指定了type,则从上下文中找到类似匹配的唯一bean进行装配,找不到或是找到多个,都会抛出异常。
- 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配。@Resource的作用相当于@Autowired,只不过@Autowired按照byType自动注入。
3.依赖注入的方式有几种?各是什么?
依赖注入有三种方式,分别是构造器注入、setter方法注入、接口注入。
- 构造器注入:
将被依赖对象通过构造函数的参数注入给依赖对象,并且在初始化对象的时候注入。
优点:对象初始化完成后便可获得可使用的对象。
缺点:当需要注入的对象很多时,构造器参数列表将会很场,不够灵活。若有多种注入方式,每种方式只需注入指定几个依赖,那么就需要提供多个重载的构造函数,麻烦。 - setter方法注入:
IoC Service Provier通过调用成员变量提供的setter函数将被依赖对象注入给依赖类。
优点:灵活。可以选择性地注入需要的对象。
缺点:依赖对象初始化完成后由于尚未注入被依赖对象,因此还不能使用。 - 接口注入:
依赖类必须要实现指定的接口,然后实现该接口中的一个函数,该函数就是用于依赖注入。该函数的参数就是要注入的对象。
优点:接口注入中,接口的名字、函数的名字都不重要,只要保证函数的参数是要注入的对象类型即可。
缺点:侵入性太强,不建议使用。侵入的意思就是如果类A要使用别人提供的一个功能,弱为了使用者功能,需要在自己的类中增加额外的代码,这就是侵入性。
4.什么是Spring
Spring是一个轻量级的IoC和AOP容器框架。是为Java应用程序提供基础性服务的一套框架。目的是用于简化企业应用程序的开发,它使得开发者只需要关心业务需求。常见的配置方式有三种:基于xml的配置、基于直接的配置、基于Java的配置。
主要由以下几个模块组成:
- Spring Core:核心类库,提供IoC服务;
- Spring Context:提供框架式的Bean访问方式,以及企业级功能;
- Spring AOP:AOP服务;
- Spring DAO:对JDBC的抽象,简化了数据访问异常的处理;
- Spring ORM:对现有的ORM框架的支持;
- Spring Web:提供了基本的面向Web的综合特性;
- Spring MVC:提供了面向Web应用的Model-View-Controller实现。
5.Spring MVC流程
- 用户发送请求至前端控制器DispatcherServlet;
- DispatcherServlet收到请求调用HandlerMapping处理器映射器;
- 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet;
- DispatcherServlet调用HandlerAdapter处理器适配器;
- HandlerAdapter经过适配器调用具体的处理器Controller;
- Controller执行返回ModelAndView;
- HandlerAdapter将Controller执行结果ModelAndView返回DispatcherServlet;
- DispatcherServlet将ModelAndView传给ViewReslover视图解析器;
- ViewReslover解析后返回具体View;
- DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中);
- DispatcherServlet响应用户。
组件:
- 前端控制器DispatcherServlet,由框架提供
作用:接收请求,响应结果,相当于转发器,中央处理器。有了DispatcherServlet减少了与其它组件之间的耦合度。
用户请求到达前端控制器,它就相当于MVC模式中的C,DispatcherServlet是整个流程控制的中心,由它调用其它组件处理用户的请求。 - 处理器映射器HandlerMapping,由框架提供
作用:根据请求的url查找Handler
HandlerMapping负责根据用户请求找到Handler即处理器,SpringMVC提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。 - 处理器适配器HandlerAdapter
作用:按照特定规则(HandlerAdapter要求的规则)去执行Handler
通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展适配及可以对更多类型的处理器进行执行。 - 处理器Handler(需要自己开发)
Handler是继DispatcherServlet前端控制器的后端控制器,在DispatcherServlet的控制下Handler对具体的用户请求进行处理。
由于Handler涉及到具体的用户业务请求,所以一般情况下工程师需要根据业务需求开发Handler。
注意:编写Handler时按照HandlerAdapter的要求去做,这样适配器才可以正确执行Handler - 视图解析器ViewReslover,由框架提供
作用:进行视图解析,根据逻辑视图名解析成真正的视图。
ViewReslover负责将处理结果生成View视图,ViewReslover首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。 - 视图View(需要开发)
View是一个接口,支持不同的View类型(jsp等)
流程如下:
- 首先用户发送请求---->DispatcherServlet,前端控制器收到请求后自己不进行处理,而是委托给其他的解析器进行处理,作为统一访问点,进行全局的流程控制;
- DispatcherServlet---->HandlerMapping,HandlerMapping会将请求映射为HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象、多个HandlerInterceptor拦截器)对象,通过这种策略模式,很容易添加新的映射策略;
- DispatcherServlet---->HandlerAdapter,HandlerAdapter会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器;
- HandlerAdapter---->处理器功能处理方法的调用,HandlerAdapter将会根据适配的结果调用真正的处理器的功能处理方法,完成功能处理;并返回一个ModelAndView对象(包含模型数据、逻辑视图名);
- ModelAndView的逻辑视图名---->ViewReslover,ViewReslover将把逻辑视图名解析为具体的View,通过这种策略模式,很容易更换其他视图技术;
- View---->渲染,View会根据传进来的Model模型数据进行渲染,此处的Model实际上是一个Map数据结构,因此很容易支持其他视图技术;
- 返回控制权给DispatcherServlet,由DispatcherServlet返回响应给用户。