Spring框架技术

什么是spring?

spring是一个简化java企业级开发的一个框架,内部包含了很多技术,比如:控制反转&依赖注入、面向切面编程、spring事务管理、通过spring集成其他框架、springmvc、springboot、springcloud等等,这些都是围绕简化开发展开的技术。
以前需要为移动端提供api接口,接口数据以json格式输出,使用java技术,实现过程大家应该比较熟悉,如下:

  1. 使用idea创建一个web项目;
  2. 创建servlet,servlet中写业务代码,组装需要数据,将数据以json格式输出;
  3. 在web.xml中配置servlet信息;
  4. 将项目部署到tomcat中。

原生的web项目开发过程都是上面这样,和业务相关的其实只有第2步,而其他几个步骤是每个web项目都需要的,像比较大的项目,会有很多web模块,每个模块都需要重复这些1/3/4操作步骤,还是相当繁琐的,也会耗费大量时间。
使用了sprintboot之后,只有Controller是需要我们写的,而我们没有去创建servlet、将返回的结果以json格式输出、配置web.xml,没有将项目发布到tomcat,没有去启动tomcat,而只启动了一个main方法,是不是非常神奇。创建servlet、通过response将数据以json格式输出、配置web.xml、发布项目到tomcat、启动tomcat等这些操作并不是说不需要,而是springboot内部已经帮我们实现了,对于开发者来说这些都被隐藏了,springboot让我们更关注业务代码的实现,从而最大限度的帮我们提升开发效率,简化项目的开发过程。

总结:
定义:

Spring是一个轻量级的IoC(控制反转)和AOP容器框架。

目的:

用于简化企业应用程序的开发,使得开发者只需要关心业务需求。

常见的配置方式:
  • 基于XML的配置
  • 基于注解的配置
  • 基于Java的配置
组成:

Spring Core :核心类库,提供IOC服务
Spring Context :提供框架式的Bean访问方式,以及企业级功能(JNDI、定时任务等)
Spring AOP :AOP服务
Spring DAO :对JDBC的抽象,简化了数据访问异常的处理 Spring ORM :对现有的ORM框架的支持
Spring Web :提供了基本的面向Web的综合特性,例如多方文件上传
Spring MVC :提供面向Web应用的Model-View-Controller实现
Spring Test:提供了对JUnit和TestNG测试的支持。

使用Spring框架的好处:

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

Spring配置文件及工厂:

Spring配置文件是什么?

Spring配置文件是个XML 文件,一般命名为applicationContext.xml,这个文件包含了类信息,描述了如何配置它们,以及如何相互调用。

ApplicationContext通常的实现是什么?

FileSystemXmlApplicationContext :此容器从一个XML文件中加载beans的定义,XML Bean 配置文件的全路径名必须提供给它的构造函数。
ClassPathXmlApplicationContext:此容器也从一个XML文件中加载beans的定义,这里,你需要正确设置classpath因为这个容器将在classpath里找bean配置。
WebXmlApplicationContext:此容器加载一个XML文件,此文件定义了一个WEB应用的所有bean。

BeanFactory和ApplicationContext有什么区别?

概述:都可以当做Spring的容器。其中ApplicationContext是BeanFactory的子接口。
区别:

BeanFactory: 是Spring里面最底层的接口。 以延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化。 如果Bean的某一个属性没有注入,BeanFacotry加载后,直至第一次使用调用getBean方法才会抛出异常。(运行时异常)
ApplicationContext: 是BeanFactory的子接口。 在容器启动时,一次性创建了所有的Bean。在容器启动时,一次性创建了所有的Bean,我们就可以发现Spring中存在的配置错误。(启动时异常)

Spring 框架中用到的设计模式

工厂模式:BeanFactory就是简单工厂模式的体现,用来创建对象的实例
单例模式:Bean默认为单例模式
代理模式:Spring的AOP功能用到了JDK的动态代理和CGLIB字节码生成技术
模板方法:用来解决代码重复的问题。比如.RestTemplate, JmsTemplate, JpaTemplate
观察者模式:定义对象键一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知被制动更新,如Spring中listener的实现:ApplicationListener
适配器模式:Spring AOP的增强或通知(Advice)使用到了适配器模式、SpringMVC中也是用到了适配器模式适配Controller。
包装器设计模式:我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库。这种模式让我们可以根据客户的需求能够动态切换不同的数据源。

