素材巴巴 > 程序开发 >

Spring及SpringMvc

程序开发 2023-09-04 07:29:21

Spring

什么是 Spring IOC 容器?

Spring 框架的核心是 Spring 容器。容器创建对象,将它们装配在一起,配置它们并管理它们的完整生命周期。Spring 容器使用依赖注入来管理组成应用程序的组件。容器通过读取提供的配置元数据来接收对象进行实例化,配置和组装的指令。该元数据可以通过 XML,Java 注解、 Java 代码提供。
在这里插入图片描述

什么是依赖注入?

在依赖注入中,您不必创建对象,但必须描述如何创建它们。您不是直接在代码中将组件和服务连接在一起,而是描述配置文件中哪些组件需要哪些服务。由 IoC 容器将它们装配在一起。

可以通过多少种方式完成依赖注入?

通常,依赖注入可以通过三种方式完成,即:

在 Spring Framework 中,仅使用构造函数和 setter 注入。

构造函数注入和 setter 注入的区别。

在这里插入图片描述

Spring 中有多少种 IOC 容器?

  1. BeanFactory - BeanFactory 就像一个包含 bean 集合的工厂类。它会在客户端要求时实例化 bean。
  2. ApplicationContext - ApplicationContext 接口扩展了 BeanFactory 接口。它在 BeanFactory 基础上提供了一些额外的功能。

区分 BeanFactory 和 ApplicationContext

在这里插入图片描述

列举 IoC 的一些好处

Spring IoC 的实现机制?

Spring 中的 IoC 的实现原理就是工厂模式加反射机制。

interface Fruit {public abstract void eat();
 }
 class Apple implements Fruit {public void eat(){System.out.println("Apple");}
 }
 class Orange implements Fruit {public void eat(){System.out.println("Orange");}
 }
 class Factory {public static Fruit getInstance(String ClassName) {Fruit f=null;try {f=(Fruit)Class.forName(ClassName).newInstance();} catch (Exception e) {e.printStackTrace();}return f;}
 }
 class Client {public static void main(String[] a) {Fruit f=Factory.getInstance("io.github.dunwu.spring.Apple");if(f!=null){f.eat();}}
 }
 

什么是 spring bean?

Spring 提供了哪些配置方式?

基于 xml 配置
bean 所需的依赖项和服务在 XML 格式的配置文件中指定。这些配置文件通常包含许多 bean 定义和特定于应用程序的配置选项。它们通常以 bean 标签开头。例如:


 
 

基于注解配置
您可以通过在相关的类,方法或字段声明上使用注解,将 bean 配置为组件类本身,而不是使用 XML 来描述 bean 装配。默认情况下,Spring 容器中未打开注解装配。因此,您需要在使用它之前在 Spring 配置文件中启用它。例如:


 
 

基于 Java API 配置
Spring 的 Java 配置是通过使用@Bean 和 @Configuration 来实现。
@Bean 注解扮演与 元素相同的角色。
有@Configuration 的类允许通过简单地调用同一个类中的其他@Bean 方法来定义 bean 间依赖关系。

public class StudentConfig {@Beanpublic StudentBean myStudent() {return new StudentBean();}
 }
 

Spring 支持集中 bean scope(作用域)?

Spring bean 支持 5 种 scope:

  1. Singleton - 每个 Spring IoC 容器仅有一个单实例。
  2. Prototype - 每次请求都会产生一个新的实例。
  3. Request - 每一次 HTTP 请求都会产生一个新的实例,并且该 bean 仅在当前 HTTP 请求内有效。
  4. Session - 每一次 HTTP 请求都会产生一个新的 bean,同时该 bean 仅在当前 HTTP session 内有效。
  5. Global-session - 类似于标准的 HTTP Session 作用域,不过它仅仅在基于 portlet 的 web 应用中才有意义。Portlet 规范定义了全局 Session 的概念,它被所有构成某个 portlet web 应用的各种不同的 portlet 所共享。在 global session 作用域中定义的 bean 被限定于全局 portlet Session 的生命周期范围内。如果你在 web 中使用 global session 作用域来标识 bean,那么 web 会自动当成 session 类型来使用。

仅当用户使用支持 Web 的 ApplicationContext 时,最后三个才可用。

Spring bean 容器的生命周期是什么样的?

