KYLO的Spring知识总结

本文概述Spring的核心特点,如轻量级、控制反转、面向切面和容器管理。深入解析Spring IOC原理、BeanFactory与ApplicationContext,讨论AOP在Spring中的实现,以及SpringMVC的工作原理和Spring在依赖注入和自动装配中的运用。
摘要由CSDN通过智能技术生成

Spring

Spring特点

  • 轻量级:从大小和开销两方面来说,Spring都是轻量级的。完整的Spring框架可以再一个大小只有1M多的JAR文件里面发布,并且Spring所需的处理开销也是微不足道的。此外Spring是非侵入式的,Spring应用中的对象不依赖于Spring的特定类。
  • 控制反转:IOC,Spring通过控制反转促进了低耦合,当应用了IOC,一个对象依赖的其他对象会被通过被动待方式传递进来,而不是这个对象自己创建或者查找依赖对象
  • 面向切面:AOP,Spring支持面向切面编程,并且把应用业务逻辑和系统服务分开
  • 容器:Spring包含并管理应用对象的配置生命周期,再这个意义上他是一种容器,你可以配置你的每一个Bean如何被创建,基于一个可配置原型,你的bean可以创建一个单独的实例或者每次需要时都生成一个新的实例,以及他们时如何互相关联的。
  • 框架集合:Spring 可以将简单的组件配置,组合成复杂的应用。在spring中,应用对象被声明式的组合,典型的是在一个xml文件里。

*非侵入式:即我们进行开发时,不需要知道spring的实现,例如不需要继承spring中的某个类才能使用。着就是非侵入式。

SpringIOC原理

Spring通过一个配置文件描述Bean即Bean之间的依赖关系,利用java语言的反射功能实例化Bean并建立Bean之间的依赖关系。Spring的Ioc容器在完成这些底层工作的基础上,还提供了Bean实例缓存、生命周期管理、Bean实例代理、时间发布、资源装载等高级服务。

Spring启动时读取应用程序提供的Bean配置信息,并在Spring容器生成一份相应的Bean配置注册表,然后根据这张注册表实例化Bean,装配好Bean之间的依赖关系,为上层引用提供准备就绪的运行环境。其中Bean缓存池为HashMap实现

IOC容器实现

BeanFactory-框架基础设施

BeanFactory,是Spring框架的基础设施,面向Spring本身,是提供容器基本功能的接口。ApplicationContext面向使用Spring容器的开发者,功能更偏向使用。几乎所有的使用场景我们都直接使用ApplicationContext而非BeanFactory。

1) BeanDefinitionRegistry注册表

Spring配置文件中,每一个节点元素在Spring容器中都通过一个BeanDefiniton对象表示,它描述了Bean的配置信息。而BeanDefinitionRegistry接口提供了向容器手工注册BeanDefinition对象的方法

2)BeanFactory顶层接口

容器顶端的接口,提供给Bean容器最基本的功能。其最主要的方法就是通过getBean方法获取Bean实例。这个接口只规定了Bean的基本行为,不关心Bean是如何产生的。BeanFactory的功能通过其他接口得到不断的扩展

3)ListableBeanFactory-BeanFactory子接口

该接口定义了访问容器中Bean基本信息的若干方法,如查看Bean个数、获取某一类型Bean的配置名、查看容器是否包含某一Bean等方法。在BeanFactory的基础上提供了列举所有Bean的能力,不需要在根据要求一个一个getBean,需要预加载所有Bean的BeanFactory实例可以实现此接口

4)HierarchicalBeanFactory父子级联

父子级联IOC容器的接口,子容器可以通过接口方法访问父容器;通过HierarchicalBeanFactory接口,Spring的IOC容器可以建立父子层级关联的容器体系,子容器可以访问父容器中的Bean,但父容器不能访问子容器中的Bean。Spring使用父子容器实现了很多功能,比如在SpringMVC中,展现层Bean位于一个子容器中,而业务层和持久层的Bean位于父容器中。这样,控制层Bean就可以引用业务层和持久层的Bean,而业务层和持久层的Bean看不到控制层的Bean。

5)ConfigurableBeanFactory

是一个重要的接口,增强了IOC容器的可定制性,它定义了设置类装载器、属性编辑器、容器初始化后置处理器等方法。也就是提供给容器自定义配置的方法

6)AutowireCapableBeanFactory

定义了将Bean容器中Bean按照某种规则进行自动装配的方法

7)SingletonBeanRegistry运行期间注册单例Bean

定义了运行在运行期间向容器注册单例Bean的方法;对于单例的Bean来说,BeanFactory会缓存Bean实例,所以第二次使用getBean获取Bean是将直接从IOC容器的缓存中获取Bean实例。Spring在DefaultSingletonBeanRegistry类中提供了一个用于缓存单实例Bean的缓存器,它是一个用HashMap实现的缓存器,单实例的Bean以beanName为键保存在zhegeHashMap中。

8)依赖日志框架

在初始化BeanFactory时,必须为其提供一种日志框架,比如使用log4j,即在类路径下提供log4j配置文件,这样启动Spring容器才不会出错。

9)DefaultListableBeanFactory

第一个真正可以独立运行的IOC容器

BeanDefinition

SpringIOC容器管理定义了我们定义的各种Bean对象及其相互的关系,Bean对象在Spring实现中是以BeanDefinition来描述的。Bean解析主要就是对Spring配置文件的解析。这个解析过程主要通过BeanDefintionReader等对象完成。

ApplicationContext面向开发应用,应用上下文

ApplicationContext,由BeanFactory派生而来,提供了更多面向实际应用的功能,ApplicationContext继承了HierarchicalBeanFactory和ListableBeanFactory接口,在此基础上,还通过多个其他的接口拓展了BeanFactory的功能

1)ClassPathXmlApplicationContext:默认从类路径加载配置文件

2)FileSystemXmlApplicationContext:默认从文件系统中装载配置文件

3)ApplicationEventPublisher:让容器拥有发布应用上下文事件的能力,包括启动事件、关闭事件等。

4)MessageSource:为应用提供国际化消息访问的功能

5)resourcePatternResolver:为所有ApplicationContext实现类都实现了类似于PathMatchingResourceResolver的功能,可以通过带前缀的Ant风格的资源文件路径装载Spring的配置文件

6)LifeCycle:该接口是Spring2.0加入的,该接口提供了start()和stop()两个方法,主要用于控制异步处理过程,在具体使用时,该接口同时被ApplicationContext实现及具体Bean实现,ApplicationContext会将start/stop的信息传递给容器中所有实现了该接口的Bean,以达到管理和控制JMX、任务调度等目的。

