[Java框架]SSM框架之Spring

目录

简介

特点:

体验spring

属性注入

构造器注入

set注入

复杂对象

类型转换器

p命名空间和c命名空间

自动装配

注解注入

工厂模式

beanfactory

factorybean

实例工厂

静态工厂

bean生命周期

spring注解开发

类的注入

方法的注入

属性的注入

AOP

织入点语法

通知(advice)

实现接口

定义切面

注解方式

整合mybatis

spring事务


简介

spring 是目前主流的 Java Web 开发框架。Spring 是分层的 Java SE/EE 一站式轻量级开源框架,以 IoC(Inverse of Control,控制反转)和 AOP(Aspect Oriented Programming,面向切面编程)为内核。

IoC 指的是将对象的创建权交给 Spring 去创建,IOC(控制对象的生命周期和对象间的关系)。使用 Spring 之前,对象的创建都是由我们使用 new 创建,而使用 Spring 之后,对象的创建都交给了 Spring 框架。在系统运行中,动态的向某个对象提供它所需要的其他对象。这一点是通过DI(Dependency Injection,依赖注入)来实现的。DI(通过反射实现属性的动态注入)。

AOP 用来封装多个类的公共行为,将那些与业务无关,却为业务模块所共同调用的逻辑封装起来,减少系统的重复代码,降低模块间的耦合度。另外,AOP 还解决一些系统层面上的问题,比如日志、事务、权限等。

特点:

  1. 方便解耦,简化开发
  2. 方便集成各种优秀框架,降低 Java EE API 的使用难度
  3. 声明式事务的支持
  4. AOP 编程的支持

体验spring

  1. 创建maven项目,导入spring依赖
  2. 编写beans.xml,和与之相关的Java bean类
  3. 编写ApplicationContext接口和ClassPathXmlApplicationContext实现类(编写spring底层,实际使用时不用,直接使用spring自带的) 读取beans.xml,调用getBean(接口类类型)
  4. 完成dao层和service层,测试运行

读取beans.xml:FileSystemXmlApplicationContext和ClassPathXmlApplicationContext,FileSystemXmlApplicationContext有两种写法1.盘符路径(绝对路径) 2.classpath:(相对路径),ClassPathXmlApplicationContext默认相对路径,不需要写classpath:

IoC控制反转的xml配置管理,也是spring框架的核心知识点之一,spring通过配置文件beans.xml动态实例对象(Dao dao=new DaoService a/b)

<?xml version="1.0" encoding="UTF-8"?>
<!--spring IOC 就是管理bean的生命周期和bean之间的关系-->
<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
               https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="personDao" class="com.xx.dao.impl.PersonDaoImpl">
        <property name="personInfoId" value="1"/>
        <property name="personInfo" value="abc"/>
    </bean>
    <bean id="personService" class="com.xx.service.impl.PersonServiceImpl">
        <!-- personService 需要使用一个id为personDao bean进行初始化-->
        <!--
        根据名称
        根据类型
        -->
        <property name="personDao" ref="personDao"/>
    </bean>

    <bean id="orderService" class="com.xx.service.impl.OrderServiceImpl">
        <property name="personDao" ref="personDao"/>
    </bean>
    <!-- <bean id="personDaoWithCount" class="com.xx.dao.impl.PersonDaoImpWithCount">
         <property name="personInfoId" value="1"/>
         <property name="personInfo" value="abc"/>
     </bean>-->
</beans>

属性注入

构造器注入

在Spring的配置文件中,使用bean标签,配置id和class属性之后,且没有其他属性和标签时。采用的就是默认构造函数创建bean对象,此时如果类中没有默认构造函数,则对象无法创建成功。

构造器注入属性值有三种方式:

  //通过下标传递参数
 <constructor-arg index="0">
 //通过类型传递参数
 <constructor-arg type="int">
 //通过属性名传递参数
 <constructor-arg name="cardId">

set注入

通过setter方法进行属性值注入

//set注入
<property name="persionId" value="1"/>

复杂对象