Spring bean 容器的生命周期流程如下:

  1. Spring 容器根据配置中的 bean 定义中实例化 bean。
  2. Spring 使用依赖注入填充所有属性,如 bean 中所定义的配置。
  3. 如果 bean 实现 BeanNameAware 接口,则工厂通过传递 bean 的 ID 来调用 setBeanName()。
  4. 如果 bean 实现 BeanFactoryAware 接口,工厂通过传递自身的实例来调用 setBeanFactory()。
  5. 如果存在与 bean 关联的任何 BeanPostProcessors,则调用 preProcessBeforeInitialization() 方法。
  6. 如果为 bean 指定了 init 方法( 的 init-method 属性),那么将调用它。
  7. 最后,如果存在与 bean 关联的任何 BeanPostProcessors,则将调用 postProcessAfterInitialization() 方法。
  8. 如果 bean 实现 DisposableBean 接口,当 Spring 容器关闭时,会调用 destory()。
  9. 如果为 bean 指定了 destroy 方法( 的 destroy-method 属性),那么将调用它。

什么是 Spring 的内部 bean?

只有将 bean 用作另一个 bean 的属性时,才能将 bean 声明为内部 bean。为了定义 bean,Spring 的基于 XML 的配置元数据在 中提供了元素的使用。内部 bean 总是匿名的,它们总是作为原型。
例如,假设我们有一个 Student 类,其中引用了 Person 类。这里我们将只创建一个 Person 类实例并在 Student 中使用它。

public class Student {private Person person;//Setters and Getters
 }
 public class Person {private String name;private String address;//Setters and Getters
 }
 

 
 

什么是 spring 装配

当多个 bean 在 Spring 容器中组合在一起时,它被称为装配或 bean 装配。 Spring 容器需要知道需要什么 bean 以及容器应该如何使用依赖注入来将 bean 绑定在一起,同时装配 bean。

自动装配有哪些方式?

Spring 容器能够自动装配 bean。也就是说,可以通过检查 BeanFactory 的内容让 Spring 自动解析 bean 的协作者。

自动装配的不同模式:

  1. no - 这是默认设置,表示没有自动装配。应使用显式 bean 引用进行装配。
  2. byName - 它根据 bean 的名称注入对象依赖项。它匹配并装配其属性与 XML 文件中由相同名称定义的 bean。
  3. byType - 它根据类型注入对象依赖项。如果属性的类型与 XML 文件中的一个 bean 名称匹配,则匹配并装配属性。
  4. 构造函数 - 它通过调用类的构造函数来注入依赖项。它有大量的参数。
  5. autodetect - 首先容器尝试通过构造函数使用 autowire 装配,如果不能,则尝试通过 byType 自动装配。

自动装配有什么局限?

你用过哪些重要的 Spring 注解?

@Required 注解有什么用?

@Required 应用于 bean 属性 setter 方法。此注解仅指示必须在配置时使用 bean 定义中的显式属性值或使用自动装配填充受影响的 bean 属性。如果尚未填充受影响的 bean 属性,则容器将抛出 BeanInitializationException。

public class Employee {private String name;@Requiredpublic void setName(String name){this.name=name;}public string getName(){return name;}
 }
 

@Autowired 注解有什么用?

@Autowired 可以更准确地控制应该在何处以及如何进行自动装配。此注解用于在 setter 方法,构造函数,具有任意名称或多个参数的属性或方法上自动装配 bean。默认情况下,它是类型驱动的注入。

public class Employee {private String name;@Autowiredpublic void setName(String name) {this.name=name;}public string getName(){return name;}
 }
 

@Qualifier 注解有什么用?

当创建多个相同类型的 bean 并希望仅使用属性装配其中一个 bean 时,您可以使用@Qualifier 注解(指定bean的名称)和 @Autowired 通过指定应该装配哪个确切的 bean 来消除歧义。
例如,这里我们分别有两个类,Employee 和 EmpAccount。在 EmpAccount 中,使用@Qualifier 指定了必须装配 id 为 emp1 的 bean。

@RequestMapping 注解有什么用?

答:@RequestMapping 注解用于将特定 HTTP 请求方法映射到将处理相应请求的控制器中的特定类或方法。此注解可应用于两个级别:

列举 spring 支持的事务管理类型

Spring 支持两种类型的事务管理:
程序化事务管理:在此过程中,在代码编程的帮助下管理事务。它为您提供极大的灵活性,但维护起来非常困难。
声明式事务管理:在此过程中,事务管理与业务代码分离。仅使用注解或基于 XML 的配置来管理事务。