7)ConfiguableApplicationContext扩展于ApplicationContext,它新增加了两个主要的方法:refresh()和close(),让Application具有启动、刷新和关闭应用上下文的能力。在应用上下文关闭的情况下调用refresh()即可启动应用上下文,在已经启动的状态下,调用refresh()则清除缓存并重新装载配置信息,而调用close()则可关闭应用上下文。

IOC容器的初始化

IOC容器的初始化包括BeanDefinition的Resource定位、载入和注册这三个基本的过程。

WebApplication 体系架构

SpringBean作用域

Singleton(单例模式):spring ioc容器只会存在一个共享的Bean实例,无论有多少个Bean引用他,始终指向同一对象。该模式在多线程下是不安全的。Singleton作用域是Spring中的默认作用域,也可以显式将Bean定义为Singleton模式

Prototype(原型模式):每次通过Spring ioc容器获取prototype定义的Bean时,容器都将创建一个新的Bean实例,每个Bean实例都有自己的属性和状态,而singleton全局只有一个对象。根据经验,对有状态的Bean使用prototype作用域,而对无状态的bean使用singleton作用域

Request(一次request一个实例):在一次http请求中,容器会返回该Bean的同一实例。而对不同的Http请求则会产生新的Bean,而且该Bean仅在当前HttpReque内有效,当前Http请求结束,该Bean实例也将会被销毁。

Session:在一次HttpSession中,容器会返回该Bean的同一实例。而对不同的Session请求则会创建新的实例,该Bean实例仅在当前session内有效,同Http请求相同,每一次Session请求创建新的实例,而不同的实例之间不共享属性,且实例仅在自己的session请求内有效,请求结束,则实例将被销毁。

global Session:在一个全局的Http Session中,容器会返回该Bean的同一个实例,仅在使用portlet context时有效。

Spring Bean生命周期

1)实例化:实例化一个Bean,也就是我们常说的new。

2)IOC依赖注入:按照Spring上下文对实例化的Bean进行配置,也就是IOC注入。

3)setBeanName实现:如果这个Bean已经实现了BeanNameAware接口,会调用它实现的setBeanName(String)方法,此处传递的就是Spring配置文件中的id值。

4)BeanFactoryAware实现:如果这个Bean已经实现了BeanFactoryAware接口,会调用它实现的setBeanFactory,setBeanFactory(BeanFactory) 传递的时spring的工厂自身(可以用这种方式来获取其他的Bean,只需要在Spring配置文件中配置一个普通的Bean即可)

5)ApplicationContextAware实现:如果这个Bean已经实现了ApplicationContextAware接口,会调用setApplicationContext(ApplicationContext)方法,传入Spring上下文(同样这个方式也可以实现步骤四的内容,但是比四更丰富,因为ApplicationContext比BeanFactory的功能更丰富)

6)postProcessBeforeInitialization接口实现-初始化预处理:如果这个Bean关联了BeanPostProcessor接口,将会调用postProcessBeforeInitialization(Object obj,String s)方法,BeanPostProcessor经常被用作是Bean内容的更改,并且由于这个是在Bean初始化的时候调用那的那个方法,也可以被应用于内存或者缓存技术。

7)init-method:如果Bean在Spring配置文件中配置了init-method属性,会自动调用其配置的初始化方法。

8)postProcessAfterInitialization初始化后处理:如果这个Bean关联了BeanPostProcessor接口,将会调用postProcessAfterInitialization(Object obj,String s) 方法。

在以上工作完成以后就可以应用这个Bean了,那这个bean是一个Singleton的,所以一般情况下我们调用同一个id的Bean会是在内容地址相同的实例,当然在Spring配置文件中也可以配置非singleton。

9)Destrpy过期自动清理阶段:当Bean不在需要时,会经过清理阶段,如果Bean实现了DisposableBean这个接口,会调用其实现的destory()方法

10)destroy-method自配置清理:最后,如果这个Bean的Spring配置中配置了destory-method属性,会自动调用其配置的销毁方法。

*bean标签有两个重要的属性(init-methd和destroy-method)。用它们你可以自己定制初始化和注销方法。它们也有相应的注解(@PostConstruct和@PreDestroy)

*Aware接口下的子接口一般都只有一个方法,这个接口一般作用是让bean和容器可以交互,也就是可以通过bean获取到数据,比如Beanname,BeanFactory、ApplicationContext

Spring依赖注入的四种方式

1)构造器注入

2)setter方法注入:必须在类中声明setter方面

3)静态工厂注入:必须存在一个工厂类,调用工厂类的静态方法获得实例

4)实例工厂注入:实例工厂注入,不能通过工厂类的静态方法获得,所以必须先创建工厂类的实例,在调用工厂类的成员方法。

五种自动装配的不同方式

Spring装配包括手动装配和自动装配,手动装配是基于xml装配、构造方法、setter方法等手动装配。有五种自动装配方式,可以用来指导Spring容器用自动装配方式来进行依赖注入。

  1. no:默认的方式是不进行自动装配,通过显式设置ref属性来进行装配
  2. byName:通过参数名,自动装配,Spring容器在配置文件中发现bean的autowire属性被设置成byName,之后容器试图匹配、装配和该bean的属性具有相同名字的bean
  3. byType:通过类型自动装配
  4. constructor:通过构造器装配
  5. default:使用Beans标签中指定的方式自动装配

介绍一下IOC

IOC(inversion of control)控制反转,不是某种技术,而是一种思想,一种实现对象解耦的思想

说到解耦就得先说以下耦合,所谓耦合就是两个或者两个以上的对象互相关联,其中一个对象发生了改变,其他的对象也会受到影响。解耦就是,解除这种情况,让一个对象的改变不会对其他对象产生改变。

比如,在一个对象A中用new实例化另一个对象B。当B类的构造器参数发生改变,A类中的代码也要修改,这就叫耦合。解耦就是,用传入对象代替在A中实例化B对象。这样无论B对象怎么改,A中的代码也不需要修改。

Spring中实现IOC的方法就是,将实例的管理权交给IOC容器,由IOC容器使用DI实现依赖注入。

介绍一下DI

DI(Dependence injection)依赖注入,DI和IOC不同,DI是一种实际的技术,而不是思想。DI就是实现动态的将某个依赖对象注入到另一个对象中的技术

SpringIOC是什么,优点是什么

IOC即,Inversion of control,即控制反转,IOC实际上是一种思想,而不是一种实际上的技术,所谓IOC思想就是一种解耦的思想。说解耦之前,得先说一下耦合,所谓耦合就是两个或者多个对象之间会相互影响,修改一个对象是,另一个对象也需要修改,而解耦就是,让一个对象被修改时,另一个对象不会受到影响。