一些如property,map,list,set等复杂对象

      //property类型
    <props>
          //给property赋值
        <prop key="administrator">administrator@example.org</prop> 
        <prop key="support">support@example.org</prop> 
        <prop key="development">development@example.org</prop> 
    </props> 
      //map类型
    <map> 
             //给map属性赋值
         <entry key="an entry" value="just some string"/>
         //map的value是对象时使用 
        <entry key ="a ref" value-ref="myDataSource"/> 
    </map>
       //list类型
     <list> 
          //给list赋值
        <value>a list element followed by a reference</value>
         //list里是对象时使用 
        <ref bean="myDataSource" />
     </list> 
       //set类型
    <set> 
         //给set赋值
        <value>just some string</value>
          //set里是对象时使用 
        <ref bean="myDataSource" />
    </set> 

类型转换器

解决复杂类型,如日期

 //Java代码
public class MyConverter  implements Converter<String, Date> {

    @Override
    public Date convert(String source) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Date parse = simpleDateFormat.parse(source);
            return parse;
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }
}

//xml配置
<bean id="convert" class="com.xx.basic.convert.MyConverter"></bean>

<bean id="conversionService" 
    class="org.springframework.context.support.ConversionServiceFactoryBean">
      <property name="converters">
            <set>
                <ref bean="convert"></ref>
            </set>
      </property>
</bean>

p命名空间和c命名空间

p命名空间(简化set注入)

  • 实体类中必须有set方法;
  • 实体类中必须有无参构造器(默认存在);
  • 必须导入p命名空间注入方式依赖。

导入约束后在bean标签里添加 p:name="" 使用:

xmlns:p="http://www.springframework.org/schema/p"

c命名空间(简化构造器注入)

  • 实体类中必须存在有参构造器;
  • 必须导入c命名空间注入方式依赖。

导入约束后在bean标签里添加 c:name="" 使用:

xmlns:c="http://www.springframework.org/schema/c"

自动装配

使用autowire来配置自动装载模式

  • AUTOWIRE_NO(no):默认的方式是不进行自动装配的,通过手工设置ref属性来进行装配。bean。
  • AUTOWIRE_BY_NAME(byName):通过bean的名称进行自动装配。如果一个bean的property与另一个bean的name相同,就进行自动装配。
  • AUTOWIRE_BY_TYPE(byType):通过参数的数据类型进行自动装配.。
  • AUTOWIRE_CONSTRUCTOR(constructor):利用构造函数进行装配,并且构造函数的参数通过byType进行装配。
<bean id="person" class="com.xx.Person" autowire="constructor/byName/byType"></bean>

注解注入

@Value

     //添加约束
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd"
     //引入注解
    <context:annotation-config/>
     //引入属性文件
    <context:property-placeholder location="classpath:test.properties"/>

使用注解的方式需要用到注解@Value,在属性文件的读取中使用的是“$”,从Spring 容器中获取属性使用“#”。#{}里可以使用一些Java方法,案例:

ublic class PersonCard {
    @Value("${test.boolean}")
    private Boolean testBoolean;
    @Value("${test.string}")
    private String testString;
    @Value("${test.integer}")
    private Integer testInteger;
    @Value("${test.long}")
    private Long testLong;
    @Value("${test.float}")
    private Float testFloat;
    @Value("${test.double}")
    private Double testDouble;
    @Value("#{'${test.array}'.split(',')}")
    private String[] testArray;
    @Value("#{'${test.list}'.split(',')}")
    private List<String> testList;
    @Value("#{'${test.set}'.split(',')}")
    private Set<String> testSet;
    @Value("#{${test.map}}")
    private Map<String, Object> testMap;
}

工厂模式

一般用于构建复杂对象的实例,三种工厂模式(factorybean,实例工厂,静态工厂)。

单例对象:工厂启动工厂中所有的单例的对象随之创建,工厂销毁工厂中所有单例对象随之销毁    多例对象:每次在工厂中使用时进行创建,工厂不负责多例对象的销毁

beanfactory

BeanFactory 是 Spring 框架的核心接口之一,用于管理和获取应用程序中的 Bean 实例。它是一个工厂模式的实现,负责创建、配置和管理 Bean 对象。BeanFactory 是 Spring IoC 容器的基础,它可以从配置元数据(如 XML 文件)中读取 Bean 的定义,并在需要时实例化和提供这些 Bean。

factorybean

FactoryBean是一个能生产或者修饰对象生成的工厂Bean,它的实现与设计模式中的工厂模式和修饰器模式类似。创建实现类实现FactoryBean重写getObject(),在beans.xml配置实现类的bean和接口类的bean。

