Java Spring框架

什么是框架?

框架(Framework):框(指其约束性)架(指其支撑性),在软件设计中指为解决一个开放性问题而设计的具有一定约束性的支撑结构。在此结构上可以根据具体问题扩展、安插更多的组成部分,从而更迅速和方便地构建完整的解决问题的方案。
它是一个半成品,已经对基础的代码进行了封装并提供相应的API,开发者在使用框架是直接调用封装好的API可以省去很多代码编写,从而提高工作效率和开发速度。

什么是Spring框架?

Spring官网链接: https://spring.io.

Spring 被称为 J2EE 的春天,是一个是分层的 Java SE/EE full-stack 开源的轻量级的 Java 开发框架, 是最受欢迎的企业级 Java 应用程序开发框架,数以百万的来自世界各地的开发人员使用 Spring 框架来创建性能好、易于测试、可重用的代码。
Spring具有控制反转(IoC)和面向切面(AOP)两大核心。Java Spring 框架通过声明式方式灵活地进行事务的管理,提高开发效率和质量。
Spring 框架不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何 Java 应用都可以从 Spring 中受益。Spring 框架还是一个超级粘合平台,除了自己提供功能外,还提供粘合其他技术和框架的能力。

Spring能干什么?

在这里插入图片描述

Spring的优势

1、方便解耦,简化开发Spring 就是一个大工厂,可以将所有对象的创建和依赖关系的维护交给Spring 管理。
2、方便集成各种优秀框架Spring 不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如 Struts2、Hibernate、MyBatis 等)的直接支持。
3、降低 Java EE API 的使用难度Spring 对 Java EE 开发中非常难用的一些 API(JDBC、JavaMail、远程调用等)都提供了封装,使这些 API 应用的难度大大降低。
4、方便程序的测试Spring 支持 JUnit4,可以通过注解方便地测试 Spring 程序。
5、AOP 编程的支持Spring 提供面向切面编程,可以方便地实现对程序进行权限拦截和运行监控等功能。
6、声明式事务的支持只需要通过配置就可以完成对事务的管理,而无须手动编程。

Spring的体系结构