IOC控制反转,反转的是对象创建管理的权限,将本来对象创建的权力从对象转到IOC容器中。举个例子就是,如果A类中new一个B类对象,如果B类对象的结构发生改变,A类代码也就需要重构了。如果把B类对象创建好了赋值给B类,这样B类代码无论怎么变,A类代码都不需要重构

优点

  • 资源集中管理,实现资源的可配置和易管理
  • 降低了使用资源双方的依赖程度,也就是我们说的耦合度

SpringAOP

概念:

横切的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用的模块,并将其命名未Aspect,即切面,简单来说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性

使用切面技术,AOP把软件系统分为两个部分,核心关注点和横切关注点。业务处理的主要流程市核心关注点,与之关系不大的市横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,和各处基本相似,比如权限认证,日志、事务。AOP的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。

AOP核心概念

  1. 切面(aspect):类是对物体特征的抽象,切面就是对横切关注点的抽象
  2. 横切关注点:对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点。
  3. 连接点(joinpoint):被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器。
  4. 切入点(pointcut):对连接点进行拦截的定义
  5. 通知/增强(advice):所谓通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕五类
  6. 目标对象:代理的目标对象
  7. 织入(weave):将切面应用到目标对象并导致代理对象创建的过程
  8. 引入(introduction):在不修改代码的前提下,引入可以在运行期间为类动态的添加一些方法或字段。

介绍一下AOP

AOP,面向切面编程,可以理解成一种OOP的延续,OOP也就是面向对象编程,OOP解决了这么一种场景,三个类的方法相同,重复定义方法,我们可以使用OOP中继承的思想,让他们都继承一个父类,这样就可以代码的复写。但是如果是一个类中的多个方法有很多代码重复呢。这就是AOP需要解决的问题了。这中代码一般被称为横切代码逻辑,例如像,事务管理,权限校验,日志等。AOP做的就是把横切代码和业务代码分离,我们只需要写业务代码,横切代码通过代理的方式实现。

AOP的两种代理方式

Spring提供了两种方式来生成代理对象:JDKProxy和Cglib,具体使用哪种方法生成由AopProxyFactory根据AdvisedSupport对象的配置来决定。默认策略是如果目标类是接口,则使用JDK动态代理技术,否则使用Cglib来生成代理

JDK动态接口代理

JDK动态代理主要涉及到java.lang.reflect包中的两个类:Proxy和InvocationHandler。

InvocationHandler是一个接口,通过实现该接口定义横切逻辑,并通过反射机制调用目标类的代码,动态将横切逻辑和业务逻辑编织在一起。Proxy利用InvocationHandler动态创建一个符合某一接口的实例,生成目标类的代理对象。

CGLib动态代理

CGLib全称Code Generation Library,是一个强大的高性能,高质量的代码生成类库,可以在运行期扩展Java类于实现Java接口,CGLib封装了asm,可以在运行期间动态生成新的class。和JDK动态代理相比较,JDK代理有一个限制,就是JDK创建代理有一个限制,就只能为接口创建代理实例,而对于没用通过接口定义业务方法的类,则可以通过CGLib创建动态代理。

静态代理和动态代理的区别

静态代理,在编译的时候就已经实现了,编译完成后代理类是一个实际的Class文件。

动态代理,在运行时动态创建,即编译完成后没有实际的class文件。而是在运行时动态创建。

两种动态代理的实现

JDKProxy

JDKProxy,是利用Proxy类的方法创建的,这种代理方法有一个约束,就是,代理的类必须是某一个接口的实现类,Proxy.newProxyInstance() 有三个参数,类加载器,类接口和 InvocationHandler,类加载器加载代理类,InvocationHandler实现具体的代理功能,其底层还是使用了被代理类的方法,返回值是接口的实现类。参数中有一个类接口,这也就是为什么JDKProxy要依赖于接口才能实现。

CGLib

使用CGLib,需要实现MethodInterceptor接口,这种方式是JDKProxy的优化,可以不受接口的约束,针对类对象实现动态代理。重写接口的intercept方法实现具体的代理功能,其底层和JDKProxy一样依然还是使用了被代理对象的功能。其底层实际上是生成了一个被代理类的子类,在子类中拓展功能。所以无法拓展被final修饰的被代理类的方法

SpringAOP的实现原理和使用场景

场景

  • 事务管理
  • 权限校验
  • 安全检查
  • 数据校验
  • 缓存
  • 对象池管理

实现技术

AOP的主要实现方式有SpringAOP和Aspectj。

1)AspectJ,AspectJ的底层技术是静态代理,即用一种Aspectj支持的特定语言编写切面,通过一个命令来编译,生成一个新的代理类,该代理类增强了业务类,这是在编译时增强,相对于下面说的运行时增强,编译时增强的性能更好。

2)Spring AOP,SpringAOP使用的时动态代理,JDKProxy和CGLib 

SpringMVC原理

Spring的模型-视图-控制器(MVC)框架是围绕一个DispatcherServlet来设计的,这个Servlet会把请求分发给各个处理器,并支持可配置的处理器映射、视图渲染、本地化、失去与主题渲染等。

MVC流程

  • 客户端发起请求到dispatcherServlet。
  • DispatcherServlet接收请求,查询HandlerMapping
  • HandlerMapping返回处理器链(拦截器和具体处理的Controller)
  • 调用处理器链的适配器HandlerAdapter来处理请求
  • 执行handler的pre拦截器
  • 执行具体的业务方法
  • 执行handler的post拦截器
  • 返回结果的视图解析器(ModelAndView)
  • 最后进行视图解析和渲染返回结果给用户

什么是Spring?

Spring是一个轻量级Java开发框架,目的是为了解决企业级应用开发的业务逻辑层和其他层的耦合问题,它是一个分层的轻量级开源框架,为开发Java应用程序提供全面的基础架构支持。Spring负责基础架构,因此Java开发者可以专注于应用程序的开发。Spring最根本的使命是解决企业级应用开发的复杂性,即简化开发

Spring可以做很多事情,它为企业级开发提供了丰富的功能,但是这些功能的底层都依赖于他的两个核心特性IOC,和AOP

Spring框架的设计目标,设计理念,和核心是什么

spring设计目标:Spring为开发者提供一个一站式轻量级应用开发平台

Spring设计理念:在JavaEE开发中,支持POJO和JavaBean开发方式,Ⅹ应用面向接口开发,充分支持OOP设计方法;Spring通过IOC容器实现对象耦合关系的管理,并实现依赖反转,将对象之间的依赖关系交给IOC容器实现解耦

