Spring 的理解

Spring 是一个开源框架,为简化企业级应用开发而生。Spring 可以是使简单的 JavaBean 实现以前只有 EJB 才能实现的功能。Spring 是一个 IOC 和 AOP 容器框架。

Spring 容器的主要核心是:

  • 控制反转(IOC),传统的 java 开发模式中,当需要一个对象时,我们会自己使用 new 或者 getInstance 等直接或者间接调用构造方法创建一个对象。而在 spring 开发模式中,spring 容器使用了工厂模式为我们创建了所需要的对象,不需要我们自己创建了,直接调用 spring 提供的对象就可以了,这是控制反转的思想。
  • 依赖注入(DI),spring 使用 javaBean 对象的 set 方法或者带参数的构造方法为我们在创建所需对象时将其属性自动设置所需要的值的过程,就是依赖注入的思想。
  • 面向切面编程(AOP),在面向对象编程(oop)思想中,我们将事物纵向抽成一个个的对象。而在面向切面编程中,我们将一个个的对象某些类似的方面横向抽成一个切面,对这个切面进行一些如权限控制、事物管理,记录日志等。公用操作处理的过程就是面向切面编程的思想。AOP 底层是动态代理,如果是接口采用 JDK 动态代理,如果是类采用CGLIB 方式实现动态代理。

使用Spring框架的好处是什么?缺点?

好处:

  • 轻量:Spring是轻量的,基本的版本大约2MB。
  • 控制反转:Spring通过控制反转实现了松散耦合,对象们给出它们的依赖,而不是创建或查找依赖的对象们。
  • 面向切面的编程(AOP):Spring支持面向切面的编程,并且把应用业务逻辑和系统服务分开。
  • 容器:Spring包含并管理应用中对象的生命周期和配置。
  • MVC 框架:Spring的WEB框架是个精心设计的框架,是Web框架的一个很好的替代品。
  • 事务管理:Spring提供一个持续的事务管理接口,可以扩展到上至本地事务下至全局事务(JTA)。
  • 异常处理:Spring提供方便的API把具体技术相关的异常(比如由JDBC,HibernateorJDO抛出的)转化为一致的unchecked异常。

缺点:

  • 依赖反射,影响性能。

Spring 中的设计模式有哪些

工厂模式:
BeanFactory就是简单工厂模式的体现,用来创建对象的实例;

单例模式:
Bean默认为单例模式。

代理模式:
Spring的AOP功能用到了JDK的动态代理和CGLIB字节码生成技术;

模板方法:
用来解决代码重复的问题。比如. RestTemplate, JmsTemplate, JpaTemplate。

观察者模式:
定义对象键一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知被制动更新,如Spring中listener的实现ApplicationListener。

IOC

Spring bean 的生命周期

  • Bean 定义:在配置文件里面用

    来进行定义。

  • Bean 初始化:有两种方式初始化:
    ①在配置文件中通过指定 init-method 属性来完成
    ②实现 org.springframwork.beans.factory.InitializingBean 接口

  • Bean 调用:有三种方式可以得到 bean 实例,并进行调用

  • Bean 销毁:销毁有两种方式
    ①使用配置文件指定的 destroy-method 属性
    ②实现 org.springframwork.bean.factory.DisposeableBean 接口

Spring支持的几种bean的作用域。

Spring框架支持以下五种bean的作用域:

  • singleton:bean在每个Springioc容器中只有一个实例。
  • prototype:一个bean的定义可以有多个实例。
  • request:每次http请求都会创建一个bean,该作用域仅在基于web的SpringApplicationContext情形下有效。
  • session:在一个HTTPSession中,一个bean定义对应一个实例。该作用域仅在基于web的SpringApplicationContext情形下有效。
  • global-session:在一个全局的HTTPSession中,一个bean定义对应一个实例。该作用域仅在基于web的SpringApplicationContext情形下有效。

缺省的Springbean的作用域是Singleton.

Spring 框架中的bean是线程安全的吗?

原型Bean

对于原型Bean,每次创建一个新对象,也就是线程之间并不存在Bean共享,自然是不会有线程安全的问题。

单例Bean

不,Spring框架中的单例bean不是线程安全的。

对于单例Bean,所有线程都共享一个单例实例Bean,因此是存在资源的竞争。

如果是一个无状态Bean,也就是线程中的操作不会对Bean的成员执行查询以外的操作,那么这个单例Bean是线程安全的。比如Spring mvc 的 Controller、Service、Dao等,这些Bean大多是无状态的,只关注于方法本身。

对于有状态的bean,Spring官方提供的bean,一般提供了通过ThreadLocal去解决线程安全的方法,比如RequestContextHolder、TransactionSynchronizationManager、LocaleContextHolder等。
注: Spring容器本身并没有提供线程安全的策略,因此是否线程安全完全取决于Bean本身的特性。