在这里插入图片描述

  1. 核心容器
  • 核心容器由 Spring-core,Spring-beans,Spring-context,Spring-context-support和Springexpression(SpEL,Spring表达式语言,Spring Expression Language)等模块组成
  • Spring-core 模块提供了框架的基本组成部分,包括 IoC 和依赖注入功能。
  • Spring-beans 模块提供 BeanFactory,工厂模式的微妙实现,它移除了编码式单例的需要,并且可以把配置和依赖从实际编码逻辑中解耦。
  • context 模块建立在由 core和 beans 模块的基础上建立起来的,它以一种类似于 JNDI 注册的方式访问对象。Context 模块继承自 Bean 模块,并且添加了国际化(比如,使用资源束)、事件传播、资源加载和透明地创建上下文(比如,通过 Servelet 容器)等功能。Context 模块也支持 JavaEE 的功能,比如 EJB、JMX 和远程调用等。ApplicationContext 接口是 Context 模块的焦点。Spring-context-support 提供了对第三方集成到 Spring 上下文的支持,比如缓存(EhCache,Guava, JCache)、邮件(JavaMail)、调度(CommonJ, Quartz)、模板引擎(FreeMarker,JasperReports, Velocity)等。
  • Spring-expression 模块提供了强大的表达式语言,用于在运行时查询和操作对象图。它是 JSP2.1规范中定义的统一表达式语言的扩展,支持 set 和 get 属性值、属性赋值、方法调用、访问数组集合及索引的内容、逻辑算术运算、命名变量、通过名字从 Spring IoC 容器检索对象,还支持列表的投影、选择以及聚合等。
  • 它们的完整依赖关系如下图所示:
    在这里插入图片描述
  1. 数据访问/集成
  • JDBC=Java Data Base Connectivity,ORM=Object Relational Mapping,OXM=Object XML
    Mapping,JMS=Java Message Service

  • JDBC 模块提供了 JDBC 抽象层,它消除了冗长的 JDBC 编码和对数据库供应商特定错误代码的解析。

  • ORM 模块提供了对流行的对象关系映射 API 的集成,包括 JPA、JDO 和 Hibernate 等。通过此模块可以让这些 ORM 框架和 Spring的其它功能整合,比如前面提及的事务管理。

  • OXM 模块提供了对 OXM 实现的支持,比如 JAXB、Castor、XML Beans、JiBX、XStream 等。

  • JMS 模块包含生产(produce)和消费(consume)消息的功能。从 Spring 4.1 开始,集成了
    Spring-messaging 模块。

  • 事务模块为实现特殊接口类及所有的 POJO 支持编程式和声明式事务管理。

  1. Web
  • Web 模块提供面向 web 的基本功能和面向 web 的应用上下文,比如多部分(multipart)文件上
    传功能、使用 Servlet 监听器初始化 IoC 容器等。它还包括 HTTP 客户端以及 Spring 远程调用中与web 相关的部分。
  • Web-MVC 模块为 web 应用提供了模型视图控制(MVC)和 REST Web服务的实现。Spring 的
    MVC 框架可以使领域模型代码和 web 表单完全地分离,且可以与 Spring 框架的其它所有功能进行集成。
  • Web-Socket 模块为 WebSocket-based 提供了支持,而且在 web 应用程序中提供了客户端和服
    务器端之间通信的两种方式。
  • spring-webflux:是一个新的非阻塞式Reactive Web框架,可以用来建立异步、非阻塞、事件驱动的服务,并且扩展性非常好。
  • 参考如下图包结构
    在这里插入图片描述
  1. 其他
  • AOP 模块提供了面向方面(切面)的编程实现,允许你定义方法拦截器和切入点对代码进行干净地解耦,从而使实现功能的代码彻底的解耦出来。
  • Aspects 模块提供了与 AspectJ 的集成,这是一个功能强大且成熟的面向切面编程(AOP)框
    架。
  • Instrumentation 模块在一定的应用服务器中提供了类 instrumentation 的支持和类加载器的实
    现。
  • Messaging 模块为 STOMP 提供了支持作为在应用程序中 WebSocket 子协议的使用。它也支持一个注解编程模型,它是为了选路和处理来自 WebSocket 客户端的 STOMP 信息。
  • 测试模块支持对具有 JUnit 或 TestNG 框架的 Spring 组件的测试。

Spring核心之IoC控制反转

IoC的概念

Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。

IoC 是指在程序开发中,实例的创建不再由调用者管理,而是由 Spring 容器创建。Spring 容器会负责控制程序之间的关系,而不是由程序代码直接控制,因此,控制权由程序代码转移到了 Spring 容器中,控制权发生了反转,这就是 Spring 的 IoC 思想。

使用Spring容器创建对象

1.配置文件中创建对象

<?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="student" class="com.link.pojo.Student"></bean>
<!--创建非自定义的对象-->
<bean id="date" class="java.util.Date"></bean>
</beans>

bean标签的属性

属性说明
class指定bean对应类的全路径
namename是bean对应对象的一个标识
scope执行bean对象创建模式和生命周期,scope="singleton"和scope=“prototype”
idid是bean对象的唯一标识,不能添加特别字符
lazy-init是否延时加载 默认值:false。true 延迟加载对象,当对象被调用的时候才会加载,测试的时候,通过getbean()方法获得对象。lazy-init=“false” 默认值,不延迟,无论对象是否被使用,都会立即创建对象,测试时只需要加载配置文件即可。注意:测试的时候只留下id,class属性
init-method只需要加载配置文件即可对象初始化方法
destroy-method对象销毁方法

获取Spring容器

Spring 提供了两种 IoC 容器,分别为 BeanFactory 和 ApplicationContext.

  • BeanFactory
    BeanFactory 是基础类型的 IoC 容器,是一个管理 Bean 的工厂,它主要负责初始化各种 Bean,并调用它们的生命周期方法。
    BeanFactory 接口有多个实现类,最常见的是
    org.Springframework.beans.factory.xml.XmlBeanFactory,它是根据 XML 配置文件中的定义装配Bean 的。
    列如:
BeanFactory beanFactory = new XmlBeanFactory(new FileSystemResource(Spring配置文件
的名称));
  • ApplicationContext
    ApplicationContext 是 BeanFactory 的子接口,也被称为应用上下文。它不仅提供了 BeanFactory 的所有功能,还添加了对 i18n(国际化)、资源访问、事件传播等方面的良好支持。ApplicationContext 接口有两个常用的实现类:
    1.ClassPathXmlApplicationContext
    类从类路径 ClassPath 中寻找指定的 XML 配置文件,找到并装载完成 ApplicationContext 的实例化工作
ApplicationContext applicationContext=new ClassPathXmlApplicationContext(Spring配
置文件的名称);

2.FileSystemXmlApplicationContext

ApplicationContext applicationContext = new FileSystemXmlApplicationContext(StringconfigLocation);

它与 ClassPathXmlApplicationContext 的区别是:在读取 Spring 的配置文件时,FileSystemXmlApplicationContext 不再从类路径中读取配置文件,而是通过参数指定配置文件的位
置,它可以获取类路径之外的资源,如“D:\application.xml”。

基于XML的DI

  • DI—Dependency Injection,即“依赖注入”:是组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。

  • IoC 是一个概念,是一种思想,其实现方式多种多样。依赖注入就是其中用的比较多的一种方式。

  • Ioc和DI是同一个概念的不同角度描述。IoC是一种思想,概念,DI是实现它的手段。Spring框架使用依赖注入实现IoC.

  • Spring 容器是一个超级大工厂,负责创建、管理所有的 Java 对象,这些 Java 对象被称为 Bean。

  • Spring 容器管理着容器中 Bean 之间的依赖关系,Spring 使用“依赖注入”的方式来管理 Bean 之间的依赖关系。使用 IoC 实现对象之间的解耦和。

注入分类

bean 实例在调用无参构造器创建对象后,就要对 bean 对象的属性进行初始化。初始化是由容器自动完成的,称为注入。

通过set方法

set 注入也叫设值注入是指,通过 setter 方法传入被调用者的实例。这种注入方式简单、直观,因而在Spring 的依赖注入中大量使用。

通过构造方法

构造注入是指,在构造调用者实例的同时,完成被调用者的实例化。使用构造器设置依赖关系。

自动注入

对于引用类型属性的注入,也可不在配置文件中显示的注入。可以通过为标签设置 autowire 属性值,为引用类型属性进行隐式自动注入(默认是不自动注入引用类型属 性)。根据自动注入判断标准的不同,可以分为两种:
byName:根据名称自动注入
byType: 根据类型自动注入
1、 byName
当配置文件中被调用者 bean 的 id 值与代码中调用者 bean 类的属性名相同时,可使用byName 方式,让容器自动将被调用者 bean 注入给调用者 bean。容器是通过调用者的 bean类的属性名与配置文件的被调用者 bean 的 id 进行比较而实现自动注入的。
2、 byType
使用 byType 方式自动注入,要求:配置文件中被调用者 bean 的 class 属性指定的类,要与代码中调用者 bean 类的某引用类型属性类型同源。即要么相同,要么有 is-a 关系(子类,或是实现类)。但这样的同源的被调用 bean 只能有一个。多于一个,容器就不知该匹配哪一个了。

基于注解实现IoC