Spring框架的核心:IOC容器和AOP模块。通过IOC容器管理POJO对象以及他们之间的耦合关系;通过AOP以动态非侵入的方式增强服务。IOC让相互协作的组件保持松散的耦合,而AOP编程允许你把遍布于应用各层的功能分离出来形成可重用的功能组件

Spring的优缺点是什么

优点:

  • 方便解耦,简化开发
  • 支持面向切面编程
  • 声明式事务的支持,只需要通过配置就可以完成对事务的管理,而无需手动编程
  • 方便程序的测试,Spring对Junit4支持,可以通过注解方便的测试Spring的程序
  • 方便集成各种优秀框架,Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架的直接支持
  • 降低JavaEE API使用难度,Spring对JavaEE开发中非常难用的一些API,都提供了封装,Ⅹ用这些API难度大大降低

缺点:

  • Spring依赖反射,反射影响性能
  • 使用门槛升高,入门Spring需要较长时间

Spring有哪些应用场景

应用场景:JavaEE企业级应用开发,包括SSH、SSM等

Spring价值:

  • Spring是一个非侵入式的框架,目标是使应用程序代码对框架的依赖最小化
  • Spring提供一个一致性的编程模型,使应用直接使用POJO开发,与运行环境隔离开来;
  • Spring推动应用设计风格向面向对象和面向接口开发转变,提高了代码的可重用性,和可测试性

Spring由哪些模块组成

Spring总共大约有二十个模块,由1300多个不同的文件构成。而这些组件被分别整合在核心容器,AOP、设备支持、数据访问与集成、Web、消息、Test。等6个模块中。

  • IOC容器(Core Container)核心容器:Spring Core:提供了框架的基本组成部分,包括控制反转(IOC),依赖注入(DI)。Spring Beans :提供了BeanFactory,是工厂模式的一个经典实现,Spring将管理对象称之为Bean。Spring Context:构建于core封装包基础上的context封装包,提供了一种框架式的对象访问方法。
  • AOP 面向切面编程:Spring AOP:提供了面向切面的编程实现,让你可以自定义拦截器,切点等
  • Messageing 消息
  • Test 测试:Spring test :主要为测试提供支持的,支持使用JUnit或TestNG对Spring组件进行单元测试和集成测试。
  • Web:SpringWeb:提供了针对Web开发的集成特性,例如文件上传,利用Servlet listeners进行IOC容器初始化和针对Web的ApplicationContext
  • Data Access/Integration 数据访问与集成:Spring jdbc 提供了一个JDBC的抽象层,消除了烦琐的JDBC编码和数据库厂商特有的错误代码解析,用于简化JDBC

Spring框架中都用到了哪些设计模式

  1. 工厂模式:BeanFactory就是简单工厂模式的体现,用来创建对象的实例
  2. 单例模式:Bean默认为单例模式
  3. 代理模式:SpringAOP 使用动态代理实现
  4. 模板方法:大量抽象类使用了模板方法模式,Spring还提供了很多模板类对象
  5. 观察者模式:定义对象间一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知,被制动更新。如spring中的listener的实现

详细讲解一下核心容器(Core Container)模块

这是最基本的Spring模块,提供了Spring框架的基本功能,包含Spring core,Spring bean,Spring context,Spring Spel,Spring core提供了基本的IOC和DI的功能,Spring Bean模块提供了IOC容器也就是BeanFactory的基本功能,Spring context模块提供了ApplicationContext 也就是高级容器的基本功能。

Spring框架中有哪些不同类型的事件

Spring提供了以下五种标准的事件:

  1. 上下文更新事件(ContextRefreshedEvent):在调用ConfigurableApplicationContext接口中的refresh()方法时被触发
  2. 上下文开始事件(ContextStartedEvent):当容器调用ConfigurableApplicationContext的start方法时开始/重新开始容器时触发该事件
  3. 上下文停止事件(ContextStoppedEvent):当容器调用ConfigurableApplicationContext的stop方法停止容器时触发该事件。
  4. 上下文关闭事件(ContextClosedEvent):当ApplicationContext被关闭时触发该事件,其管理的所有单例Bean都被销毁
  5. 请求处理事件(RequestHandledEvent):在Web应用中,当一个http请求(request)结束触发该事件。如果一个bean实现了ApplicationListener接口,当一个ApplicationEvent被发布以后,Bean会自动被通知。

Spring应用程序有哪些不同的组件?

Spring应用一般有以下组件:

  • 接口:定义功能
  • Bean:包含属性,setter和getter方法,函数等
  • BeanDefinition:Bean描述信息,包含Bean的基本信息
  • AOP:面向切面编程
  • 用户程序,他会使用接口

使用Spring有哪些方式

  • 做为一个成熟的Spring Web应用程序
  • 作为第三方Web框架,使用Spring Frameworks中间层
  • 作为企业级JavaBean,它可以包装现有的POJO
  • 用于远程使用

什么是Spring IOC容器

Spring IOC容器时Spring中对IOC思想的一种实现。所谓IOC即inversion of control 控制反转。控制反转是一种思想,而不是一种技术,IOC思想是一种用来解耦的思想。解耦也就是解除耦合。耦合是两个对象之间会相互影响,即一个对象改变,会影响另一个对象,而解耦就是让两个对象之间不会影响。实现IOC的方法是DI,即依赖注入,把new对象的权力从对象手中转移到Spring容器中,也就是SpringIOC容器。从代码方面来说,Spring framework中有两种容器的实现,一种是简单IOC容器,BeanFactory,这种容器只提供操作Bean的基本功能,不关心Bean是如何创建的。高级容器ApplicationContext,提供了更丰富的功能。

控制反转有什么用

控制反转即IOC,Inversion of control ,控制反转是一种思想,而不是一种技术,控制反转核心是为了解决一个耦合问题。其有以下几种作用

  • 管理对象的创建和依赖关系的维护
  • 解耦,由容器去维护具体的对象
  • 托管了类的生成过程,比如我们需要在类的产生过程中做一些处理,最直接的例子就是代理,如果有容器程序可以把这部分处理交给容器,应用程序不用去关心类是如何完成代理的。

IOC的优点是什么

  • IOC或依赖注入把应用的代码量降到最低
  • 它使应用容易测试,单元测试不在需要单例和JNDI查找机制
  • 最小的代价和最小的侵入性使松散耦合得以实现
  • IOC容器支持加载服务时的饿汉式初始化和懒加载

Spring IOC的实现机制