一般情况下,Spring是通过反射机制利用bean的class属性指定实现类来实例化bean的。在某些情况下,实例化bean过程比较复杂,如果按照传统的方式,那么则需要在标签中提供大量的配置信息,配置方式的灵活性是受限的,这时采用编码的方式可以得到一个更加简单的方案。Spring为此提供了一个org.springframework.bean.factory.FactoryBean的工厂类接口,用户可以通过实现该接口定制实例化bean的逻辑。

区别

生命周期流程:

使用beanFactory创建对象时,需要遵循严格的生命周期流程。它会按照预定的顺序执行各个生命周期阶段,包括实例化、属性填充、初始化和销毁等。这种严格的生命周期管理确保了bean的正确创建和销毁,但也使得自定义对象的创建变得复杂。

而在FactoryBean中,我们可以更加自由地定义对象的创建过程。通过实现FactoryBean接口,我们可以在getObject()方法中编写自定义的创建逻辑,从而实现更加灵活的对象创建方式。这使得我们能够根据需求定制对象的创建过程,而不需要遵循严格的生命周期流程。

对象管理:

使用beanFactory创建的对象由Spring容器负责管理,我们无需过多关心对象的创建和销毁。Spring容器会在需要时自动创建bean,并在容器关闭时销毁它们。

而FactoryBean创建的对象同样由Spring容器管理,但我们需要明确地将FactoryBean注册到容器中。这意味着我们可以通过配置文件或编码的方式明确指定要创建的bean是一个FactoryBean。Spring容器会自动检测到FactoryBean接口,并调用其getObject()方法获取实际的bean对象。

实例工厂

创建一个实例方法来创建Bean的实例,在beans.xml配置 bean调用实例方法(填写factory-beanfactory-method)

<bean id="id名" factory-bean="实例方法所在类的beanid" 
factory-method="实例方法名"></bean>

举例:

          //使用实例工厂
    <bean id="student1" class="com.xk.entity.Student">
        <property name="studentId" value="1"/>
        <property name="studentName" value="1"/>
        <property name="birthday">
             //这是属性并不是bean,不需要id
            <bean factory-bean="dateFormat" factory-method="parse" >
                <constructor-arg value="2023-01-01" />
            </bean>
        </property>
     </bean>

    <bean id="dateFormat" class="java.text.SimpleDateFormat">
        <constructor-arg value="yyyy-MM-dd" />
    </bean>

静态工厂

创建一个静态方法来创建Bean的实例(填写class和factory-method)

<bean id="id名" class="类的全限定名" factory-method="静态实例方法名"></bean>

由于spring默认单例模式,在测试启动时,默认会立即将单实例bean进行实例化,可以使用lazy-init=true 让bean使用时再实例

区别

  1. 静态工厂方法:初始化之前,工厂中的类已经被实例化放在工厂容器中
  2. 实例工厂方法:在构造方法初始化时,会将类进行实例化放在工厂中
  3. 静态工厂创建对象是一步到位,写一个bean标签即可;实例工厂创建对象是分两步,
    需要两个bean标签,一个标签是工厂类,另一个标签是对象类

bean生命周期

  • scope=“singleton” 单例模式:在启动(容器初始化之前),就已经创建了bean,且整个应用只有一个。先创建bean对象,然后把bean放到容器的map中,完成容器的初始化。
  • scope=“prototype” 原型模式:在用到对象的时候,才创建对象。
  1. 调用无参创建对象
  2. 调用set方法初始化属性
  3. 调用初始化方法
  4. 关闭容器,调用销毁的方法

对应的方法

  1. createBeanInstance() -> 实例化
  2. populateBean() -> 属性赋值
  3. initializeBean() -> 初始化
  4. destroyBeans() ->销毁

Spring 容器在初始化一个Bean实例时,会指定该实例的作用域,scope=""属性支持6 种作用域(scope属性)。1.singleton(单例模式) 2.prototype(原型模式) 3.request 4.session 5.application 6.websocket;后四种只能在web应用中使用。

singleton(单例模式)

Spring 容器中只有一个 Bean 实例,Bean 以单例的方式存在,每次都返回一个相同的 Bean 实例。底层由map存储,所以bean是同一个。容器启动的时候创建对象,容器正常关闭时销毁对象。Spring默认状态是单例的,单例默认状态是非懒加载的。

prototype(原型模式)