控制反转IOC和依赖注入DI

什么是Spring IOC 容器?

Spring IOC 负责创建对象,管理对象,通过依赖注入(DI),装配对象,配置对象,并且管理这些对象的整个生命周期。

如何理解IOC和DI?

控制反转(Inversion of Control,缩写为IoC)
依赖注入(Dependency Injection,简称DI)
两个名词是以不同角度来描述Spring的工作,控制反转指的是把创建对象的控制权交由Spring进行处理,从“主动”变成“被动”;依赖注入指的是把配置在Spring容器中,由Spring组装好的对象引入到你自己的对象之中去。

IOC的优点是什么?

IOC 或 DI把应用的代码量降到最低。最小的代价和最小的侵入性实现松耦合。
小结

IOC控制反转,是一种设计理念,将对象创建和组装的主动控制权利交给了spring容器去做,控制的动作被反转了,降低了系统的耦合度,利于系统维护和扩展,主要就是指需要使用的对象的组装控制权被反转了,之前是自己要做的,现在交给spring容器做了。
DI依赖注入,表示spring容器中创建对象时给其设置依赖对象的方式,通过某些注入方式可以让系统更灵活,比如自动注入等可以让系统变的很灵活。
spring容器:主要负责容器中对象的创建、组装、对象查找、对象生命周期的管理等等操作。

Spring容器使用步骤:

引入spring相关的maven配置 创建bean配置文件,比如bean xml配置文件 在bean
xml文件中定义好需要spring容器管理的bean对象
创建spring容器,并给容器指定需要装载的bean配置文件,当spring容器启动之后,会加载这些配置文件,然后创建好配置文件中定义好的bean对象,将这些对象放在容器中以供使用
通过容器提供的方法获取容器中的对象,然后使用
示例

有哪些不同类型的IOC(依赖注入)方式?

构造器依赖注入:
构造器依赖注入通过容器触发一个类的构造器来实现的,该类有一系列参数,每个参数代表一个对其他类的依赖。
Setter方法注入:
Setter方法注入是容器通过调用无参构造器或无参static工厂方法实例化bean之后,调用该bean的setter方法,即实现了基于setter的依赖注入。
根据注解注入:
如用@Autowired、@Resource等注解来进行Bean的注入。

各种注入方式

自动注入

自动注入是采用约定大约配置的方式来实现的,程序和spring容器之间约定好,遵守某一种都认同的规则,来实现自动注入。
xml中可以在bean元素中通过autowire属性来设置自动注入的方式:

<bean id="" class="" autowire="byType|byName|constructor|default" />

byteName:按照名称进行注入
byType:按类型进行注入
constructor:按照构造方法进行注入
default:默认注入方式

Spring Beans

什么是Spring beans?

被Spring IOC容器初始化,装配,和管理的,形成Spring应用主干的java对象。(默认为单例 tag=“singleton”)

Spring容器中Bean的生命周期?
  • 实例化Bean并填充属性
  • 注入依赖关系
  • 初始化
  • bean交给应用开发人员处理(进行业务逻辑使用)
  • 销毁
创建Spring beans的方式?

构造函数:SpringContext利用无参的构造函数创建一个对象,然后利用setter方法赋值。也可以直接通过有参构造函数直接赋值。
静态方法创建对象:在类中定义一个返回值为需要获取的对象的构造方法,然后在xml中配置“factory-method”属性指向构造方法。
工厂方法创建对象:实例工程方法需要先创建工厂实例,然后在创建所需对象的时候,将其赋值为“factory-bean”
详解见Spring创建对象的三种方式

更具体划分如下:
Spring容器内部创建bean实例对象常见的4种方式:

  • 通过反射调用构造方法创建bean对象
  • 通过静态工厂方法创建bean对象
  • 通过实例工厂方法创建bean对象
  • 通过FactoryBean创建bean对象

实例

Spring Bean 定义 包含什么?

一个Spring Bean 的定义包含容器必知的所有配置元数据,包括如何创建一个bean,它的生命周期详情及它的依赖。
PS:元数据主要是描述数据属性(property)的信息,用来支持如指示存储位置、历史数据、资源查找、文件记录等。
xml中bean定义详解