Spring中IOC的实现就是工厂模式反射机制

SpringIOC支持哪些功能

Spring 的IOC设计支持以下功能:

  • 依赖注入
  • 依赖检查
  • 自动装配
  • 支持集合
  • 指定初始化方法和销毁方法
  • 支持某些回调方法(但是要实现Spring接口,略有侵入性)

BeanFactory 和 ApplicationContext的区别

BeanFactory和ApplicationContext是Spring的两大核心接口,都可以当作Spring的容器,其中ApplicationContext是BeanFactory的子接口

依赖关系

BeanFactory:是SpringBeans 模块中的接口,这个接口提供IOC容器的基本功能,包括根据名字查找bean实例,根据类型查找bean,查找bean是singleton还是prototype等。这个接口只关心容器的基本实现,不关心Bean是如何产生的。

ApplicaitonContext:是SpringContext 模块中的接口,这个接口基础了BeanFactory接口,在BeanFactory容器的基础上,添加了更完整的框架功能。简单来说就是,BeanFactory是给Spring开发者使用的,ApplicationContext是使用Spring的程序员使用的。

加载方式:

BeanFactory采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean的时候,才对该Bean进行加载实例化。这样,我们就不能发现一些存在Spring的配置问题,如Bean的某一个属性没有注入,BeanFactory加载后,直到第一次使用调用getBean方法才会抛出异常。

ApplicationContext,是在容器启动时,一次性创建了所有的Bean。这样在容器启动时,我们就可以发现Spring中存在的配置问题,这样有利于检查所依赖属性是否注入。ApplicationContext启动后预载入所有的单例Bean,通过预载入单例Bean,确保你需要的时候,你就不需要等待了

创建方式:

BeanFactory通常以编程的方式被创建,ApplicationContext还能以声明的方式创建,如使用ContextLoader

注册方式:

BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,但两者之间的区别是,BeanFactory需要手动注册,而ApplicationContext是自动注册。

Spring是如何设计容器的,BeanFactory和ApplicationContext的关系详解

Spring作者Rod Johnson设计了两个接口用以表示容器

  • BeanFactory
  • ApplicationContext

BeanFactory是Spring提供的简单容器,可以理解为就是一个HashMap,key是BeanName,Value是Bean实例。通常只提供注册(put),获取(get)这两个功能。我们称之为低级容器

ApplicationContext 可以称之为高级容器,因为他比BeanFactory多了更多功能,他继承了多个接口。因此具备了更多的功能。例如资源的获取,支持多种消息,对BeanFactory多了工具级别的支持等。该接口定义了一个refresh方法,此方法用于重新加载/刷新所有的bean

Bean实例的创建方法,

  1. 加载配置文件,解析成BeanDefinition放在Map里。
  2. 调用getBean的时候,从BeanDefinition所属的Map里拿出Class对象进行实例化,同时如果有依赖关系,将递归调用getBean方法,一一完成依赖注入

ApplicationContext在BeanFactory容器的基础上拓展了很多功能

  • 读取多个配置文件
  • BeanFactory工具类
  • 支持层级容器
  • 支持访问文件资源
  • 支持事件发布通知
  • 支持接口回调

ApplicationContext通常的实现是什么

FileSystemXmlApplicationContext:此容器从一个XML文件加载beans的定义,XMLBean配置文件的全路径名必须提供给他的构造函数。

ClassPathXmlApplicationContext:此容器也从一个XML文件中加载beans的定义,这里,你需要正确的设置classpath因为这个容器将在classpath里找到bean配置

WebXmlApplicationContext:此容器加载一个XML文件,此文件定义了一个WEB应用的所有Bean

什么是Spring的依赖注入

控制反转是一个很大的概念,可以哟个不同的方式来实现。其主要实现方式有两种:依赖注入和依赖检查

依赖注入:相对于IOC而言,依赖注入更加准确的描述了IOC的设计理念。所谓依赖注入,即组件之间的依赖关系由容器在应用系统运行期间来决定,也就是由容器动态的将某种依赖关系的目标对象实例注入到应用系统中的各个关联的组件之中。组件不做定位查询,只提供普通的java方法让容器去决定依赖关系。

依赖注入的基本原则

 依赖注入的基本原则是:应用组件不应该负责查找资源或者其他依赖的协作对象。配置对象的工作应该交给IOC容器负责,查找资源的逻辑应该从应用组件的代码中抽取出来,交给IOC容器负责。容器全权负责组件的装配,它会把符合依赖关系的对象通过熟悉(JavaBean中的setter)或者是构造器传递给需要的对象。

依赖注入有什么优势

依赖注入之所以更流行是因为它是一种更可取的方式:让容器全权负责依赖查询,受管理组件只需要暴露JavaBean的setter方法或者带参数的构造器或者接口,使容器可以在初始化时组装对象的依赖关系。其与依赖查找方式相比,主要优势为

  • 查找定位操作与应用代码完全无关
  • 不依赖于容器的API,可以很容器地在任何容器以外使用应用对象
  • 不需要特殊的接口,绝大多数对象可以做到完全不必依赖容器

有哪些不同类型的依赖注入实现方式

依赖注入是时下最流行的IOC实现方式,依赖注入分为接口注入Setter方法注入和构造器注入三种方法。

接口注入由于在灵活性和易用性比较差,在Spring4.0中已经废弃。

构造器依赖注入:构造器依赖注入通过容器触发一个类的构造器来实现,该类有一系列参数,每个参数代表一个其他类的依赖。

Setter方法注入:Setter方法注入是容器通过调用无参构造器或者static工厂方法实例化bean之后调用该bean的setter方法,

构造器依赖注入和Setter方法注入的区别

构造函数注入setter注入
没有部分注入有部分注入
不会覆盖setter属性会覆盖setter属性
任意修改都会创建一个新实例任意修改不会创建新实例
适用于很多属性适用于少量属性

两种依赖方式都可以使用,构造器注入和Setter方法注入。最好的解决方法是用构造器注入实现强制依赖,Setter方法实现可选依赖

什么是SpringBeans

Spring Beans 指那些形成Spring应用主干的Java对象。本质上就是Java的实例对象,只不过实例创建,配置,管理的权限交给IOC容器了。这些Bean通过容器中配置的元数据创建。比如以XML文件中的形式定义。在Spring容器中Bean可以是Singleton的或者prototype等

一个BeanDefinition包含什么

BeanDefintion之于Bean就像Class之于实例对象。

一个BeanDefintion从字面意思上来看就是Bean的定义信息。而Bean就是通过BeanDefintion实例化来的。