事务的传播行为?

事务的第一个方面是传播行为(propagation behavior)。当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行。

传播行为含义PROPAGATION_REQUIRED(默认)表示当前方法必须运行在事务中。如果当前事务存在,方法将会在该事务中运行。否则,会启动一个新的事务。外围方法开启事务的情况下Propagation.REQUIRED修饰的内部方法会加入到外围方法的事务中,所有Propagation.REQUIRED修饰的内部方法和外围方法均属于同一事务,只要一个方法回滚,整个事务均回滚。PROPAGATION_SUPPORTS表示当前方法不需要事务上下文,但是如果存在当前事务的话,那么该方法会在这个事务中运行PROPAGATION_MANDATORY表示该方法必须在事务中运行,如果当前事务不存在,则会抛出一个异常PROPAGATION_REQUIRED_NEW外围方法未开启事务的情况下Propagation.REQUIRES_NEW修饰的内部方法会新开启自己的事务,且开启的事务相互独立,互不干扰。在外围方法开启事务的情况下Propagation.REQUIRES_NEW修饰的内部方法依然会单独开启独立事务,且与外部方法事务也独立,内部方法之间、内部方法和外部方法事务均相互独立,互不干扰。PROPAGATION_NOT_SUPPORTED表示该方法不应该运行在事务中。如果存在当前事务,在该方法运行期间,当前事务将被挂起。如果使用JTATransactionManager的话,则需要访问TransactionManagerPROPAGATION_NEVER表示当前方法不应该运行在事务上下文中。如果当前正有一个事务在运行,则会抛出异常PROPAGATION_NESTED在外围方法开启事务的情况下Propagation.NESTED修饰的内部方法属于外部事务的子事务,外围主事务回滚,子事务一定回滚,而内部子事务可以单独回滚而不影响外围主事务和其他子事务

Spring使用@Transactional开启事务那种情况会失效?

@Transactional的使用:

不会回滚的情况:

什么是 AOP?

AOP(Aspect-Oriented Programming), 即 面向切面编程, 它与 OOP( Object-Oriented Programming, 面向对象编程) 相辅相成, 提供了与 OOP 不同的抽象软件结构的视角. 在 OOP 中, 我们以类(class)作为我们的基本单元, 而 AOP 中的基本单元是 Aspect(切面)

AOP 中的 Aspect、Advice、Pointcut、JointPoint 和 Advice 参数分别是什么?

在这里插入图片描述

什么是通知(Advice)?

特定 JoinPoint 处的 Aspect 所采取的动作称为 Advice。Spring AOP 使用一个 Advice 作为拦截器,在 JoinPoint “周围”维护一系列的拦截器。

有哪些类型的通知(Advice)?

指出在 spring aop 中 concern 和 cross-cutting concern 的不同之处

concern 是我们想要在应用程序的特定模块中定义的行为。它可以定义为我们想要实现的功能。

cross-cutting concern 是一个适用于整个应用的行为,这会影响整个应用程序。例如,日志记录,安全性和数据传输是应用程序几乎每个模块都需要关注的问题,因此它们是跨领域的问题。

AOP 有哪些实现方式?

实现 AOP 的技术,主要分为两大类:

什么叫静态代理?

代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强。值得注意的是,代理类和被代理类应该共同实现一个接口,或者是共同继承某个类,然后通过调用相同的方法来调用目标对象的方法。整个过程发生在编译前。所以叫静态代理。

优点:可以做到在不修改目标对象的功能前提下,对目标功能扩展.
缺点:因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类,类太多。同时,一旦接口增加方法,目标对象与代理对象都要维护。

什么叫动态代理?

动态代理主要是通过反射机制,在运行时动态生成所需代理的class。

动态代理的实现方式有几种?

第一种:JDK自带的动态代理【InvocationHandler】
JDK的动态代理底层是通过Java反射机制实现的,并且需要目标对象继承自一个接口才能生成它的代理类。

第二种:CGLIB:这个是高级的字节码生成库,总体性能比JDK动态代理好,且功能强大。
和JDK代理不同,CGLib动态代理技术不需要目标对象实现自一个接口,只需要实现一个处理代理逻辑的切入类,并实现MethodInterceptor接口。
CgLib的特点:

第三种:Javassist:这个是高级的字节码生成库,总体性能比JDK动态代理好,且功能强大。
Javassist是一个开源的分析、编辑和创建Java字节码的类库,可以直接编辑和生成Java生成的字节码。
相对于bcel, asm等这些工具,开发者不需要了解虚拟机指令,就能动态改变类的结构,或者动态生成类。

第四种:ASM:低级字节码生成工具,近乎使用bytecode编码,对开发人员要求最高。当然性能也是最好(相比前几种也不是很大的提升)。

Spring AOP and AspectJ AOP 有什么区别?

Spring AOP 基于动态代理方式实现;AspectJ AOP 基于静态代理方式实现。 Spring AOP 仅支持方法级别的 PointCut;提供了完全的 AOP 支持,它还支持属性级别的 PointCut。

如何理解 Spring 中的代理?

将 Advice 应用于目标对象后创建的对象称为代理。在客户端对象的情况下,目标对象和代理对象是相同的。

什么是编织(Weaving)?

为了创建一个 advice 对象而链接一个 aspect 和其它应用类型或对象,称为编织(Weaving)。在 Spring AOP 中,编织在运行时执行。请参考下图:
在这里插入图片描述

什么是Spring MVC?

Spring Web MVC 框架提供 模型-视图-控制器 架构和随时可用的组件,用于开发灵活且松散耦合的 Web 应用程序。 Spring MVC是一个基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web框架,通过把Model,View,Controller分离,将web层进行职责解耦,把复杂的Web应用分成逻辑清晰的几部分,简化开发,减少出错,方便组内开发人员之间的配合。

Spring MVC的主要组件?

(1)前端控制器 DispatcherServlet(不需要程序员开发)
作用:接收请求、响应结果,相当于转发器,有了DispatcherServlet 就减少了其它组件之间的耦合度。

(2)处理器映射器HandlerMapping(不需要程序员开发)
作用:根据请求的URL来查找Handler

(3)处理器适配器HandlerAdapter
注意:在编写Handler的时候要按照HandlerAdapter要求的规则去编写,这样适配器HandlerAdapter才可以正确的去执行Handler。

(4)处理器Handler(需要程序员开发)

(5)视图解析器 ViewResolver(不需要程序员开发)
作用:进行视图的解析,根据视图逻辑名解析成真正的视图(view)

(6)视图View(需要程序员开发jsp)
View是一个接口, 它的实现类支持不同的视图类型(jsp,freemarker,pdf等等)

Spring MVC的流程?

(1) 用户发送请求至前端控制器DispatcherServlet;
(2) DispatcherServlet收到请求后,调用HandlerMapping处理器映射器,请求获取Handler;
(3) 处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet;
(4) DispatcherServlet调用HandlerAdapter处理器适配器;
(5) HandlerAdapter经过适配调用具体处理器(Handler,也叫后端控制器);
(6) Handler执行完成返回ModelAndView;
(7) HandlerAdapter将Handler执行结果ModelAndView返回给DispatcherServlet;
(8) DispatchServet将ModelAndView传给ViewResvoler视图解析器进行解析;
(9) ViewResvoler解析后返回View;
(10) DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中);
(11)DispatcherServlet响应用户;
在这里插入图片描述

SpringMVC和struts2的区别有哪些?

(1)springmvc的入口是一个servlet即前端控制器(DispatchServlet),而struts2入口是一个filter过滤器(StrutsPrepareAndExecuteFilter)。

(2)springmvc是基于方法开发(一个url对应一个方法),请求参数传递到方法的形参,可以设计为单例或多例(建议单例),struts2是基于类开发,传递参数是通过类的属性,只能设计为多例。

(3)Struts采用值栈存储请求和响应的数据,通过OGNL存取数据,springmvc通过参数解析器是将request请求内容解析,并给方法形参赋值,将数据和视图封装成ModelAndView对象,最后又将ModelAndView中的模型数据通过reques域传输到页面。Jsp视图解析器默认使用jstl。

SpringMVC怎么样设定重定向和转发的?

(1)转发:在返回值(String)前面加"forward:“,譬如"forward:user.do?name=method4”
(2)重定向:在返回值(String)前面加"redirect:“,譬如"redirect:http://www.baidu.com”

SpringMvc怎么和AJAX相互调用的?

通过json框架就可以把Java里面的对象直接转化成 Js 可以识别的Json对象。具体步骤如下 :
(1)加入 json 对应的jar包
(2)在配置文件中配置json的映射
(3)在接受Ajax方法里面可以直接返回Object,List等,但方法前面要加上@ResponseBody注解。