如何给Spring 容器提供配置元数据?

XML配置文件。
基于注解的配置。
基于java的配置。(建立一个SpringConfig的java类用于配置,用@Configuration来注解该类)
PS:详解见Spring中基于java的配置

如何定义Bean的作用域?

可以通过bean 定义中的scope属性来定义。
Spring框架支持以下五种bean的作用域:

singleton : bean在每个Spring ioc 容器中只有一个实例。(非线程安全!!!)
prototype:一个bean的定义可以有多个实例。
request:每次http请求都会创建一个bean,该作用域仅在基于web的Spring ApplicationContext情形下有效。
session:在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。 global-session:在一个全局的HTTP
Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。

作用域小结

Spring容器自带的有2种作用域,分别是singleton和prototype;还有3种分别是spring
web容器环境中才支持的request、session、application
singleton是spring容器默认的作用域,一个spring容器中同名的bean实例只有一个,多次获取得到的是同一个bean;单例的bean需要考虑线程安全问题
prototype是多例的,每次从容器中获取同名的bean,都会重新创建一个;多例bean使用的时候需要考虑创建bean对性能的影响
一个应用中可以有多个spring容器,自定义scope 3个步骤,实现Scope接口,将实现类注册到spring容器,使用自定义的sope

什么是Spring的内部bean?

当一个bean仅被用作另一个bean的属性时,它能被声明为一个内部bean,为了定义inner bean,在Spring 的 基于XML的 配置元数据中,可以在 或 元素内使用 元素,内部bean通常是匿名的,它们的Scope一般是prototype。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="person2" class="com.itdjx.spring.dependency.injection.Person">
        <property name="name" value="ZH"/>
        <property name="age" value="25"/>
        <property name="sex" value="男"/>
        <property name="car" >
            <bean class="com.itdjx.spring.dependency.injection.Car">
                <constructor-arg value="Audi" index="0"/>
                <constructor-arg value="德国" index="1"/>
                <constructor-arg value="300000" type="double"/>
            </bean>
        </property>
    </bean>
</beans>
在 Spring中如何注入一个java集合?

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

<list>类型用于注入一列值,允许有相同的值。 
<set> 类型用于注入一组值,不允许有相同的值。 
<map> 类型用于注入一组键值对,键和值都可以为任意类型。 
<props>类型用于注入一组键值对,键和值都只能为String类型。
Bean的装配与自动装配?

装配:装配,或bean 装配是指在Spring 容器中把bean组装到一起,前提是容器需要知道bean的依赖关系,如何通过依赖注入来把它们装配到一起。
自动装配:Spring> 容器能够自动装配相互合作的bean,这意味着容器不需要和配置,能通过Bean工厂自动处理bean之间的协作。

解释不同方式的自动装配?
  1. 基于xml

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

  1. 基于注解

在使用@Autowired注解之前需要在Spring配置文件进行配置:<context:annotation-config />

  • @Autowired默认是按照类型装配注入的,默认情况下它要求依赖对象必须存在(可以设置它required属性为false)。
  • @Resource默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入。
自动装配的局限性

重写: 你仍需用 和 配置来定义依赖,意味着总要重写自动装配。
基本数据类型:你不能自动装配简单的属性,如基本数据类型,String字符串,和类。
模糊特性:自动装配不如显式装配精确,如果有可能,建议使用显式装配。

并发时对Bean的处理

无状态的Bean才可以在多线程环境下共享,在Spring中,绝大部分Bean都可以声明为singleton作用域,因为Spring对一些Bean中非线程安全状态采用ThreadLocal进行处理,解决线程安全问题。
ThreadLocal采用了“空间换时间”的方式,会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。
PS:ThreadLocal可用于变量操作相互不影响的情况,不能用于多线程并发时共享变量的场景。
ThreadLocal详解

depend-on的作用