每次通过 Spring 容器获取 Bean 时,容器都会创建一个 Bean 实例。获取对象的时候创建对象,spring容器不负责对象的销毁。(垃圾回收机制)。多例状态是默认懒加载的,只要是多例模式都是懒加载,只有在单例模式下才能控制懒加载有效。

懒加载

(lazy-init="true/false"),默认是false,Spring在启动时,默认会立即将单实例bean进行实例化,并加载到Spring容器中。进行延迟加载(延迟到在第一次调用的时候实例化)可以节省资源

spring注解开发

类的注入

@Service(service层)、@Controller(controller层)、@Repository(dao层)、@Component(组件):作用于类。这四个注解作用都是一样的,把类注入bean中,作用等于<bean id="" >...</bean>。为了层次结构命名不同,组件是不好归类时使用。

方法的注入

@Bean:作用于方法,将方法返回的对象注册为一个 Bean(class=返回值类型的全限定名),然后交给Spring容器,能够动态获取一个Bean对象

属性的注入

@Autowired、@Resource:@Resource注解和@Autowired注解作用于属性,等价于<property ></property>。 在接口只有一个实现类的时候,两个注解可以互相替换,效果相同。@Resource注解是Java自身的注解,@Autowired注解是Spring的注解所以一般使用@Autowired

@Resource注解默认按照名称进行匹配,@Resource注解有两个重要的属性,分别是name和type,name有值则按byName自动注入,type有值按byType自动注入。

@Autowired注解只根据type进行注入,不会去匹配name。如果只根据type无法辨别注入对象时,就需要配合使用@Qualifier注解或者@Primary使用。

@Qualifier:指定按照名称去装配 bean,和@Autowired一起

@Primary:存在多个类型的实例时,哪个主要就标记哪个,标记在@Autowired要实现的bean上
 

AOP

不改变原有代码的情况下实现代码功能的增强。通过代理类为原始类增加额外的功能,代理类最终执行的是被代理类的方法。底层是用代理模式实现AOP,springAOP实现有三种方式。

切面 = 切入点表达式(四种,常用execution和注解) + 通知方法

切入点表达式:如果目标对象满足切入点表达式的判断,则spring自动为其创建代理对象

步骤:

1.导入依赖

<!--支持切入点表达式-->
 <dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.19</version>
</dependency>

<!--支持aop相关注解-->
<dependency>
   <groupId>org.aspectj</groupId>
   <artifactId>aspectjrt</artifactId>
   <version> 1.9.19 </version>
</dependency>

织入点语法

Aspectj织入点语法:

 

execution(public * *(..))

任何类的任何返回值的任何方法

execution(* set*(..))

任何类的set开头的方法

execution(* com.xyz.service.AccountService.*(..))

任何返回值的规定类里面的方法

execution(* com.xyz.service..*.*(..)) 

任何返回值,规定包或规定包子包的任何类任何方法

execution(* com.xyz.service.*.*(..)) 任何返回值,规定包的任何类任何方法

通知(advice)

  • Before advice(前置通知@Before):连接点前面执行,不能终止后续流程,除非抛异常
  • After returning advice(后置通知@AfterReturning):连接点正常返回时执行,有异常不执行
  • Around advice(环绕通知@Around):围绕连接点前后执行,也能捕获异常处理
  • After advice(最终通知@After):连接点退出时执行,无论是正常退出还是异常退出
  • After throwing advice(异常通知@AfterThrowing):连接点方法抛出异常时执行

实现接口

创建实现类实现 MethodBeforeAdvice/AfterReturningAdvice/MethodInterceptor/ThrowsAdvice 这四个接口,并实现方法。

注意:在异常接口实现类中不会提示重写的方法,但必须按照格式编写

//(中括号表示里面的参数要不全都存在,不要全都不存在),方法名、修饰符也不能改
public void afterThrowing([Method, args, target], ThrowableSubclass){}
    <!--spring配置类的bean-->
    <bean id="beforeAdvice" class="com.xk.aop01.BeforeAdvice"/>
    <bean id="afterAdvice" class="com.xk.aop01.AfterAdvice"/>
    <bean id="aroundAdvice" class="com.xk.aop01.AroundAdvice"/>
    <bean id="exceptionAdvice" class="com.xk.aop01.ExceptionAdvice"/>
    <!--aop配置-->
    <aop:config>
          <!--切点配置-->
        <aop:pointcut id="pointCut" expression="execution(* com.xk.dao.impl.*.*(..))"/>
        <!--通知配置-->
        <aop:advisor advice-ref="beforeAdvice" pointcut-ref="pointCut"/>
        <aop:advisor advice-ref="afterAdvice" pointcut-ref="pointCut"/>
        <aop:advisor advice-ref="aroundAdvice" pointcut-ref="pointCut"/>
        <aop:advisor advice-ref="exceptionAdvice" pointcut-ref="pointCut"/>
    </aop:config>-->