如何解决POST请求中文乱码问题,GET的又如何处理呢?

(1)解决post请求乱码问题:
在web.xml中配置一个CharacterEncodingFilter过滤器,设置成utf-8;

CharacterEncodingFilterorg.springframework.web.filter.CharacterEncodingFilterencodingutf-8
 
 CharacterEncodingFilter/*
 
 

(2)get请求中文参数出现乱码解决方法有两个:
①修改tomcat配置文件添加编码与工程编码一致,如下:

②另外一种方法对参数进行重新编码:
String userName = new String(request.getParamter("userName").getBytes("ISO8859-1"),"utf-8")
ISO8859-1是tomcat默认编码,需要将tomcat编码后的内容按utf-8编码。

Spring MVC的异常处理 ?

可以将异常抛给Spring框架,由Spring框架来处理;我们只需要配置简单的异常处理器,在异常处理器中添视图页面即可。

Spring怎么处理全局异常?

答:@ControllerAdvice作用再异常处理类。
@ExceptionHandler(CustomGenericException.class)作用在方法上,说明该方法处理的异常类型。
@ResponseBody作用在方法上表示返回的都是json数据

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

是单例模式

存在的问题:在多线程访问的时候有线程安全问题,不要用同步,会影响性能的。解决方案是在控制器里面不能写字段。

SpringMVC常用的注解有哪些?

@RequestMapping:用于处理请求 url 映射的注解,可用于类或方法上。用于类上,则表示类中的所有响应请求的方法都是以该地址作为父路径。
@RequestBody:注解实现接收http请求的json数据,将json转换为java对象。
@ResponseBody:注解实现将conreoller方法返回对象转化为json对象响应给客户。

SpingMvc中的控制器的注解一般用那个,有没有别的注解可以替代?

一般用@Controller注解,也可以使用@RestController,@RestController注解相当于@ResponseBody + @Controller,表示是表现层,除此之外,一般不用别的注解代替。

如果在拦截请求中,我想拦截get方式提交的方法,怎么配置?

可以在@RequestMapping注解里面加上method=RequestMethod.GET。或者使用 @GetMapping()注解

怎样在方法里面得到Request,或者Session?

直接在方法的形参中声明request,SpringMvc就自动把request对象传入。

如果想在拦截的方法里面得到从前台传入的参数,怎么得到?

直接在形参里面声明这个参数就可以,但必须名字和传过来的参数一样,也可以用Java对象封装。

如果是json类型数据的话使用注解@RequestBody,json中的数据都封装到java类型对象中去。

如果前台有很多个参数传入,并且这些参数都是一个对象的,那么怎么样快速得到这个对象?

直接在方法中声明这个对象,SpringMvc就自动会把属性赋值到这个对象里面,属性名称和参数名称要一致。

SpringMvc中函数的返回值是什么?

返回值可以有很多类型,有String, ModelAndView。ModelAndView类把视图和数据都合并的一起的,但一般用String比较好。

SpringMvc用什么对象从后台向前台传递数据的?

通过ModelMap对象,可以在这个对象里面调用put方法,把对象加到里面,前台就可以通过el表达式拿到。

怎么样把ModelMap里面的数据放入Session里面?

可以在类上面加上@SessionAttributes注解,里面包含的字符串就是要放入session里面的key。

SpringMvc里面拦截器是怎么写的?

有两种写法,一种是实现HandlerInterceptor接口,另外一种是继承适配器类,接着在接口方法当中,实现处理逻辑;然后在SpringMvc的配置文件中配置拦截器即可:


 

Spring源码分析

SpringAOP在什么时候创建aop代理对象?

参考博客:https://blog.csdn.net/gongsenlin341/article/details/111240114

可以分成两类,提前和非提前生成代理对象。

非提前生成代理对象
非提前生成代理对象 是在属性填充populateBean完成之后,执行了initializeBean方法的时候进行的动态代理。

提前生成代理对象
提前动态代理,其实是在依赖注入的时候,也就是在populateBean属性填充方法内完成的。

生命周期源码分析

参考博客:https://www.cnblogs.com/xushuanglong/p/14632982.html


标签:

素材巴巴 Copyright © 2013-2021 http://www.sucaibaba.com/. Some Rights Reserved. 备案号:备案中。