如果xml中定义的bean特别多,而有些bean之间也没有强依赖关系,此时如果想去调整bean的创建和销毁的顺序,得去调整xml中bean的定义顺序,或者去加强依赖,这样是非常不好的,spring中可以通过depend-on来解决这些问题,在不调整bean的定义顺序和强加依赖的情况下,可以通过通过depend-on属性来设置当前bean的依赖于哪些bean,那么可以保证depend-on指定的bean在当前bean之前先创建好,销毁的时候在当前bean之后进行销毁。
depend-on使用方式:

<bean id="bean1" class="" depend-on="bean2,bean3; bean4" />

depend-on:设置当前bean依赖的bean名称,可以指定多个,多个之间可以用”,;空格“进行分割

primary的作用
当从容器中查找一个bean的时候,如果容器中出现多个Bean候选者时,可以通过primary="true"将当前bean置为首选者,那么查找的时候就会返回主要的候选者,否则将抛出异常。
spring配置文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
 
    <bean id="serviceA" class="com.javacode2018.lesson001.demo8.PrimaryBean$ServiceA" primary="true"/>
    <bean id="serviceB" class="com.javacode2018.lesson001.demo8.PrimaryBean$ServiceA"/>
 
    <bean id="setterBean" class="com.javacode2018.lesson001.demo8.PrimaryBean" autowire="byType" />
</beans>
autowire-candidate的作用

我们可以通过primary属性来指定一个主要的bean,当从容器中查找的时候,如果有多个候选的bean符合查找的类型,此时容器将返回primary="true"的bean对象。
spring还有一种方法也可以解决这个问题,可以设置某个bean是否在自动注入的时候是否为作为候选bean,通过bean元素的autowire-candidate属性类配置,如下:

<bean id="serviceA" class="com.javacode2018.lesson001.demo8.SetterBean$ServiceA" autowire-candidate="false"/>

autowire-candidate:设置当前bean在被其他对象作为自动注入对象的时候,是否作为候选bean,默认值是true。

lazy-init:bean延迟初始化

实时初始化的bean都会在容器启动过程中创建好,如果程序中定义的bean非常多,并且有些bean创建的过程中比较耗时的时候,会导致系统消耗的资源比较多,并且会让整个启动时间比较长,这个我估计大家都是有感受的,使用spring开发的系统比较大的时候,整个系统启动耗时是比较长的,基本上多数时间都是在创建和组装bean。
spring对这些问题也提供了解决方案:bean延迟初始化。
所谓延迟初始化,就是和实时初始化刚好相反,延迟初始化的bean在容器启动过程中不会创建,而是需要使用的时候才会去创建,先说一下bean什么时候会被使用:

被其他bean作为依赖进行注入的时候,比如通过property元素的ref属性进行引用,通过构造器注入、通过set注入、通过自动注入,这些都会导致被依赖bean的创建
开发者自己写代码向容器中查找bean的时候,如调用容器的getBean方法获取bean。

上面这2种情况会导致延迟初始化的bean被创建。
延迟bean的配置
在bean定义的时候通过lazy-init属性来配置bean是否是延迟加载,true:延迟初始化,false:实时初始化

<bean lazy-init="是否是延迟初始化" />
使用继承简化bean配置(abstract & parent)

bean元素的abstract属性为true的时候可以定义某个bean为一个抽象的bean,相当于定义了一个bean模板,spring容器并不会创建这个bean,从容器中查找abstract为true的bean的时候,会报错BeanIsAbstractException异常
bean元素的parent属性可以指定当前bean的父bean,子bean可以继承父bean中配置信息,也可以自定义配置信息,这样可以覆盖父bean中的配置

Spring注解

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

基于Java的配置,允许你在少量的Java注解的帮助下,进行你的大部分Spring配置而非通过XML文件。

@Configuration:用来标记类可以当做一个的定义,被Spring IOC容器使用。
@Bean注解:表示此方法将要返回一个对象,作为一个bean注册进Spring应用上下文。

怎样开启注解装配?

注解装配在默认情况下是不开启的,为了使用注解装配,我们必须在Spring配置文件中配置 context:annotation-config/元素。

@Required 注解

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

@Autowired 注解

@Autowired 注解提供了更细粒度的控制,包括在何处以及如何完成自动装配。它的用法和@Required一样,修饰setter方法、构造器、属性或者具有任意名称和/或多个参数的PN方法。

@Qualifier 注解