定义切面

步骤:

1.在一个类里定义切面方法 2.beans.xml配置 

   <bean id="aspectTest" class="com.xx.aop02.AspectTest"/>
    <!--aop配置-->
    <aop:config>
       <!--切面配置-->
        <aop:aspect ref="aspectTest">
          <!--切点配置-->
            <aop:pointcut id="pointCut2" expression="execution(* com.xx.dao.impl.*.*(..))"/>
            <!--通知(增强)配置,参数JoinPoint/ProceedingJoinPoint(around专属的)-->
            <aop:before method="before" pointcut-ref="pointCut2"/>
             <!--有额外参数的,无额外参数的用<aop:after>-->
            <aop:after-returning  method="after" pointcut-ref="pointCut2" returning="o"/>
            <aop:around method="around" pointcut-ref="pointCut2"/>
            <!--异常通知配置-->
            <aop:after-throwing method="exception" pointcut-ref="pointCut2" throwing="e"/>
        </aop:aspect>
    </aop:config>

参考代码:

@Component
@Aspect
public class AspectTest02 {
    @Pointcut("execution(* com.xx.dao.impl.*.*(..))")
    public void aopTest() {

    }
    @Around("execution(* com.xx.dao.impl.*.*(..))")
    public Object around(ProceedingJoinPoint pj) {
        System.out.println(pj.getClass().getName()+"执行前");
        Object o;
        try {
           o=pj.proceed();
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
        System.out.println(pj.getClass().getName()+"执行后");
        return o;
    }

    @Before("execution(* com.xx.dao.impl.*.*(..))")
    public void before(JoinPoint p) {
        System.out.println(p.getSignature().getName());
    }

    @AfterReturning(value = "execution(* com.xx.dao.impl.*.*(..))",returning = "o")
    public void after(JoinPoint p,Object o) {
        System.out.println(p.getSignature().getName()+o);
    }

    @AfterThrowing(value = "execution(* com.xx.dao.impl.*.*(..))",throwing = "e")
    public void exception(JoinPoint jp,Exception e) {
        System.out.println(jp);
    }

注解方式

xml配置:<!--开启aspectj自动代理--><aop:aspectj-autoproxy/>

1.在一个类里定义切面方法 2.在类上添加@Component(注册bean)@Aspect(定义aop类) 3.在方法上添加@Around/@Before/@AfterReturning(无参用@After)/@AfterThrowing,值和xml里一致

 //四个aop注解及其传值
  @Around("execution(* com.xk.dao.impl.*.*(..))")
  @Before("execution(* com.xk.dao.impl.*.*(..))")
  @AfterReturning(value = "execution(* com.xk.dao.impl.*.*(..))",returning = "o")
  @AfterThrowing(value = "execution(* com.xk.dao.impl.*.*(..))",throwing = "e")

整合mybatis

整合部分集中在配置文件中,其他部分基本不变

1.导入相关依赖

        <!-- spring依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.20</version>
        </dependency>
        <!--aspects 切面-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>5.3.20</version>
        </dependency>
        <!--支持切入点表达式-->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.19</version>
        </dependency>
        <!--支持aop相关注解-->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version> 1.9.19 </version>
        </dependency>
        <!--使用Spring Test后,只需要通过注解指定Spring配置类-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.3.20</version>
            <scope>test</scope>
        </dependency>

        <!-- Junit测试 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>

        <!--Log4J日志工具  打印运行日志用的!-->
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.16.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.16.0</version>
        </dependency>
        <!-- mysql驱动包 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.26</version>
        </dependency>
        <!--jdbc-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.3.20</version>
        </dependency>
        <!-- mysql驱动包 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.26</version>
        </dependency>
        <!--druid-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.10</version>
        </dependency>

        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.13</version>
        </dependency>
        <!--mybatis&spring 整合包-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.1.1</version>
        </dependency>

        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
        </dependency>

        <!--mybatis分页插件-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>5.2.1</version>
        </dependency>

2.编写配置文件(ApplicationContext.xml、mybatis-config.xml、db.properties、log4j.properties等)

   <!--引入外部的数据源配置文件-->
    <context:property-placeholder location="classpath:db.properties"/>
    <!--配置druid数据库连接池-->
    <bean id="druid" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${driver}"/>
        <property name="url" value="${url}"/>
        <property name="username" value="${name}"/>
        <property name="password" value="${password}"/>
    </bean>
   <!--sqlSessionFactory-->
    <bean id="ssf" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 配置数据源-->
        <property name="dataSource" ref="druid"/>
        <!-- 注入mybatis的核心配置文件-->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <!--mapper映射文件-->
        <property name="mapperLocations" value="classpath:mapper/*.xml"/>
    </bean>
    <!--扫描所有的接口-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!--扫描所有的接口,生成代理对象,注入spring容器-->
        <property name="basePackage" value="com.xk.dao"/>
    </bean>

主要改动:ApplicationContext.xml

因为整合了druid,db.properties里不能写username;没有整合druid,db.properties里不能写name(这里可能会被识别成微软账户名,最好写复杂点,例如:db.name)

3.分层编写相关业务、功能java类和mapper.xml

dao层:dao接口和mapper.xml文件、entity:实体类、service:接口和实现类。通过controller层或Test类调用实现功能

插件mybatisX

spring事务

事务在逻辑上是一组操作,要么执行,要不都不执行。事务满足ACID特点

步骤

1.xml配置

   <!-- 约束-->
   xmlns:tx="http://www.springframework.org/schema/tx
   http://www.springframework.org/schema/tx
   http://www.springframework.org/schema/tx/spring-tx.xsd
<!--    注入事务管理器-->
  <bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
      <property name="dataSource" ref="druid"/>
  </bean>
    
<!--配置事务通知-->
<tx:advice id="tx" transaction-manager="dataSourceTransactionManager">
    <tx:attributes>
    <!--筛选方法名前缀为save/delete的-->
        <tx:method name=“save*"/>
        <tx:method name=“delete*"/>
    </tx:attributes>
</tx:advice>

<!--配置事务的aop-->
    <aop:config>
        <aop:pointcut id=“servicePoint” expression=“execution(* org.kgc.spring.service.imp.*.*(..))"/>
        <aop:advisor advice-ref="tx" pointcut-ref="servicePoint"/>
    </aop:config>

2.使用注解

<!--    开启事务注解支持--> 
<tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>

@Transactional(propagation=Propagation.REQUIRED,rollbackFor=Exception.class)

捕获异常也可提交事务

传播特性

传播级别定义的是事务的控制范围

传播机制说明
PROPAGATION_REQUIRED如果当前没有事务就新建事务,已存在事务就加入到这个事务(常见)
PROPAGATION_SUPPORTS支持当前事务,当前没有事务则以非事务方式执行
PROPAGATION_MANDATORY使用当前事务,当前没有事务则抛出异常
PROPAGATION_REQUIRED_NEW新建事务,若当前存在事务就把当前事务挂起
PROPAGATION_NOT_SUPPORTED以非事务方式执行,若当前存在事务就把当前事务挂起
PROPAGATION_NEVER以非事务方式执行,若当前存在事务则抛出异常
PROPAGATION_NESTED若存在事务则嵌套事务执行,若没有事务则新建事务

隔离级别

事务隔离级别定义的是事务在数据库读写方面的控制范围。事务隔离级别是对事务 4 大特性中隔离性的具体体现,使用事务隔离级别可以控制并发事务在同时执行时的某种行为。

Spring 中的事务隔离级别比 MySQL 中的事务隔离级别多了一种,它包含的 5 种隔离级别分别是:

  • Isolation.DEFAULT:默认的事务隔离级别,以连接的数据库的事务隔离级别为准。
  • Isolation.READ_UNCOMMITTED:读未提交,可以读取到未提交的事务,存在脏读。
  • Isolation.READ_COMMITTED:读已提交,只能读取到已经提交的事务,解决了脏读,存在不可重复读。
  • Isolation.REPEATABLE_READ:可重复读,解决了不可重复读,但存在幻读(MySQL 数据库默认的事务隔离级别)。
  • Isolation.SERIALIZABLE:串行化,可以解决所有并发问题,但性能太低。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值