对于 DI 使用注解,将不再需要在 Spring 配置文件中声明 bean 实例。Spring 中使用注解,需要在原有Spring 运行环境基础上再做一些改变。

  • 声明Bean的注解 @Component
    在类上添加注解@Component表示该类创建对象的权限交给Spring容器。注解的value属性用于指定bean的id值,value可以省略。
    @Component 不指定 value 属性,bean 的 id 是类名的首字母小写。
    除此之外,Spring中还提供了其他3个用于创建对象的注解:
    @Repository : 用于dao实现类的的注解
    @Service: 用户service实现类的注解
    @Controller: 用于controller实现类的注解
    这三个注解与@Component 都可以创建对象,但这三个注解还有其他的含义,@Service创建业务层对象,业务层对象可以加入事务功能,@Controller 注解创建的对象可以作为处理器接收用户的求。
    @Repository,@Service,@Controller 是对@Component 注解的细化,标注不同层的对象。即持久层对象,业务层对象,控制层对象。

包扫描

需要在 Spring 配置文件中配置组件扫描器,用于在指定的基本包中扫描注解。如果没有报扫描,添加的创建对象的注解不生效。

如果要扫描的包有多个,可以有以下方式扫描:
1、使用多个context:component-scan指定不同的包路径

<context:component-scan base-package="com.link.dao"></context:component-scan>
    <context:component-scan base-package="com.link.service"></context:component-scan>
    <context:component-scan base-package="com.link.controller"></context:component-scan>

2、指定 base-package的值使用分隔符

<context:component-scan basepackage="com.link.dao,com.link.service,com.link.controller"></context:componentscan>

3、base-package是指定到父包名
base-package 的值表是基本包,容器启动会扫描包及其子包中的注解,当然也会扫描到子包下级的子包。所以 base-package 可以指定一个父包就可以。
但不建议使用顶级的父包,扫描的路径比较多,导致容器启动时间变慢。指定到目标包和合适的。也就是注解所在包全路径。

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

属性注入@Vaule

需要在属性上使用注解@Value,该注解的 value 属性用于指定要注入的值。使用该注解完成属性注入时,类中无需 setter。当然,若属性有 setter,则也可将其加到 setter 上。

byType自动注入@Autowired

需要在引用属性上使用注解@Autowired,该注解默认使用按类型自动装配 Bean 的方式。使用该注解完成属性注入时,类中无需 setter。当然,若属性有 setter,则也可将其加到 setter 上。

byName自动注入@Autowired和@Qualifier

需要在引用属性上联合使用注解@Autowired 与@Qualifier。@Qualifier 的 value 属性用于指定要匹配的 Bean 的 id 值。类中无需 set 方法,也可加到 set 方法上。

@Autowired 还有一个属性 required,默认值为 true,表示当匹配失败后,会终止程序运行。若将其值设置为 false,则匹配失败,将被忽略,未匹配的属性值为 null。

自动注入@Resource

Spring提供了对 jdk中@Resource注解的支持。@Resource 注解既可以按名称匹配Bean,也可以按类型匹配 Bean。默认是按名称注入。使用该注解,要求 JDK 必须是 6 及以上版本。@Resource 可在属性上,也可在 set 方法上。
1、byType注入引用类型属性
@Resource 注解若不带任何参数,采用默认按名称的方式注入,按名称不能注入 bean,则会按照类型进行 Bean 的匹配注入。
2、byName注入引用类型属性
@Resource 注解指定其 name 属性,则 name 的值即为按照名称进行匹配的 Bean 的 id。

Spring核心之AOP

什么是AOP

AOP为Aspect Oriented Programming的缩写,意思为面向切面编程,是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。
AOP的作用:不修改源码的情况下,程序运行期间对方法进行功能增强
好处:
1、减少代码的重复,提高开发效率,便于维护。
2、专注核心业务的开发。
核心业务和服务性代码混合在一起
开发中:各自做自己擅长的事情,运行的时候将服务性代码织入到核心业务中。
通过spring工厂自动实现将服务性代码以切面的方式加入到核心业务代码中。