BeanDefintion中有的信息

  • 是单例Bean还是多例Bean
  • 是Spring内部Bean还是外部Bean
  • 当前Bean的父类BeanName
  • 当前Bean的BeanName
  • 当前Bean的作用域
  • 当前Bean的依赖对象
  • 定义该Bean对象的工厂类(如果有的话)
  • 创建该Bean的工厂方法
  • 当前Bean的构造函数参数值
  • 当前Bean的class文件

Spring配置文件包含哪些信息

Spring的配置文件是一个XML文件,该文件包含了Bean信息,描述了如何配置他们,以及如何相互调用

Spring基于XML注入Bean的几种方式

  1. Set方法注入
  2. 构造器注入:1)通过index设置参数的位置;2)通过type设置参数类型
  3. 静态工厂注入
  4. 实例工厂注入

你怎样定义Bean的作用域

Bean的scope有

  • Singleton
  • Prototype
  • Session
  • Request
  • GlobalSession:在一个全局的Http Session中,一个Bean定义对应一个实例。该作用域仅在基于Web 的Spring ApplicationContext情形下有效

选择Bean的作用域一般根据具体的业务环境决定。一般是使用单例Bean即可,但是也有场景需要使用其他的作用域

Spring框架中的单例Bean是线程安全的吗

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

Spring中的Bean默认是Singleton,Spring框架并没有对单例Bean进行多线程的封装处理。

实际上大部分时候Spring Bean是无状态的,所以某种程度来说bean也是线程安全的,但是如果bean有状态的话,就要开发者自己去保证线程安全了,最简单就是改变Bean的作用域。

把Singleton变更为Prototype,这样请求bean相当于new Bean了,就保证了线程安全。

Spring单例,为什么Controller,Service,Dao层可以实现线程安全

实际上大部分时间,SpringBean是无状态的,所以某种程度上来说,Bean是线程安全的。但是如果Bean有状态的话,就需要我们自己实现线程安全的操作了。

为什么无状态是线程安全的。无状态即每一次使用Spring bean的使用,使用的数据不会保留下来,即前一次使用bean对第二次使用bean没有影响。如果一个bean中只有查询的操作,那么这个bean就是无状态的。

Spring如何处理线程并发问题

在一般情况下,只有无状态的bean才可以在多线程环境下共享,在Spring中,绝大部分Bean都可以声明为singleton作用域,因为Spring对一些Bean中非线程安全状态采用ThreadLocal进行处理。解决线程安全问题

ThreadLocal线程同步机制都是为了解决多线程中相同变量访问冲突问题。同步机制采用了“时间换空间”的方式,仅提供一份变量,不同的线程在访问前需要获取锁,没有锁的线程则需要排队。而ThreadLocal使用了一种空间换时间的方式。ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离多个线程对数据的访问冲突。因为每一个线程都有自己的变量副本,自然也就不需要对改变量进行线程同步了。

哪些是重要的Bean生命周期方法?你能重载他们吗?

有两个重要的Bean生命周期方法,一个是setup,一个是在容器加载Bean的时候被调用。第二个方法是teardown,它是在容器卸载bean的时候被调用

bean标签页有两个重要的属性init-method和destory-method。用它们你可以自己定制初始化方法和销毁方法。

什么是Spring的内部bean?什么是Spring inner bean?

在Spring框架中,当一个bean仅被用作另一个bean的属性时,它能被声明为一个内部的bean。内部bean可以用setter或者构造器的方式来实现注入。内部bean通常时匿名的。它们的scope一般时prototype。

在Spring中注入一个Java集合

Spring提供以下几种集合的配置元素:

List类型用于注入一列值,允许有相同的值。

Set类型用于注入一组值,不允许有相同的值。

Map类型用于注入一组键值对,键和值都只能时String类型

什么是Bean装配

装配,或bean装配是指在Spring容器中把Bean组装到一起,前提是容器需要知道bean的依赖关系,如何通过依赖注入来把它们装配到一起。

我们知道实际上有两种依赖注入的方法,构造器注入和setter方法注入。创建应用对象之间协作关系的行为称为装配,实际上装配就是依赖注入的具体行为,这就是依赖注入和装配的关系

什么是Bean的自动装配

在Spring框架中,在配置文件中设定bean的依赖关系是一个很好的机制,Spring容器能够自动装配相互合作的Bean,这意味着容器不需要配置,能通过Bean容器自动处理bean之间的协作。这意味着Spring可以通过IOC容器中注入的方式自动搞定Bean之间的依赖关系。自动装配可以设置在每个bean上,也可以设定在特定的bean上。

自动装配就是 不需要在xml文件中显示的为一个Bean声明依赖关系,即这个Bean对象有什么成员对象。通过byName、byType、constructor、autodetect等方式让ApplicationContext自动实现装配。取代显示的声明

Spring自动装配有哪些方式

在Spring中,对象无需自己查找或者创建于其关联的其他对象,由容器负责把需要相互协作的对象引用赋予各个对象,使用autowire来配置自动装配模式。

在Spring框架xml配置中共有5种自动装配

  • no:默认的方式,不适用自动装配,通过手工显式装配bean
  • byName:通过Bean的名称进行自动装配,如果一个bean的property与另一个bean的name相同,就进行自动装配
  • byType:通过Bean的类型进行自动装配。
  • constructor:利用构造函数进行装配,并且构造函数的参数通过byType进行装配
  • autodetect:自动探测,如果有构造方法,通过construct的方式进行自动装配,否则使用byType的方式自动装配

使用@Autowired注解自动装配的过程是怎样的

使用@Autowired注解来自动装配指定的bean。在使用@Autowired注解之前需要在Spring配置文件进行配置<context:component-scan base-package="com"/>

在启动Spring IOC容器时,容器自动装载了一个AutowiredAnnotationBeanPostProcessor后置处理器,当容器扫描到@Autowired、@Resource、@Inject时,就会在Ioc容器中自动查询对应类型的Bean,并装配给该对象的属性,在使用@Autowired时,首先在容器中查询对应类型的bean

  • 如果查询结果刚好为一个,就将该bean装配给@Autowired指定的数据;
  • 如果查询的结果不止一个,那么@Autowired会根据名称来查找
  • 如果上述查找的结果为空,那么会抛出异常。解决方法时,使用required=false

自动装配有哪些局限性

  1. 存在覆盖的可能性,使用<constructor-arg> 和 <property> 显式的装配会覆盖自动装配
  2. 基本元数据类型无法自动装配:比如基本数据类型、String字符串、和类
  3. 模糊特性,自动装配的精确性没有显式的手动装配精确性高。