IOC注入哪几种方式?

  • 构造器:构造器依赖注入通过容器触发一个类的构造器来实现的,该类有一系列参数,每个参数代表一个对其他类的依赖。
  • setter:Setter方法注入是容器通过调用无参构造器或无参static工厂方法实例化bean之后,调用该bean的setter方法,即实现了基于setter的依赖注入。
  • 接口

复杂类型的注入

用于list结构的注入:list,array,set

用于map结构集合的注入:map,props

那种依赖注入的方式比较好?

两种依赖方式都可以使用,最好的解决方案是用构造器参数实现强制依赖,setter方法实现可选依赖。

ApplicationContext 通常的实现是什么?

  • FileSystemXmlApplicationContext 此容器从一个XML文件中加载beans的定义,XMLBean配置文件的全路径名必须提供给它的构造函数。
  • ClassPathXmlApplicationContext 此容器也从一个XML文件中加载beans的定义,这里,你需要正确设置classpath因为这个容器将在classpath里找bean配置。
  • AnnotationConfigApplicationContext:它是用于读取注解创建容器的。

BeanFactory和Applicationcontexts有什么区别?

Applicationcontexts提供一种方法处理文本消息,一个通常的做法是加载文件资源(比如镜像),它们可以向注册为监听器的bean发布事件。另外,在容器或容器内的对象上执行的那些不得不由bean工厂以程序化方式处理的操作,可以在Applicationcontexts中以声明的方式处理。Applicationcontexts实现了MessageSource接口,该接口的实现以可插拔的方式提供获取本地化消息的方法。适合单例对象使用

BeanFactory 多例对象使用 ,它在构建核心容器时,创建对象采取的策略是采用延迟加载的方式。也就是说,什么时候根据id获取对象了,什么时候才真正的创建对象。

不同方式的自动装配。

有五种自动装配的方式,可以用来指导Spring容器用自动装配方式来进行依赖注入。

  • no:默认的方式是不进行自动装配,通过显式设置ref属性来进行装配。
  • byName 通过参数名自动装配,Spring容器在配置文件中发现bean的autowire属性被设置成byname,之后容器试图匹配、装配和该bean的属性具有相同名字的bean。
  • byType::通过参数类型自动装配,Spring容器在配置文件中发现bean的autowire属性被设置成byType,之后容器试图匹配、装配和该bean的属性具有相同类型的bean。如果有多个bean符合条件,则抛出错误。
  • constructor :这个方式类似于byType,但是要提供给构造器参数,如果没有确定的带参数的构造器参数类型,将会抛出异常。
  • autodetect 首先尝试使用constructor来自动装配,如果无法工作,则使用byType方式。

自动装配有哪些局限性?

自动装配的局限性是:

重写:你仍需用和配置来定义依赖,意味着总要重写自动装配。

基本数据类型:你不能自动装配简单的属性,如基本数据类型,String字符串,和类。

模糊特性:自动装配不如显式装配精确,如果有可能,建议使用显式装配。

AOP

Spring 管理事务的方式?

  • 编程式事务:在代码中硬编码。
  • 声明式事务:在配置文件中配置
    声明式事务又分为:
    ①基于XML的声明式事务
    ②基于注解的声明式事务

面向切面编程

Joinpoint(连接点): 目标对象中所有可以增强的方法

Pointcut(切入点): 我们对其进行增强的方法.

Advice(通知/增强): 对切入点进行的增强操作

​ 包括前置通知,后置通知,异常通知,最终通知,环绕通知

Weaving(织入): 是指把增强应用到目标对象来创建新的代理对象的过程。

Aspect(切面): 是切入点和通知的结合。它将多个类的通用行为封装成可重用的模块,该模块含有一组API提供横切功能。比如,一个日志模块可以被称作日志的AOP切面。

Spring 的通知是什么?有哪几种类型?

Spring 切面可以应用五种类型的通知:

  • before:前置通知,在一个方法执行前被调用。
  • after: 在方法执行之后调用的通知,无论方法执行是否成功。
  • after-returning: 仅当方法成功完成后执行的通知。
  • after-throwing: 在方法抛出异常退出时执行的通知。
  • around: 在方法执行之前和之后调用的通知。

有几种不同类型的自动代理?

BeanNameAutoProxyCreator

DefaultAdvisorAutoProxyCreator

Metadataautoproxying

Spring的事务传播行为有哪些

1、PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。
2、PROPAGATION_SUPPORTS:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。
3、PROPAGATION_MANDATORY:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。
4、PROPAGATION_REQUIRES_NEW:创建新事务,无论当前存不存在事务,都创建新事务。
5、PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
6、PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
7、PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则按REQUIRED属性执行。