SpringAOP

  • Spring AOP相关概念
    Spring的AOP实现底层就是对上面的动态代理的代码进行了封装,封装后我们只需要对需要关注的部分进行代码编写,并通过配置的方式完成指定目标的方法增强。
  • Target(目标对象)
    要被增强的对象,一般是业务逻辑类的对象。
  • Proxy(代理)
    一个类被 AOP 织入增强后,就产生一个结果代理类。
  • Aspect(切面)
    表示增强的功能,就是一些代码完成的某个功能,非业务功能。是切入点和通知的结合。
  • Joinpoint(连接点)
    所谓连接点是指那些被拦截到的点。在Spring中,这些点指的是方法(一般是类中的业务方法),因为Spring只支持方法类型的连接点。
  • Pointcut(切入点)
    切入点指声明的一个或多个连接点的集合。通过切入点指定一组方法。
    被标记为 final 的方法是不能作为连接点与切入点的。因为最终的是不能被修改的,不能被增强的。
  • Advice(通知/增强)
    所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知。通知定义了增强代码切入到目标代码的时间点,是目标方法执行之前执行,还是之后执行等。通知类型不同,切入时间不同。
    通知的类型:前置通知,后置通知,异常通知,最终通知,环绕通知。
    切入点定义切入的位置,通知定义切入的时间。
  • Weaving(织入).
    是指把增强应用到目标对象来创建新的代理对象的过程。 spring 采用动态代理织入,而 AspectJ 采用编译期织入和类装载期织入。

AspectJ 对 AOP 的实现

对于 AOP 这种编程思想,很多框架都进行了实现。Spring 就是其中之一,可以完成面向切面编程。
AspectJ 也实现了 AOP 的功能,且其实现方式更为简捷而且还支持注解式开发。所以,Spring 又将
AspectJ 的对于 AOP 的实现也引入到了自己的框架中。
在 Spring 中使用 AOP 开发时,一般使用 AspectJ 的实现方式

AspectJ的通知类型

AspectJ 中常用的通知有5种类型:

  1. 前置通知
  2. 后置通知
  3. 环绕通知
  4. 异常通知
  5. 最终通知

AspectJ的切入点表达式

AspectJ 定义了专门的表达式用于指定切入点。
表达式的原型如下:
execution(modifiers-pattern? ret-type-pattern
declaring-type-pattern?name-pattern(param-pattern)
throws-pattern?)
说明:
modifiers-pattern] 访问权限类型
ret-type-pattern 返回值类型
declaring-type-pattern 包名类名
name-pattern(param-pattern) 方法名(参数类型和参数个数)
throws-pattern 抛出异常类型
?表示可选的部分

以上表达式共 4 个部分。
execution(访问权限 方法返回值 方法声明(参数) 异常类型)
切入点表达式要匹配的对象就是目标方法的方法名。所以,execution 表达式中就是方法的签名。

符号Value
*0-多个任意字符
用在方法参数中,表示任意个参数;用在包名后,表示当前及其子包路径
+用在类名后,表示当前及其子类;用在接口后,表示当前接口及其实现类

Spring整合JDBC

使用spring-jdbc操作数据库

添加依赖

<dependencies>
        <!--spring 核心依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.13.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.13.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.23</version>
        </dependency>
        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.5.2</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.6</version>
        </dependency>
        <!--测试依赖-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <!--编译插件-->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.0</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

测试连接

import com.mchange.v2.c3p0.ComboPooledDataSource;
        import org.junit.Test;
        import org.springframework.jdbc.core.JdbcTemplate;
        import java.beans.PropertyVetoException;
public class Test01 {
    @Test
    public void test01() throws PropertyVetoException {
//创建数据源
        ComboPooledDataSource dataSource=new ComboPooledDataSource();
        dataSource.setDriverClass("com.mysql.cj.jdbc.Driver");
        dataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/springJDBC?
                serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false");
                dataSource.setUser("root");
        dataSource.setPassword("******");
//使用JDBCTemplete
        JdbcTemplate template=new JdbcTemplate(dataSource);
        String sql="insert into student(sno,sname) value (?,?)";
        int update = template.update(sql,"1","张三");
        System.out.println("插入数据的结果:"+update);
    }
}

Spring管理JdbcTemplate

spring整合jdbc的时候直接让dao继承Spring提供的JdbcDaoSupport类,该类中提供了
JdbcTemplate模板可用。

