Spring 面试集
基于Spring Framework 4.x 总结的常见面试题,零碎学习倡议还是官网文档走起:https://spring.io/projects/spring-framework#learn
一、个别问题
开发中次要应用 Spring 的什么技术 ?
- IOC 容器治理各层的组件
- 应用 AOP 配置申明式事务
- 整合其余框架
Spring有哪些长处?
- 轻量级:Spring在大小和透明性方面相对属于轻量级的,根底版本的Spring框架大概只有2MB。
- 管制反转(IOC):Spring应用管制反转技术实现了松耦合。依赖被注入到对象,而不是创立或寻找依赖对象。
- 面向切面编程(AOP):Spring反对面向切面编程,同时把利用的业务逻辑与零碎的服务拆散开来。
- 容器:Spring蕴含并管理应用程序对象的配置及生命周期。
- MVC框架:Spring的web框架是一个设计低劣的web MVC框架,很好的取代了一些web框架。
- 事务管理:Spring对下至本地业务上至全局业务(JAT)提供了对立的事务管理接口。
- 异样解决:Spring提供一个不便的API将特定技术的异样(由JDBC, Hibernate, 或JDO抛出)转化为统一的、Unchecked异样。
Spring模块
简述 AOP 和 IOC 概念
AOP:Aspect Oriented Program, 面向(方面)切面的编程;Filter(过滤器)也是一种 AOP. AOP 是一种新的 方法论, 是对传统 OOP(Object-OrientedProgramming, 面向对象编程) 的补充. AOP 的次要编程对象是切面(aspect),而切面模块化横切关注点.能够举例通过事务阐明.
IOC:Invert Of Control, 管制反转. 也称为 DI(依赖注入)其思维是反转资源获取的方向. 传统的资源查找形式要求组件向容器发动申请查找资源.作为回应, 容器适时的返回资源. 而利用了 IOC 之后, 则是容器被动地将资源推送给它所治理的组件,组件所要做的仅是抉择一种适合的形式来承受资源. 这种行为也被称为查找的被动模式
二、依赖注入
IoC(Inverse of Control:管制反转)是一种设计思维,就是 将本来在程序中手动创建对象的控制权,交由Spring框架来治理。 IoC 在其余语言中也有利用,并非 Spring 特有。 IoC 容器是 Spring 用来实现 IoC 的载体, IoC 容器实际上就是个Map(key,value),Map 中寄存的是各种对象。
将对象之间的相互依赖关系交给 IoC 容器来治理,并由 IoC 容器实现对象的注入。这样能够很大水平上简化利用的开发,把利用从简单的依赖关系中解放出来。 IoC 容器就像是一个工厂一样,当咱们须要创立一个对象的时候,只须要配置好配置文件/注解即可,齐全不必思考对象是如何被创立进去的。 在理论我的项目中一个 Service 类可能有几百甚至上千个类作为它的底层,如果咱们须要实例化这个 Service,你可能要每次都要搞清这个 Service 所有底层类的构造函数,这可能会把人逼疯。如果利用 IoC 的话,你只须要配置好,而后在须要的中央援用就行了,这大大增加了我的项目的可维护性且升高了开发难度。
什么是 Spring IOC 容器?
Spring 框架的外围是 Spring 容器。容器创建对象,将它们拆卸在一起,配置它们并治理它们的残缺生命周期。Spring 容器应用依赖注入来治理组成应用程序的组件。容器通过读取提供的配置元数据来接管对象进行实例化,配置和组装的指令。该元数据能够通过 XML,Java 注解或 Java 代码提供。
什么是依赖注入?
依赖注入(DI,Dependency Injection)是在编译阶段尚未知所需的性能是来自哪个的类的状况下,将其余对象所依赖的性能对象实例化的模式。这就须要一种机制用来激活相应的组件以提供特定的性能,所以依赖注入是管制反转的根底。否则如果在组件不受框架管制的状况下,框架又怎么晓得要创立哪个组件?
依赖注入有以下三种实现形式:
- 结构器注入
- Setter办法注入(属性注入)
- 接口注入
Spring 中有多少种 IOC 容器?
在 Spring IOC 容器读取 Bean 配置创立 Bean 实例之前,必须对它进行实例化。只有在容器实例化后, 才能够从 IOC 容器里获取 Bean 实例并应用
Spring 提供了两种类型的 IOC 容器实现
- BeanFactory:IOC 容器的根本实现
- ApplicationContext:提供了更多的高级个性,是 BeanFactory 的子接口
BeanFactory 是 Spring 框架的基础设施,面向 Spring 自身;ApplicationContext 面向应用 Spring 框架的开发者,简直所有的利用场合都间接应用 ApplicationContext 而非底层的 BeanFactory;
无论应用何种形式, 配置文件是雷同的。
BeanFactory 和 ApplicationContext 区别
BeanFactory | ApplicationContext |
---|---|
懒加载 | 即时加载 |
它应用语法显式提供资源对象 | 它本人创立和治理资源对象 |
不反对国际化 | 反对国际化 |
不反对基于依赖的注解 | 反对基于依赖的注解 |
ApplicationContext
ApplicationContext 的次要实现类:
- ClassPathXmlApplicationContext:从类门路下加载配置文件
- FileSystemXmlApplicationContext: 从文件系统中加载配置文件
- ConfigurableApplicationContext 扩大于 ApplicationContext,新减少两个次要办法:refresh() 和 close(), 让 ApplicationContext具备启动、刷新和敞开上下文的能力
- WebApplicationContext 是专门为 WEB 利用而筹备的,它容许从绝对于 WEB 根目录的门路中实现初始化工作
- ApplicationContext 在初始化上下文时就实例化所有单例的 Bean
从 IOC 容器中获取 Bean
- 调用 ApplicationContext 的 getBean() 办法
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");HelloWorld helloWorld = (HelloWorld) ctx.getBean("helloWorld");helloWorld.hello();
列举 IoC 的一些益处
- 它将最小化应用程序中的代码量;
- 它将使您的应用程序易于测试,因为它不须要单元测试用例中的任何单例或 JNDI 查找机制;
- 它以最小的影响和起码的侵入机制促成松耦合;
- 它反对即时的实例化和提早加载服务
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("priv.starfish.spring.Apple"); if(f!=null){ f.eat(); } }}
三、Beans
什么是 Spring Beans?
- 它们是形成用户应用程序骨干的对象
- Bean 由 Spring IoC 容器治理
- 它们由 Spring IoC 容器实例化,配置,拆卸和治理
- Bean 是基于用户提供给容器的配置元数据创立
Spring 提供了哪些配置形式?
基于 xml 配置
bean 所需的依赖项和服务在 XML 格局的配置文件中指定。这些配置文件通常蕴含许多 bean 定义和特定于应用程序的配置选项。它们通常以 bean 标签结尾。例如:
<bean id="studentbean" class="org.edureka.firstSpring.StudentBean"> <property name="name" value="Edureka"></property></bean>
基于注解配置
您能够通过在相干的类,办法或字段申明上应用注解,将 bean 配置为组件类自身,而不是应用 XML 来形容 bean 拆卸。默认状况下,Spring 容器中未关上注解拆卸。因而,您须要在应用它之前在 Spring 配置文件中启用它。例如:
<beans><context:annotation-config/><!-- bean definitions go here --></beans>
基于 Java API 配置
Spring 的 Java 配置是通过应用 @Bean 和 @Configuration 来实现。
@Bean 注解表演与
<bean/>
元素雷同的角色。- @Configuration 类容许通过简略地调用同一个类中的其余 @Bean 办法来定义 bean 间依赖关系。
例如:
@Configurationpublic class StudentConfig { @Bean public StudentBean myStudent() { return new StudentBean(); }}
Spring Bean的作用域?
- 在 Spring 中, 能够在 \<bean> 元素的 scope 属性里设置 Bean 的作用域。
- 默认状况下,Spring 只为每个在 IOC 容器里申明的 Bean 创立惟一一个实例,整个 IOC 容器范畴内都能共享该实例:所有后续的
getBean()
调用和 Bean 援用都将返回这个惟一的 Bean 实例。该作用域被称为 singleton,它是所有 Bean 的默认作用域。
Spring 容器中的 bean 能够分为 5 个范畴。所有范畴的名称都是自阐明的,然而为了防止混同,还是让咱们来解释一下:
- singleton:这种bean范畴是默认的,这种范畴确保不论承受到多少个申请,每个容器中只有一个bean的实例,单例的模式由bean factory本身来保护。
- prototype:原型范畴与单例范畴相同,为每一个bean申请提供一个实例。
- request:每次HTTP申请都会创立一个新的bean,该作用于仅实用于WebApplicationContext环境,在申请实现当前,bean会生效并被垃圾回收器回收。
- Session:同一个HTTP Session 共享一个bean,不同的 HTTP Session应用不同的bean。该作用于仅实用于WebApplicationContext环境,在session过期后,bean会随之生效。
- global-session:全局session作用域,仅仅在基于portlet的web利用中才有意义,Spring5曾经没有了。Portlet是可能生成语义代码(例如:HTML)片段的小型Java Web插件。它们基于portlet容器,能够像servlet一样解决HTTP申请。然而,与 servlet 不同,每个 portlet 都有不同的会话
全局作用域与Servlet中的session作用域成果雷同。
Spring bean 容器的生命周期是什么样的?
Spring IOC 容器能够治理 Bean 的生命周期, Spring 容许在 Bean 生命周期的特定点执行定制的工作。
Spring bean 容器的生命周期流程如下:
- Spring 容器依据配置中的 bean 定义实例化 bean;
- Spring 应用依赖注入填充所有属性,如 bean 中所定义的配置;
- 如果 bean 实现 BeanNameAware 接口,则工厂通过传递 bean 的 ID 来调用 setBeanName();
- 如果 bean 实现 BeanFactoryAware 接口,工厂通过传递本身的实例来调用 setBeanFactory();
- 与下面的相似,如果实现了其余
*.Aware
接口,就调用相应的办法; - 如果存在与 bean 关联的任何 BeanPostProcessors,则调用 preProcessBeforeInitialization() 办法;
- 如果为 bean 指定了 init 办法(
<bean>
的 init-method 属性),那么将调用它; - 最初,如果存在与 bean 关联的任何 BeanPostProcessors,则将调用 postProcessAfterInitialization() 办法;
- 如果 bean 实现 DisposableBean 接口,当 spring 容器敞开时,会调用 destory();
- 如果为 bean 指定了 destroy 办法(
<bean>
的 destroy-method 属性),那么将调用它
在 bean 初始化时会经验几个阶段,要与容器对 bean 生命周期的治理交互,能够实现 InitializingBean
和 DisposableBean
接口。容器对前者调用 afterPropertiesSet()
,对后者调用 destroy()
,以容许 bean 在初始化和销毁 bean 时执行某些操作。
官网不倡议应用这两个接口,而是倡议应用 @PostConstruct
和 @PreDestroy
,或者 XML 配置中应用 init-method
和destroy-method
属性
<bean id="exampleInitBean" class="examples.ExampleBean" init-method="init"/>
public class ExampleBean { public void init() { // do some initialization work }}
等价于
public class AnotherExampleBean implements InitializingBean { public void afterPropertiesSet() { // do some initialization work }}
Spring Bean生命周期回调——初始化回调和销毁回调办法
实现 Bean 初始化回调和销毁回调各有三种办法,一是实现接口办法,二是在XML配置,三是应用注解
- 应用注解
@PostConstruct
和@PreDestroy
- 实现
InitializingBean
和DisposableBean
接口 - XML 中配置
init-method
和destroy-method
在一个 bean 中,如果配置了多种生命周期回调机制,会依照上边从上到下的秩序调用
在 Spring 中如何配置 Bean?
Bean 的配置形式: 通过全类名 (反射)、 通过工厂办法 (动态工厂办法 & 实例工厂办法)、FactoryBean
什么是 Spring 拆卸
当 bean 在 Spring 容器中组合在一起时,它被称为拆卸或 bean 拆卸,拆卸是创立利用对象之间协作关系的行为。 Spring 容器须要晓得须要什么 bean 以及容器应该如何应用依赖注入来将 bean 绑定在一起,同时拆卸 bean。
依赖注入的实质就是拆卸,拆卸是依赖注入的具体行为。
注入是实例化的过程,将创立的bean放在Spring容器中,分为属性注入(setter形式)、结构器注入
什么是bean主动拆卸?
Spring 容器能够主动配置相互协作 beans 之间的关联关系。这意味着 Spring 能够主动配置一个 bean 和其余合作bean 之间的关系,通过查看 BeanFactory 的内容里有没有应用< property>元素。
在Spring框架中共有5种主动拆卸,让咱们逐个剖析
- no:这是Spring框架的默认设置,在该设置下主动拆卸是敞开的,开发者须要自行在beanautowire属性里指定主动拆卸的模式
- byName:该选项能够依据bean名称设置依赖关系。当向一个bean中主动拆卸一个属性时,容器将依据bean的名称主动在在配置文件中查问一个匹配的bean。如果找到的话,就拆卸这个属性,如果没找到的话就报错。
- byType:该选项能够依据bean类型设置依赖关系。当向一个bean中主动拆卸一个属性时,容器将依据bean的类型主动在在配置文件中查问一个匹配的bean。如果找到的话,就拆卸这个属性,如果没找到的话就报错。
- constructor:结构器的主动拆卸和byType模式相似,然而仅仅实用于与有结构器雷同参数的bean,如果在容器中没有找到与结构器参数类型统一的bean,那么将会抛出异样。
- autodetect:Spring首先尝试通过 constructor 应用主动拆卸来连贯,如果它不执行,Spring 尝试通过 byType 来主动拆卸
主动拆卸有什么局限?
- 根本数据类型的值、字符串字面量、类字面量无奈应用主动拆卸来注入。
- 拆卸依赖中若是呈现匹配到多个bean(呈现歧义性),拆卸将会失败
通过注解的形式配置bean | 什么是基于注解的容器配置
组件扫描(component scanning): Spring 可能从 classpath下主动扫描, 侦测和实例化具备特定注解的组件。
特定组件包含:
- @Component:根本注解, 标识了一个受 Spring 治理的组件
- @Respository:标识长久层组件
- @Service:标识服务层(业务层)组件
- @Controller: 标识体现层组件
对于扫描到的组件,,Spring 有默认的命名策略:应用非限定类名,,第一个字母小写。也能够在注解中通过 value 属性值标识组件的名称。
当在组件类上应用了特定的注解之后,,还须要在 Spring 的配置文件中申明 <context:component-scan>
:
base-package
属性指定一个须要扫描的基类包,Spring 容器将会扫描这个基类包里及其子包中的所有类- 当须要扫描多个包时, 能够应用逗号分隔
如果仅心愿扫描特定的类而非基包下的所有类,可应用
resource-pattern
属性过滤特定的类,示例:<context:component-scan base-package="priv.starfish.front.web.controller" annotation-config="true" resource-pattern="autowire/*.class"/>
如何在 spring 中启动注解拆卸?
默认状况下,Spring 容器中未关上注解拆卸。因而,要应用基于注解拆卸,咱们必须通过配置<context:annotation-config />
元素在 Spring 配置文件中启用它。
四、AOP
:形容一下Spring AOP 呗?
你有没有⽤过Spring的AOP? 是⽤来⼲嘛的? ⼤概会怎么使⽤?
什么是 AOP?
AOP(Aspect-Oriented Programming,面向切面编程):是一种新的方法论,是对传统 OOP(Object-Oriented Programming,面向对象编程) 的补充。在 OOP 中, 咱们以类(class)作为咱们的根本单元,而 AOP 中的根本单元是 Aspect(切面)
AOP 的次要编程对象是切面(aspect)
在利用 AOP 编程时, 依然须要定义公共性能,但能够明确的定义这个性能在哪里,,以什么形式利用,,并且不用批改受影响的类。这样一来横切关注点就被模块化到非凡的对象(切面)里。
AOP 的益处:
- 每个事物逻辑位于一个地位,代码不扩散,便于保护和降级
- 业务模块更简洁, 只蕴含外围业务代码
AOP 术语
- 切面(Aspect):横切关注点(逾越应用程序多个模块的性能),被模块化的非凡对象
- 连接点(Joinpoint):程序执行的某个特定地位,如类某个办法调用前、调用后、办法抛出异样后等。在这个地位咱们能够插入一个 AOP 切面,它实际上是应用程序执行 Spring AOP 的地位
告诉(Advice): 告诉是个在办法执行前或执行后要做的动作,实际上是程序执行时要通过 SpringAOP 框架触发的代码段。Spring 切面能够利用五种类型的告诉:
- before: 前置告诉 , 在一个办法执行前被调用
- after:在办法执行之后调用的告诉,无论形式执行是否胜利
- after-returning:仅当办法胜利实现后执行的告诉
- after-throwing:在办法抛出异样退出时执行的告诉
- around:在办法执行之前和之后调用的告诉
- 指标(Target):被告诉的对象,通常是一个代理对象,也指被告诉(advice)对象
- 代理(Proxy):向指标对象利用告诉之后创立的对象
- 切点(pointcut):每个类都领有多个连接点,程序运行中的一些工夫点,例如一个办法的执行,或者是一个异样的解决。AOP 通过切点定位到特定的连接点。类比:连接点相当于数据库中的记录,切点相当于查问条件。切点和连接点不是一对一的关系,一个切点匹配多个连接点,切点通过
org.springframework.aop.Pointcut
接口进行形容,它应用类和办法作为连接点的查问条件 - 引入(Introduction):引入容许咱们向现有的类增加新办法或属性
- 织入(Weaving):织入是把切面利用到指标对象并创立新的代理对象的过程
Spring AOP
- AspectJ:Java 社区里最残缺最风行的 AOP 框架
- 在 Spring2.0 以上版本中, 能够应用基于 AspectJ 注解或基于 XML 配置的 AOP
在 Spring 中启用 AspectJ 注解反对
- 要在 Spring 利用中应用 AspectJ 注解, 必须在 classpath 下蕴含 AspectJ 类库:
aopalliance.jar
、aspectj.weaver.jar
和spring-aspects.jar
- 将 aop Schema 增加到
<beans>
根元素中. - 要在 Spring IOC 容器中启用 AspectJ 注解反对, 只有在 Bean 配置文件中定义一个空的 XML 元素
<aop:aspectj-autoproxy>
- 当 Spring IOC 容器侦测到 Bean 配置文件中的
<aop:aspectj-autoproxy>
元素时, 会主动为与 AspectJ切面匹配的 Bean 创立代理.
有哪写类型的告诉(Advice) | 用 AspectJ 注解申明切面
- 要在 Spring 中申明 AspectJ切面, 只须要在 IOC 容器中将切面申明为 Bean 实例. 当在 Spring IOC 容器中初始化 AspectJ切面之后, Spring IOC 容器就会为那些与 AspectJ切面相匹配的 Bean 创立代理.
- 在 AspectJ注解中, 切面只是一个带有 @Aspect 注解的 Java 类.
- 告诉是标注有某种注解的简略的 Java 办法.
AspectJ反对 5 种类型的告诉注解:
- @Before: 前置告诉, 在办法执行之前执行
- @After: 后置告诉, 在办法执行之后执行
- @AfterRunning: 返回告诉, 在办法返回后果之后执行
- @AfterThrowing: 异样告诉, 在办法抛出异样之后
- @Around: 盘绕告诉, 围绕着办法执行
AOP 有哪些实现形式?
实现 AOP 的技术,次要分为两大类:
动态代理 - 指应用 AOP 框架提供的命令进行编译,从而在编译阶段就可生成 AOP 代理类,因而也称为编译时加强;
- 编译时编织(非凡编译器实现)
- 类加载时编织(非凡的类加载器实现)。
动静代理 - 在运行时在内存中“长期”生成 AOP 动静代理类,因而也被称为运行时加强。
- JDK 动静代理
- CGLIB
有哪些不同的AOP实现
Spring AOP and AspectJ AOP 有什么区别?
- Spring AOP 基于动静代理形式实现,AspectJ 基于动态代理形式实现。
- Spring AOP 仅反对办法级别的 PointCut;提供了齐全的 AOP 反对,它还反对属性级别的 PointCut。
五、数据拜访
Spring对JDBC的反对
JdbcTemplate简介
- 为了使 JDBC 更加易于应用, Spring 在 JDBC API 上定义了一个形象层, 以此建设一个 JDBC 存取框架
- 作为 Spring JDBC 框架的外围, JDBCTemplate 的设计目标是为不同类型的 JDBC 操作提供模板办法。每个模板办法都能管制整个过程,并容许笼罩过程中的特定工作。通过这种形式,能够在尽可能保留灵活性的状况下,将数据库存取的工作量降到最低。
Spring 反对哪些 ORM 框架
Hibernate、iBatis、JPA、JDO、OJB
六、事务
Spring 中的事务管理
作为企业级应用程序框架,,Spring 在不同的事务管理 API 之上定义了一个形象层,而应用程序开发人员不用理解底层的事务管理 API,就能够应用 Spring 的事务管理机制
Spring 既反对编程式事务管理,也反对申明式的事务管理
- 编程式事务管理:将事务管理代码嵌入到业务办法中来管制事务的提交和回滚,在编程式治理事务时,必须在每个事务操作中蕴含额定的事务管理代码,属于硬编码
申明式事务管理:大多数状况下比编程式事务管理更好用。它将事务管理代码从业务办法中分离出来,以申明的形式来实现事务管理。事务管理作为一种横切关注点,能够通过 AOP 办法模块化。Spring 通过 Spring AOP 框架反对申明式事务管理,申明式事务又分为两种:
- 基于XML的申明式事务
- 基于注解的申明式事务
事务管理器
Spring 并不间接治理事务,而是提供了多种事务管理器,他们将事务管理的职责委托给 Hibernate 或者 JTA 等长久化机制所提供的相干平台框架的事务来实现。
Spring 事务管理器的接口是 org.springframework.transaction.PlatformTransactionManager
,通过这个接口,Spring为各个平台如 JDBC、Hibernate 等都提供了对应的事务管理器,然而具体的实现就是各个平台本人的事件了。
Spring 中的事务管理器的不同实现
事务管理器以一般的 Bean 模式申明在 Spring IOC 容器中
在应用程序中只须要解决一个数据源, 而且通过 JDBC 存取
org.springframework.jdbc.datasource.DataSourceTransactionManager
在 JavaEE 应用服务器上用 JTA(Java Transaction API) 进行事务管理
org.springframework.transaction.jta.JtaTransactionManager
用 Hibernate 框架存取数据库
org.springframework.orm.hibernate3.HibernateTransactionManager
事务管理器以一般的 Bean 模式申明在 Spring IOC 容器中
用事务告诉申明式地治理事务
- 事务管理是一种横切关注点
- 为了在 Spring 2.x 中启用申明式事务管理,能够通过 tx Schema 中定义的 \<tx:advice> 元素申明事务告诉,为此必须当时将这个 Schema 定义增加到 \<beans> 根元素中去
- 申明了事务告诉后,就须要将它与切入点关联起来。因为事务告诉是在 \<aop:config> 元素内部申明的, 所以它无奈间接与切入点产生关联,所以必须在 \<aop:config> 元素中申明一个增强器告诉与切入点关联起来.
- 因为 Spring AOP 是基于代理的办法,所以只能加强公共办法。因而, 只有私有办法能力通过 Spring AOP 进行事务管理。
用 @Transactional 注解申明式地治理事务
- 除了在带有切入点,告诉和增强器的 Bean 配置文件中申明事务外,Spring 还容许简略地用 @Transactional 注解来标注事务办法
- 为了将办法定义为反对事务处理的,能够为办法增加 @Transactional 注解,依据 Spring AOP 基于代理机制,只能标注私有办法.
- 能够在办法或者类级别上增加 @Transactional 注解。当把这个注解利用到类上时, 这个类中的所有公共办法都会被定义成反对事务处理的
- 在 Bean 配置文件中只须要启用
<tx:annotation-driven>
元素, 并为之指定事务管理器就能够了 - 如果事务处理器的名称是 transactionManager, 就能够在
<tx:annotation-driven>
元素中省略transaction-manager
属性,这个元素会自动检测该名称的事务处理器
事务流传属性
- 当事务办法被另一个事务办法调用时, 必须指定事务应该如何流传。例如:办法可能持续在现有事务中运行,也可能开启一个新事务,并在本人的事务中运行
- 事务的流传行为能够由流传属性指定,Spring 定义了 7 品种流传行为:
流传行为 | 意义 |
---|---|
PROPAGATION_MANDATORY | 示意该办法必须运行在一个事务中。如果以后没有事务正在产生,将抛出一个异样 |
PROPAGATION_NESTED | 示意如果以后正有一个事务在进行中,则该办法该当运行在一个嵌套式事务中。被嵌套的事务能够独立于封装事务进行提交或回滚。如果封装事务不存在,行为就像PROPAGATION_REQUIRES一样。 |
PROPAGATION_NEVER | 示意以后的办法不应该在一个事务中运行。如果一个事务正在进行,则会抛出一个异样。 |
PROPAGATION_NOT_SUPPORTED | 示意该办法不应该在一个事务中运行。如果一个现有事务正在进行中,它将在该办法的运行期间被挂起。 |
PROPAGATION_SUPPORTS | 示意以后办法不须要事务性上下文,然而如果有一个事务曾经在运行的话,它也能够在这个事务里运行。 |
PROPAGATION_REQUIRES_NEW | 示意以后办法必须在它本人的事务里运行。一个新的事务将被启动,而且如果有一个现有事务在运行的话,则将在这个办法运行期间被挂起。 |
PROPAGATION_REQUIRES | 示意以后办法必须在一个事务中运行。如果一个现有事务正在进行中,该办法将在那个事务中运行,否则就要开始一个新事务。 |
Spring 反对的事务隔离级别
隔离级别 | 含意 |
---|---|
ISOLATION_DEFAULT | 应用后端数据库默认的隔离级别。 |
ISOLATION_READ_UNCOMMITTED | 容许读取尚未提交的更改。可能导致脏读、幻影读或不可反复读。 |
ISOLATION_READ_COMMITTED | 容许从曾经提交的并发事务读取。可避免脏读,但幻影读和不可反复读仍可能会产生。 |
ISOLATION_REPEATABLE_READ | 对雷同字段的屡次读取的后果是统一的,除非数据被以后事务自身扭转。可避免脏读和不可反复读,但幻影读仍可能产生。 |
ISOLATION_SERIALIZABLE | 齐全遵从ACID的隔离级别,确保不产生脏读、不可反复读和幻影读。这在所有隔离级别中也是最慢的,因为它通常是通过齐全锁定以后事务所波及的数据表来实现的。 |
事务的隔离级别要失去底层数据库引擎的反对,而不是应用程序或者框架的反对;
Oracle 反对的 2 种事务隔离级别,Mysql反对 4 种事务隔离级别。
设置隔离事务属性
用 @Transactional 注解申明式地治理事务时能够在 @Transactional 的 isolation 属性中设置隔离级别
在 Spring 事务告诉中, 能够在 <tx:method>
元素中指定隔离级别
设置回滚事务属性
- 默认状况下只有未查看异样(RuntimeException和Error类型的异样)会导致事务回滚,而受查看异样不会。
事务的回滚规定能够通过 @Transactional 注解的 rollbackFor和 noRollbackFor属性来定义,这两个属性被申明为 Class[] 类型的,因而能够为这两个属性指定多个异样类。
- rollbackFor:遇到时必须进行回滚
- noRollbackFor: 一组异样类,遇到时必须不回滚
超时和只读属性
- 因为事务能够在行和表上取得锁, 因而长事务会占用资源, 并对整体性能产生影响
- 如果一个事物只读取数据但不做批改,数据库引擎能够对这个事务进行优化
- 超时事务属性:事务在强制回滚之前能够放弃多久,这样能够避免长期运行的事务占用资源
- 只读事务属性:示意这个事务只读取数据但不更新数据,这样能够帮忙数据库引擎优化事务
设置超时和只读事务属性
- 超时和只读属性能够在 @Transactional 注解中定义,超时属性以秒为单位来计算
列出两种形式的示例:
@Transactional(propagation = Propagation.NESTED, timeout = 1000, isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
<tx:advice id="txAdvice" transaction-manager="txManager"> <!-- the transactional semantics... --> <tx:attributes> <!-- all methods starting with 'get' are read-only --> <tx:method name="get*" read-only="true" propagation="REQUIRES_NEW" isolation="READ_COMMITTED" timeout="30" no-rollback-for="java.lang.ArithmeticException"/> <!-- other methods use the default transaction settings (see below) --> <tx:method name="*"/> </tx:attributes> </tx:advice> <!-- ensure that the above transactional advice runs for any execution of an operation defined by the FooService interface --> <aop:config> <aop:pointcut id="fooServiceOperation" expression="execution(* x.y.service.FooService.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="fooServiceOperation"/> </aop:config>
七、MVC
Spring MVC 框架有什么用?
Spring Web MVC 框架提供 模型-视图-控制器 架构和随时可用的组件,用于开发灵便且涣散耦合的 Web 应用程序。 MVC 模式有助于拆散应用程序的不同方面,如输出逻辑,业务逻辑和 UI 逻辑,同时在所有这些元素之间提供涣散耦合。
Spring MVC的长处
- 能够反对各种视图技术,而不仅仅局限于JSP
- 与Spring框架集成(如IoC容器、AOP等)
- 清晰的角色调配:前端控制器(dispatcherServlet) ,申请到处理器映射(handlerMapping),处理器适配器(HandlerAdapter), 视图解析器(ViewResolver)
- 反对各种申请资源的映射策略
Spring MVC 的运行流程 | DispatcherServlet形容
在整个 Spring MVC 框架中, DispatcherServlet 处于外围地位,负责协调和组织不同组件以实现申请解决并返回响应的工作
SpringMVC 解决申请过程:
- 若一个申请匹配 DispatcherServlet 的申请映射门路(在 web.xml中指定),WEB 容器将该申请转交给 DispatcherServlet 解决
- DispatcherServlet 接管到申请后, 将依据申请信息(包含 URL、HTTP办法、申请头、申请参数、Cookie 等)及 HandlerMapping 的配置找到解决申请的处理器(Handler)。可将 HandlerMapping 看成路由控制器, 将 Handler 看成指标主机
- 当 DispatcherServlet 依据 HandlerMapping 失去对应以后申请的 Handler 后,通过 HandlerAdapter 对 Handler 进行封装,再以对立的适配器接口调用 Handler
- 处理器实现业务逻辑的解决后将返回一个 ModelAndView 给 DispatcherServlet,ModelAndView 蕴含了视图逻辑名和模型数据信息
- DispatcherServlet 借助 ViewResoler 实现逻辑视图名到实在视图对象的解析
- 失去实在视图对象 View 后, DispatcherServlet 应用这个 View 对ModelAndView 中的模型数据进行视图渲染
Spring的Controller是单例的吗?多线程状况下Controller是线程平安吗?
controller默认是单例的,不要应用非动态的成员变量,否则会产生数据逻辑凌乱。正因为单例所以不是线程平安的
@Controller//@Scope("prototype")public class ScopeTestController { private int num = 0; @RequestMapping("/testScope") public void testScope() { System.out.println(++num); } @RequestMapping("/testScope2") public void testScope2() { System.out.println(++num); }}
咱们首先拜访 http://localhost:8080/testScope
,失去的答案是1
;
而后咱们再拜访 http://localhost:8080/testScope2
,失去的答案是 2
。
接下来咱们再来给controller
减少作用多例 @Scope("prototype")
咱们仍旧首先拜访 http://localhost:8080/testScope
,失去的答案是1
;
而后咱们再拜访 http://localhost:8080/testScope2
,失去的答案还是 1
。
单例是不平安的,会导致属性重复使用。
解决方案
- 不要在controller中定义成员变量
- 万一必须要定义一个非动态成员变量时候,则通过注解@Scope(“prototype”),将其设置为多例模式。
- 在Controller中应用ThreadLocal变量
八、注解
什么是基于Java的Spring注解配置? 给一些注解的例子
基于Java的配置,容许你在大量的Java注解的帮忙下,进行你的大部分Spring配置而非通过XML文件。
以@Configuration 注解为例,它用来标记类能够当做一个bean的定义,被Spring IOC容器应用。
另一个例子是@Bean注解,它示意此办法将要返回一个对象,作为一个bean注册进Spring利用上下文。
@Configurationpublic class StudentConfig { @Bean public StudentBean myStudent() { return new StudentBean(); }}
怎么开启注解拆卸?
注解拆卸在默认状况下是不开启的,为了应用注解拆卸,咱们必须在Spring配置文件中配置 <context:annotation-config/>
元素。
Spring MVC 罕用注解:
@Controller
在SpringMVC 中,控制器Controller 负责解决由DispatcherServlet 散发的申请,它把用户申请的数据通过业务解决层解决之后封装成一个Model ,而后再把该Model 返回给对应的View 进行展现。在SpringMVC 中只需应用@Controller 标记一个类是Controller ,而后应用@RequestMapping 和@RequestParam 等一些注解用以定义URL 申请和Controller 办法之间的映射,这样的Controller 就能被外界拜访到。
@RequestMapping
RequestMapping是一个用来解决申请地址映射的注解,可用于类或办法上
@RequestMapping
Spring Framework 4.3 之后引入的基于HTTP办法的变体
@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping
@PathVariable
用于将申请URL中的模板变量映射到性能解决办法的参数上,即取出uri模板中的变量作为参数
@RequestParam
应用@RequestParam绑定申请参数值,在解决办法入参处应用@RequestParam能够把申请参数传递给申请办法
- value:参数名
- required:是否必须。默认为true, 示意申请参数中必须蕴含对应的参数,若不存在,将抛出异样
@RequestBody
@RequestBody 表明办法参数应该绑定到HTTP申请体的值
@ResponseBody
@Responsebody 示意该办法的返回后果间接写入HTTP response body中
个别在异步获取数据时应用,在应用@RequestMapping后,返回值通常解析为跳转门路,加上@Responsebody后返回后果不会被解析为跳转门路,而是间接写入HTTP response body中。比方异步获取 json 数据,加上@Responsebody后,会间接返回 json 数据。
@Resource和@Autowired
@Resource和@Autowired都是做bean的注入时应用,其实@Resource并不是Spring的注解,它的包是javax.annotation.Resource,须要导入,然而Spring反对该注解的注入。
- 共同点:两者都能够写在字段和 setter 办法上。两者如果都写在字段上,那么就不须要再写 setter 办法。
不同点
- @Autowired 为 Spring 提供的注解,@Autowired 注解是依照类型(byType)拆卸依赖对象,默认状况下它要求依赖对象必须存在,如果容许 null 值,能够设置它的 required 属性为 false。如果咱们想应用依照名称(byName)来拆卸,能够联合 @Qualifier 注解一起应用
- @Resource 默认依照 ByName 主动注入,由 J2EE 提供,须要导入包
javax.annotation.Resource
。@Resource 有两个重要的属性:name 和 type,而 Spring 将@ Resource 注解的 name 属性解析为bean 的名字,而 type 属性则解析为 bean 的类型。所以,如果应用 name 属性,则应用 byName 的主动注入策略,而应用 type 属性时则应用 byType 主动注入策略。如果既不制订 name 也不制订 type 属性,这时将通过反射机制应用 byName 主动注入策略。
@ModelAttribute
办法入参标注该注解后, 入参的对象就会放到数据模型中
@SessionAttribute
将模型中的某个属性暂存到HttpSession中,以便多个申请之间能够共享这个属性
@CookieValue
@CookieValue可让解决办法入参绑定某个Cookie 值
@RequestHeader
申请头蕴含了若干个属性,服务器可据此获知客户端的信息,通过@RequestHeader即可将申请头中的属性值绑定到解决办法的入参中
@Component, @Controller, @Repository, @Service 有何区别?
- @Component:将 java 类标记为 bean。它是任何 Spring 治理组件的通用构造型。Spring 的组件扫描机制能够将其拾取并将其拉入应用程序环境中
- @Controller:将一个类标记为 Spring Web MVC 控制器。标有它的 Bean 会主动导入到 IoC 容器中
- @Service:此注解是组件注解的特化。它不会对 @Component 注解提供任何其余行为。你能够在服务层类中应用 @Service 而不是 @Component,因为它以更好的形式指定了用意
- @Repository:这个注解是具备相似用处和性能的 @Component 注解的特化。它为 DAO 提供了额定的益处。它将 DAO 导入 IoC 容器,并使未经查看的异样有资格转换为 Spring DataAccessException。
@Required 注解有什么作用
这个注解表明bean的属性必须在配置的时候设置,通过一个bean定义的显式的属性值或通过主动拆卸,若@Required注解的bean属性未被设置,容器将抛出 BeanInitializationException。示例:
public class Employee { private String name; @Required public void setName(String name){ this.name=name; } public string getName(){ return name; }}
@Autowired 注解有什么作用
@Autowired默认是依照类型拆卸注入的,默认状况下它要求依赖对象必须存在(能够设置它required属性为false)。@Autowired 注解提供了更细粒度的管制,包含在何处以及如何实现主动拆卸。它的用法和@Required一样,润饰setter办法、结构器、属性或者具备任意名称和/或多个参数的PN办法。
public class Employee { private String name; @Autowired public void setName(String name) { this.name=name; } public string getName(){ return name; }}
@Autowired和@Resource之间的区别
用处:做bean的注入时应用
- @Autowired,属于Spring的注解,
org.springframework.beans.factory.annotation.Autowired
- @Resource,不属于Spring的注解,JDK1.6反对的注解,
javax.annotation.Resource
共同点:都用来拆卸bean。写在字段上,或写在setter办法
不同点:@Autowired 默认按类型拆卸。依赖对象必须存在,如果要容许null值,能够设置它的required属性为false @Autowired(required=false),也能够应用名称拆卸,配合@Qualifier注解
@Resource默认是依照名称来拆卸注入的,只有当找不到与名称匹配的bean才会依照类型来拆卸注入
@Qualifier 注解有什么作用
当创立多个雷同类型的 bean 并心愿仅应用属性拆卸其中一个 bean 时,能够应用 @Qualifier 注解和 @Autowired 通过指定应该拆卸哪个确切的 bean 来打消歧义。
@RequestMapping 注解有什么用?
@RequestMapping 注解用于将特定 HTTP 申请办法映射到将解决相应申请的控制器中的特定类/办法。此正文可利用于两个级别:
- 类级别:映射申请的 URL
- 办法级别:映射 URL 以及 HTTP 申请办法
九、其余问题
Spring 框架中用到了哪些设计模式?
- 工厂设计模式 : Spring应用工厂模式通过
BeanFactory
、ApplicationContext
创立 bean 对象。 - 代理设计模式 : Spring AOP 性能的实现。
- 单例设计模式 : Spring 中的 Bean 默认都是单例的。
- 模板办法模式 : Spring 中
jdbcTemplate
、hibernateTemplate
等以 Template 结尾的对数据库操作的类,它们就应用到了模板模式。 - 包装器设计模式 : 咱们的我的项目须要连贯多个数据库,而且不同的客户在每次拜访中依据须要会去拜访不同的数据库。这种模式让咱们能够依据客户的需要可能动静切换不同的数据源。
- 观察者模式: Spring 事件驱动模型就是观察者模式很经典的一个利用。
- 适配器模式 :Spring AOP 的加强或告诉(Advice)应用到了适配器模式、spring MVC 中也是用到了适配器模式适配
Controller
。
参考与起源
https://www.edureka.co/blog/interview-questions/spring-interv...
https://crossoverjie.top/2018/07/29/java-senior/ThreadPool/
本文由mdnice多平台公布