你可以在Spring中注入一个null和一个空字符串吗

指定为null

<property name="name"><null/></property>

指定为空字符串

<property name="name" value=""></property>

Spring注解

什么是基于Java的Spring注解配置

基于Java的配置,允许你在少量的java注解的帮助下,进行你的大部分Spring配置而非通过XML文件。以@Configuration注解为例,它用来标记类可以当做一个bean的定义,被SpringIOC容器使用。

另一个例子是@Bean注解,它表示此方法将要返回一个对象,作为一个bean注册进Spring应用上下文。

怎样开启注解装配

注解装配默认不会打开,在xml配置文件里使用

<context:component-scan base-package="com"/>

进行配置,打开配注解的自动扫描

@Component,@Controller,@Repository,@Service有何区别

@Component:这将Java类标记为Bean,它是任何Spring管理组件的通用构造型。spring的组件扫描机制现在可以将其拾取并将其拉入应用程序环境中

@Controller:这将一个类标记为Spring Web MVC 控制器。标有它的bean会自动导入到IOC容器中

@Service:此主键是组件注解的特化。它不会对@Component注解提供任何其他的行为,在业务代码处使用@Service起到一个标识作用

@Repository:这个注解的用途和功能和@Component类似,他是@Component注解的特化。他为dao层提供了额外的好处,它将Dao导入IOC容器,并使用未经检查的异常有资格转换为SpringDataAccessException。

@Required注解有什么作用

这个注解表明bean的属性必须在配置的时候设置,通过一个bean定义的显式的属性值或通过自动装配,若@Required注解的bean属性未被设置,容器将抛出BeanInintialzationException

@Autowired注解有什么作用

@Autowired默认是按照类型装配注入的,默认情况下它要求依赖对象必须存在。@AutoWired注解提供了更细粒度的控制,包括在何处以及如何完成自动装配。它的用法和@Required一样,修饰setter方法、构造器、属性等。

@Autowired和@Resource之间的区别

@Autowired可用于:构造函数:成员变量、setter方法

@Autowired和@Resource的区别

@Resource并非Spring提供的注解,而是JavaEE提供的注解,而@Autowired是Spring提供的

@Autowired默认是按照类型装配注入的,默认情况下它要求依赖对象必须存在(可以设置它required属性为false),当同一个类型存在多个对象时,可以使用@Qualifier注解指定

@Resource默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入。

@Qualifier注解有什么用

我们知道@Autowired注解用来装配注入一个bean到另一个bean中。这个@Autowired注解默认使用的方式是根据类型注入。所以当一个类型存在多个对象时,就会出现异常。此时就可以通过@Qualifier注解来指定应该装配哪个确切的bean来消除冲突。

@RequestMapping注解有什么用

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

  • 类级别:映射请求的URL
  • 方法级别:映射URL以及HTTP请求方法

Spring数据访问

解释对象/关系映射集成模块

Spring 通过提供ORM模块,支持我们在直接JDBC之上使用一个对象/关系映射(ORM)工具,Spring支持集成主流的ORM框架,Hiberate,JDO和Ibatis,JPA,TopLink,JDP,OJB。Spring的事务管理同样支持以上所有ORM框架以及JDBC

在Spring框架中如何更有效的使用JDBC

使用Spring JDBC框架,资源管理和错误处理的代价都会被减轻。所以开发者只需写statements和queries从数据存取数据,JDBC也可以在Spring框架提供的模板类的帮助下更有效地被使用,这个模板加jdbcTemplate

解释JDBC抽象和DAO模块

通过使用JDBC抽象和DAO模块,保证数据库代码的简洁,并能避免数据库资源错误关闭导致的问题,它在各种不同的数据库的错误信息之上,提供了一个统一的异常访问层,它还利用Spring的AOP模块给Spring应用中的对象提供事务管理服务。

Spring DAO有什么用

Spring DAO 使得JDBC,Hibernate或JDO这样的数据访问技术更容易以一种统一的方式工作,这使得用户容易在持久性技术之间切换。它还允许在编写代码时,无需考虑捕获每种技术不同的异常。

Spring JDBC API中存在哪些类

  • JdbcTemplate
  • SimpleJdbcTimplate
  • NamedParameterJdbcTemplate
  • SimpleJdbcInsert
  • SimpleJdbcCall

JdbcTemplate是什么

JdbcTemplate类提供了很多便利的方法解决诸如把数据库数据转变为基本数据类型或对象,执行写好的或可调用的数据库操作语句,提供自定义的数据错误处理。

Spring支持的事务管理类型,Spring事务实现方式有哪些

Spring支持两种类型的事务管理:

  • 编程式事务管理:这意味你通过编程的方式管理事务,给你带来极大的灵活性,但是难维护。
  • 声明式事务管理:这意味着你可以将业务代码和事务管理分离,你只需用注解或XML配置来管理事务。

Spring的事务传播行为

spring事务的传播行为说的是,当多个事务同时存在的时候,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的事务隔离级别

Spring有五大隔离级别,默认值为ISOLATION_DEFAULT(使用数据库的设置),其他四个隔离级别和数据库的隔离级别一致

  • 使用底层数据库设置的隔离级别,数据库设置的是什么我就用什么
  • 读未提交,最低隔离级别、事务未提交之前,就可以被其他事务读取(可能出现脏读、幻读、不可重复读);
  • 读已提交,一个事务只有被提交后才能被其他事务读取到(可能造成幻读、不可重复读)
  • 可重复读,保证多次读取同一个数据时,其值都和事务开始时候一致,精致读取到别的事务未提交的数据(会造成幻读),MySQL默认级别;
  • 串行化,代价最高的隔离级别,该隔离级别能防止脏读、不可重复读、幻读。

Spring框架的事务管理有哪些优点

  • 为不同的事务API如JTA、JDBC、Hibernate、JPA和JDO,提供了一个不变的编程模式
  • 为编程式事务管理提供了一套简单的API而不是一些复杂事务API
  • 支持声明式事务管理
  • 和Spring各种数据访问抽象层很好集成

解释一下Spring AOP里面的几个名词

  • 连接点(JoinPoint):目标对象中所有可以被增强的方法被叫做连接点
  • 切入点(PointCut):目标对象中所有被增强的方法,切入点是连接点的子集
  • 通知/增强(Advice):增强的方法。
  • 目标对象(Target):被代理的对象
  • 织入(weaving):增强被应用到连接点的过程
  • 代理(Proxy):由目标对象生成代理对象
  • 切面(Aspect):切入点和增强的组合