当有多个相同类型的bean却只有一个需要自动装配时,将@Qualifier 注解和@Autowire 注解结合使用可以消除这种混淆。
原理:指定需要装配的确切的bean的name属性,此时相当于按照name进行装配。

@AutoWired和@Resource的区别

@AutoWired默认以类型进行查找,
@Resource默认以名称进行查找
@AutoWired(required=false) + @Qualifier(“user”) == @Resource(name=“user”)

@Component和@Bean的区别是什么?

作用对象不同。
@Component注解作用于类,而@Bean注解作用于方法。
@Component注解通常是通过类路径扫描来自动侦测以及自动装配到Spring容器中(我们可以使用@ComponentScan注解定义要扫描的路径)。
@Bean注解通常是在标有该注解的方法中定义产生这个bean(即方法需要返回一个Bean给Spring容器),告诉Spring这是某个类的实例,当我需要用它的时候还给我。
@Bean注解比@Component注解的自定义性更强,而且很多地方只能通过@Bean注解来注册bean。比如当引用第三方库的类需要装配到Spring容器的时候,就只能通过@Bean注解来实现。

声明为Bean的注解有哪些?

@Component注解。通用的注解,可标注任意类为Spring组件。如果一个Bean不知道属于哪一个层,可以使用@Component注解标注。
@Repository注解。对应持久层,即Dao层,主要用于数据库相关操作。
@Service注解。对应服务层,即Service层,主要涉及一些复杂的逻辑,需要用到Dao层(注入)。
@Controller注解。对应Spring MVC的控制层,即Controller层,主要用于接受用户请求并调用Service层的方法返回数据给前端页面。

Spring数据访问

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

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

Spring JdbcTemplate详解

JdbcTemplate

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

Spring对DAO的支持

Spring对数据访问对象(DAO)的支持旨在简化它和数据访问技术,如JDBC,Hibernate or JDO 结合使用。这使我们可以方便切换持久层。编码时也不用担心会捕获每种技术特有的异常。

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

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

Spring支持的ORM

PS:ORM即对象关系映射,通过使用描述对象和数据库之间映射的元数据,将面向对象语言程序中的对象自动持久化到关系数据库中。

JSpring支持以下ORM:

Hibernate
iBatis
JPA (Java Persistence API)
TopLink
JDO (Java Data Objects)
OJB

Spring支持的事务管理类型

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

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

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

你更倾向用那种事务管理类型?

大多数Spring框架的用户选择声明式事务管理,因为它对应用代码的影响最小,因此更符合一个无侵入的轻量级容器的思想。声明式事务管理要优于编程式事务管理,虽然比编程式事务管理(这种方式允许你通过代码控制事务)少了一点灵活性。

Spring面向切面编程(AOP)

Spring中AOP名词解释

JoinPoint(连接点):指目标对象中,所有可以增强的方法。Spring只支持方法连接点。
Pointcut(切入点):指目标对象中,已经被增强的方法。调用这几个方法之前、之后或者抛出异常时干点什么,那么就用切入点来定义这几个方法。
Advice(通知/增强) :增强方法的代码、想要的功能。
Target(目标对象):被代理对象,被通知的对象,被增强的类对象。
Weaving(织入):将通知应用到连接点形成切入点的过程。
Proxy(代理):将通知织入到目标对象之后形成的代理对象
Aspect(切面):切入点+通知————通知(Advice)说明了干什么的内容(即方法体代码)和什么时候干(什么时候通过方法名中的before,after,around等就能知道),二切入点说明了在哪干(指定到底是哪个方法),切点表达式等定义。

Aspect 切面?

AOP核心就是切面,它将多个类的通用行为封装成可重用的模块,该模块含有一组API提供横切功能。比如,一个日志模块可以被称作日志的AOP切面。根据需求的不同,一个应用程序可以有若干切面。在Spring AOP中,切面通过带有@Aspect注解的类实现。

在Spring AOP 中,关注点和横切关注的区别是什么?

关注点是应用中一个模块的行为,一个关注点可能会被定义成一个我们想实现的一个功能。横切关注点是一个关注点,此关注点是整个应用都会使用的功能,并影响整个应用,比如日志,安全和数据传输,几乎应用的每个模块都需要的功能。因此这些都属于横切关注点。