Spring事务的隔离级别

1、ISOLATION_DEFAULT:这是个 PlatfromTransactionManager 默认的隔离级别,使用数据库默认的事务隔离级别。
2、ISOLATION_READ_UNCOMMITTED:读未提交,允许另外一个事务可以看到这个事务未提交的数据。
3、ISOLATION_READ_COMMITTED:读已提交,保证一个事务修改的数据提交后才能被另一事务读取,而且能看到该事务对已有记录的更新。
4、ISOLATION_REPEATABLE_READ:可重复读,保证一个事务修改的数据提交后才能被另一事务读取,但是不能看到该事务对已有记录的更新。
5、ISOLATION_SERIALIZABLE:一个事务在执行的过程中完全看不到其他事务对数据库所做的更新。

Spring 的常用注解?

@Required:该注解应用于设值方法,过一个bean定义的显式的属性值或通过自动装配
@Autowired:该注解应用于有值设值方法、非设值方法、构造方法和变量。
@Qualifier:当有多个相同类型的bean却只有一个需要自动装配时,将@Qualifier注解和@Autowire注解结合使用以消除这种混淆,指定需要装配的确切的bean。

@Aspect

声明Bean的注解

  • @Component
  • @Service
  • @Controller
  • @Repository

SpringMVC

Spring MVC是一个基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web框架,通过把Model,View,Controller分离,将web层进行职责解耦,把复杂的web应用分成逻辑清晰的几部分,简化开发,减少出错,方便组内开发人员之间的配合。

SpringMVC 的工作原理?

  1. 用户向服务器发送请求,请求被 springMVC 前端控制器 DispatchServlet 捕获;
  2. DispatcherServle 对请求 URL 进行解析,得到请求资源标识符(URL),然后根据该 URL 调用 HandlerMapping,将请求映射到处理器 HandlerExcutionChain
  3. DispatchServlet 根据获得 Handler 选择一个合适的 HandlerAdapter 适配器处理;
  4. Handler 对数据处理完成以后将返回一个 ModelAndView()对象给 DisPatchServlet;
  5. Handler 返回的 ModelAndView()只是一个逻辑视图并不是一个正式的视图,DispatcherSevlet 通过
    ViewResolver 试图解析器将逻辑视图转化为真正的视图 View;
  6. DispatcherServle 通过 model 解析出 ModelAndView()中的参数进行解析最终展现出完整的 view 并返回给客户端;

首先,服务器的前端处理器会根据前端的request请求查找到相应的处理映射器,处理映射器会在控制层查找到相应的方法,控制层再通过业务层来实现具体的业务操作(包括对数据库的处理,调用)如何再封装到相应的视图层,在视图层封装之后再通过业务层和控制层传回用户。

说说Spring MVC的几个重要组件?

1.前端控制器 DispatcherServlet
作用:接收请求、响应结果,相当于转发器,有了DispatcherServlet 就减少了其它组件之间的耦合度。
2.处理器映射器HandlerMapping
作用:根据请求的URL来查找Handler
3.处理器适配器HandlerAdapter
注意:在编写Handler的时候要按照HandlerAdapter要求的规则去编写,这样适配器HandlerAdapter才可以正确的去执行Handler。
4.处理器Handler
5.视图解析器 ViewResolver
作用:进行视图的解析,根据视图逻辑名解析成真正的视图(view)
6.视图View
View是一个接口, 它的实现类支持不同的视图类型(jsp,freemarker,pdf等等)

SpringMVC 常用注解都有哪些?

  • @requestMapping 用于请求 url 映射。
  • @RequestBody 注解实现接收 http 请求的 json 数据,将 json 数据转换为 java 对象。
  • @ResponseBody 注解实现将 controller 方法返回对象转化为 json 响应给客户。
  • @PathVariable URL 中占位符参数绑定到控制器处理方法的入参中
  • @Cacheable 标记缓存查询
  • @CacheEvict 清空缓存

@RestController = @ResponseBody + @Controller

如何开启注解处理器和适配器?

springmvc.xml 中通过开启 ``来实现注解处理器和适配器的开启。

如何解决 get 和 post 乱码问题?

post 请求乱码:
web.xml 里边配置一个 CharacterEncodingFilter 过滤器。设置为 utf-8

get 请求的乱码:
两种方法:
①修改 tomcat 配置文件添加编码与工程编码一致。
②对参数进行重新编码 String userName = New String(Request.getParameter("userName").getBytes("ISO8859-1"),"utf-8");

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

1、转发:在返回值前面加"forward:"
2、重定向:在返回值前面加"redirect:"