public class TeamDao extends JdbcDaoSupport {


    public int getCount(){
        String sql="select count(sno) from student";
        return this.getJdbcTemplate().queryForObject(sql,Integer.class);
    }

    public Map<String, Object> getMany(){
        String sql="select max(sno),min(sno) from team";
        return this.getJdbcTemplate().queryForMap(sql);
    }

    /**
     * 自己封装一个处理结果的方法
     * @param resultSet
     * @return
     * @throws SQLException
     */
    public Student handlResult(ResultSet resultSet) throws SQLException {
        Student student=new Student();
        student.setSno(resultSet.getInt("sno"));
        return student;
    }

    public List<Student> findAll(){
        String sql="select * from student";
        return this.getJdbcTemplate().query(sql, new RowMapper<Student>() {
            @Override
            public Team mapRow(ResultSet resultSet, int i) throws SQLException {
                return handlResult(resultSet);
            }
        });
    }

    public Team findById(int sno){
        String sql="select * from student where sno=?";
        return this.getJdbcTemplate().queryForObject(sql, new Object[]{sno}, new RowMapper<Student>() {
            @Override
            public Team mapRow(ResultSet resultSet, int i) throws SQLException {
                return handlResult(resultSet);
            }
        });
    }

    public int insert(Student student){
        //使用JDBCTemplete
       // JdbcTemplate template=new JdbcTemplate(dataSource);
        String sql="insert into student(sno,sname) value (?,?)";
        return  this.getJdbcTemplate().update(sql,team.getSno(),team.getSname());
    }

    public int update(Student student){
        //使用JDBCTemplete
        // JdbcTemplate template=new JdbcTemplate(dataSource);
        String sql="update team set sno=? ,sname=? where sno=?";
        return  this.getJdbcTemplate().update(sql,student.getSno(),student.getSname(),student.getSno());
    }

    public int del(int sno){
        //使用JDBCTemplete
        // JdbcTemplate template=new JdbcTemplate(dataSource);
        String sql="delete from student where sno=?";
        return  this.getJdbcTemplate().update(sql,sno);
    }
}

spring的配置文件application.xml中需要创建数据源和给TeamDao中的jdbcTemplate赋值

 <context:component-scan base-package="com.kkb"/>
    <!--创建 JdbcTemplate 的数据源-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="com.mysql.cj.jdbc.Driver"></property>
        <property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/springJDBC?serverTimezone=UTC&amp;characterEncoding=utf8&amp;useUnicode=true&amp;useSSL=false"></property>
        <property name="user" value="root"></property>
        <property name="password" value="******"></property>
    </bean>
    <!--创建JdbcTemplate-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <bean id="studentDao" class="com.link.dao.StudentDao">
        <property name="jdbcTemplate" ref="jdbcTemplate"></property>
    </bean>

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <tx:annotation-driven transaction-manager="transactionManager" />

    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="insert*" propagation="REQUIRED"/>
            <tx:method name="add*" propagation="REQUIRED"/>
            <tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
        </tx:attributes>
    </tx:advice>

    <aop:config>
        <aop:pointcut id="pt" expression="execution(* com.link.service..*.*(..))"/>
        <aop:advisor advice-ref="txAdvice"  pointcut-ref="pt" />
    </aop:config>
</beans>

Spring事务管理

事务原本是数据库中的概念,在 Dao 层。但在实际开发中,一般将事务提升到业务层,即 Service 层。这样做是为了能够使用事务的特性来管理具体的业务。

事务隔离级别常量

这些常量均是以 ISOLATION_开头。即形如 ISOLATION_XXX。
➢ DEFAULT:采用 DB 默认的事务隔离级别。MySql 的默认为 REPEATABLE_READ; Oracle默认为
READ_COMMITTED。
➢ READ_UNCOMMITTED:读未提交。未解决任何并发问题。
➢ READ_COMMITTED:读已提交。解决脏读,存在不可重复读与幻读。
➢ REPEATABLE_READ:可重复读。解决脏读、不可重复读,存在幻读
➢ SERIALIZABLE:串行化。不存在并发问题。