连接点

连接点代表一个应用程序的某个位置,在这个位置我们可以插入一个AOP切面,它实际上是个应用程序执行Spring AOP的位置。

通知

通知是个在方法执行前或执行后要做的动作,实际上是程序执行时要通过SpringAOP框架触发的代码段。
Spring切面可以应用五种类型的通知:

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

切点

切入点是一个或一组连接点,通知将在这些位置执行。可以通过表达式或匹配的方式指明切入点。

什么是引入?

引入允许我们在已存在的类中增加新的方法和属性。

什么是目标对象?

被一个或者多个切面所通知的对象。它通常是一个代理对象。也指被通知(advised)对象。

什么是代理?

代理是通知目标对象后创建的对象。从客户端的角度看,代理对象和目标对象是一样的。

什么是织入。什么是织入应用的不同点?

织入是将切面和到其他应用类型或对象连接或创建一个被通知对象的过程。
织入可以在编译时,加载时,或运行时完成。

解释基于XML Schema方式的切面实现

在这种情况下,切面由常规类以及基于XML的配置实现。

解释基于注解的切面实现

在这种情况下(基于@AspectJ的实现),涉及到的切面声明的风格与带有java5标注的普通java类一致。

Spring 的事务

事务的特性

原子性(Atomicity):事务是一个原子操作,由一系列动作组成。事务的原子性确保动作要么全部完成,要么完全不起作用。
一致性(Consistency):一旦事务完成(不管成功还是失败),系统必须确保它所建模的业务处于一致的状态,而不会是部分完成部分失败。在现实中的数据不应该被破坏。
隔离性(Isolation):可能有许多事务会同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏。
持久性(Durability):一旦事务完成,无论发生什么系统错误,它的结果都不应该受到影响,这样就能从任何系统崩溃中恢复过来。通常情况下,事务的结果被写到持久化存储器中。

Spring事务的种类

Spring支持编程式事务管理和声明式事务管理两种方式:
编程式事务:使用TransactionTemplate,在代码中硬编码(不推荐使用)。
声明式事务:建立在AOP之上的,在配置文件中配置(推荐使用),分为基于XML的声明式事务和基于注解的声明式事务。
小结:

声明式事务最大的优点就是不需要在业务逻辑代码中掺杂事务管理的代码,其本质是通过AOP功能,对方法前后进行拦截,将事务处理的功能编织到拦截的方法中,也就是在目标方法开始之前加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务,只需在配置文件中做相关的事务规则声明或通过@Transactional注解的方式,便可以将事务规则应用到业务逻辑中。
声明式事务管理要优于编程式事务管理,这正是spring倡导的非侵入式的开发方式,使业务代码不受污染,只要加上注解就可以获得完全的事务支持。唯一不足地方是,最细粒度只能作用到方法级别,无法做到像编程式事务那样可以作用到代码块级别。

Spring事务的隔离级别

在TransactionDefinition接口中定义了五个表示隔离级别的常量:

ISOLATION_DEFAULT:使用后端数据库默认的隔离级别,Mysql默认采用的REPEATABLE_READ隔离级别;Oracle默认采用的READ_COMMITTED隔离级别。
ISOLATION_READ_UNCOMMITTED:最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。
ISOLATION_READ_COMMITTED:允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生
ISOLATION_REPEATABLE_READ:对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
ISOLATION_SERIALIZABLE:最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。

Spring事务的传播行为

在TransactionDefinition接口中定义了七个表示事务传播行为的常量。

支持当前事务的情况:
PROPAGATION_REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
PROPAGATION_SUPPORTS: 如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
PROPAGATION_MANDATORY: 如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。(mandatory:强制性)。
不支持当前事务的情况:
PROPAGATION_REQUIRES_NEW: 创建一个新的事务,如果当前存在事务,则把当前事务挂起。
PROPAGATION_NOT_SUPPORTED: 以非事务方式运行,如果当前存在事务,则把当前事务挂起。
PROPAGATION_NEVER: 以非事务方式运行,如果当前存在事务,则抛出异常。
其他情况:
PROPAGATION_NESTED: 如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于PROPAGATION_REQUIRED。

参考文章:Spring知识点汇总

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值