Spring AOP和AspectJ AOP有什么区别 ,AOP 有哪些实现方式

AOP的实现本质是代理,AOP出现时OOP的延伸,用来解决一个内内部方法的代码复用问题。

AOP实现的关键在于代理模式,AOP代理主要分为静态代理和动态代理。静态代理的代表为AspectJ;动态代理则以Spring AOP为代表

AspectJ实现AOP的方式是静态代理。我们知道静态代理是一种增加代码的方式,在编译时实现代理,这种方式的缺点是需要编写大量代码,很麻烦,但是Aspectj实现类自动生成代码实现编译时代理。

SpringAOP使用的是动态代理,所谓的动态代理就是说AOP不需要去修改字节码,使用运行时代理。这种方式有两种实现,JDKProxy和CGLibProxy两种代理。

Spring在运行时通知对象

通过在代理类中包裹切面,Spring在运行期间把切面织入到Spring管理的bean中。代理封装了目标类,并拦截被通知方法的调用,再把调用转发给真正的目标bean。当代理拦截到方法调用时,在调用目标bean方法之前,会执行切面逻辑。直到应用需要被代理bean时,Spring才会创建代理对象。

如果使用的是ApplicationContext的话,在ApplicationContext从BeanFactory中加载所有bean的时候,Spring才会创建被代理的对象。因为Spring运行时才创建代理对象,所以我们不需要特殊的编译器来织入切面。

Spring通知有哪些类型

在AOP术语中,切面的工作被称为通知,实际上是程序执行时要通过SpringAOP框架触发的代码段。

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

  1. 前置通知(Before):在目标方法被调用之前通知功能;
  2. 后置通知(After):在目标方法完成之后调用通知,此时不会关心方法输出的是什么
  3. 返回通知(After-returning):在目标方法成功执行之后调用通知;
  4. 异常通知(After-throwing):在目标方法抛出异常后调用通知
  5. 环绕通知(Around):通知包裹了被通知的方法,在被通知方法调用之前和调用之后执行自定义的行为。

同一个aspect,不同advice执行顺序

没有异常的情况下 Around Before target Around After After-Returning

有异常的情况下:Around Before target Around After After-Throwing

什么是切面Aspect

切面是由切入点和增强的组合,它既包含了横切逻辑的定义,也包括了连接点的定义,SpringAOP就是负责实施切面所定义的横切逻辑编制到切面所指定的连接点中

AOP的工作重心在于如何将增强编织到目标对象的连接点上,这里包含两个工作:

  • 如何通过pointcut和advice定位到特定的joinpoint上
  • 如何在advice中编写切面代码

可以简单的认为,使用@Aspect注解的类就是切面

SpringMVC

什么是SpringMVC

SpringMVC是Spring提供的对于MVC框架的实现,MVC框架是一种软件的设计模式,分成三个层次,Model(模型层),View(表现层),Controller(控制层)。分层降低对象之间的耦合性,便于代码的维护。

其中模型层,即Model,是实际上进行数据处理的地方,一个模型可以为多个视图提供数据。在SpringMVC中model层就是Dao和Service。

视图层,即View,使用来展示数据给用户看的地方。即我们的用户界面

控制层,即Controller层,控制层负责视图层和模型层的交互,这一层主要负责两件工作,将视图层的请求发往模型层进行数据处理。将模型层返回的数据交付给视图层进行展示。

在SpringMVC出现之前,经典的MVC框架是,JSP、Servlet和JavaBean,JavaBean作为模型层,JSP作为视图层、Servlet作为控制层,但是这种模式有很大的缺陷,耦合性太强了,这才出现了SpringMVC,SpringMVC的改进是将模型层分为DAO和Service,将Controller层分为前端控制器DispatcherServlet和后端控制器Controller层来。在视图层也支持使用不同的视图类型

SpringMVC的优点

  1. 它是基于组件技术的,全部的应用对象,无论控制器和视图,还是业务对象之类的都是java组件,并且和Spring提供的其他基础组件紧密集成。
  2. 不依赖于ServletAPI(目标虽是如此,但是在实现的时候确实是依赖于Servlet的)
  3. 可以任意使用各种视图技术,不仅仅局限于JSP
  4. 支持各种请求资源的映射策略,不仅仅是Controller
  5. 它是易于扩展的
  6. 清晰的角色划分,各个职责分模块处理,降低了耦合性
  7. 可以很好的集成,使我们只需要关注与spring的集成。

SpringMVC的工作原理

  1. 客户端发起请求
  2. 服务器端DispatcherServlet接收请求
  3. DispatcherServlet查询HandlerMapping生成处理器链(包括拦截器和Controller)
  4. 调用处理器链的适配器HandlerAdepter 来处理请求
  5. 执行Handler的pre拦截器
  6. 执行具体的业务方法
  7. 执行Handler的post拦截器
  8. HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet
  9. DispatcherServlet将ModelAndView传给ViewReslover视图解析器
  10. ViewReslover解析后返回具体的View
  11. DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中国)
  12. DispatcherServlet将响应发给客户端

SpringMVC的控制器是不是单例,如果是,有什么问题,怎么解决

SpringMVC的控制器是单例模式,所以在多线程访问的时候有线程安全问题,不要使用同步,解决方案是在控制器里面不能写字段。

SpringMVC中的控制器的注解一般用哪个,有没有别的注解可以代替

一般用@Controller注解,表示是表现层,不能用别的注解代替。

@RequestMapping注解用在类上有什么作用

是一个用来处理请求地址映射的注解,可以用于类或者方法上。用于类上,表示类中的所有响应请求的方法都已该地址作为父路径。用于方法上,表示用这个路径来请求这个方法。

怎么把某个请求映射到特定的方法上面

直接在方法上面加@RequestMapping注解,在这个注解中声明访问的路径

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

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

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

直接在方法的形参中声明Request参数或者Session参数,SpringMVC框架会自动把request对象和session对象传入

怎么在拦截的方法里得到从前台传入的参数

直接在方法形参中声明这个参数,但是必须名字和传过来的参数一样

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

直接在方法中声明这个对象,SpringMVC就会自动把属性赋值到这个对象里面。

SpringMVC中函数的返回值是什么

返回值可以有很多类型,有void,String、ModelAndView。

ModelAndView一般是在前后端没有分离的项目中使用,指定数据到哪个视图

void的使用场景一般是,真的没有返回值、重定向、服务端跳转、使用response返回数据,这种方式要加上@ResponseBody注解

String的使用场景:重定向,转发,字符串,JSON,逻辑视图名

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

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

怎样把ModelMap里面的数据放入session里面

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

KYLO_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值