事务传播行为常量

所谓事务传播行为是指,处于不同事务中的方法在相互调用时,执行期间事务的维护情况。如,A 事务中的方法 doSome()调用 B 事务中的方法 doOther(),在调用执行期间事务的维护情况,就称为事务传播行为。事务传播行为是加在方法上的。
事务传播行为常量都是以 PROPAGATION_ 开头,形如 PROPAGATION_XXX。
Propagation.REQUIRED
当前没有事务的时候,就会创建一个新的事务;如果当前有事务,就直接加入该事务,比较常用的
设置 Propagation.SUPPORTS
支持当前事务,如果当前有事务,就直接加入该事务;当前没有事务的时候,就以非事务方式执行
Propagation.MANDATORY
支持当前事务,如果当前有事务,就直接加入该事务;当前没有事务的时候,就抛出异常
Propagation.REQUIRES_NEW
创建新事务,无论当前是否有事务都会创建新的
PROPAGATION_NESTED
PROPAGATION_NEVER
PROPAGATION_NOT_SUPPORTED

默认事务超时时限

常量 TIMEOUT_DEFAULT 定义了事务底层默认的超时时限,sql 语句的执行时长。
注意,事务的超时时限起作用的条件比较多,且超时的时间计算点较复杂。所以,该值一般就使用默认值即可。

声明式事务控制

Spring提供的对事务的管理,就叫做声明式事务管理。
如果用户需要使用spring的声明式事务管理,在配置文件中配置即可:不想使用的时候直接移除置。
这种方式实现了对事务控制的最大程度的解耦。
声明式事务管理,核心实现就是基于AOP。

Spring中提供了对事务的管理。开发者只需要按照spring的方式去做就行。
事务必须在service层统一控制。
事务的粗细粒度:
细粒度:对方法中的某几行的代码进行开启提交回滚;
粗粒度:对整个方法进行开启提交回滚;
Spring中的aop只能对方法进行拦截,所有我们也就针对方法进行事务的控制。
如果只有单条的查询语句,可以省略事务;如果一次执行的是多条查询语句,例如统计结果、报表查询。必须
开启事务。

基于注解的事务

@Service
public class TeamService {
    @Autowired
    private TeamDao teamDao;
    /**
     * @Transactional 属性 说明:
     * readOnly:是否只读
     *
     * rollbackFor={Exception.class}: 遇到什么异常会回滚
     *
     * propagation事务的传播:
     * Propagation.REQUIRED:当前没有事务的时候,就会创建一个新的事务;如果当前有事务,就直
    接加入该事务,比较常用的设置
     * Propagation.SUPPORTS:支持当前事务,如果当前有事务,就直接加入该事务;当前没有事务的
    时候,就以非事务方式执行
     * Propagation.MANDATORY:支持当前事务,如果当前有事务,就直接加入该事务;当前没有事务的
    时候,就抛出异常
     * Propagation.REQUIRES_NEW:创建新事务,无论当前是否有事务都会创建新的
     *
     * isolation=Isolation.DEFAULT:事务的隔离级别:默认是数据库的隔离级别
     *
     */
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor =
            {Exception.class})
    public int insert(Team team){
        int num1=teamDao.insert(team);
        System.out.println("第一条执行结果:num1="+num1);
        System.out.println(10/0);
        int num2=teamDao.insert(team);
        System.out.println("第二条执行结果:num2="+num2);
        return num2+num1;
    	}
    }
<!--配置文件中添加context约束-->
<context:component-scan base-package="com.kkb"/>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />

基于XML的事务

添加依赖

<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>
<!-- 事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="insert*" propagation="REQUIRED"/>
<tx:method name="add*" propagation="REQUIRED"/>
<tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="pt" expression="execution(* com.link.service..*.*
        (..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt" />
</aop:config>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Link♛

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

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

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

打赏作者

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

抵扣说明:

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

余额充值