Spring

Spring是一个轻量级的控制反转(IOC)和面向切面(AOP)的容器

Spring组成

 Spring框架是一个分层架构,由七个模块组成。构建在核心容器上(Spring Core),核心容器定义了创建,配置和管理Bean的方式。

每个模块的功能如下:

  • 核心容器(Spring Core):主要组件是BeanFactory。定义了创建,配置和管理Bean的方式
  • Spring上下文(Spring Context):Spring Context是一个配置文件,向Spring框架提供上下文信息
  • Spring AOP:通过配置管理特性,Spring AOP将面向切面编程的功能集成到Spring框架中
  • Spring DAO:面向JDBC的数据库访问接口
  • Spring ORM:插入多个框架来提供ORM对象关系映射工具,包括JDO,Hibernate,iBatis
  • Spring WEB:为Web应用提供上下文
  • Spring MVC:提供构建Web应用的MVC实现

IOC本质

控制反转(Inversion Of Control)IOC是一种设计思想,依赖注入(Dependency Injection)DI是一种方法 

程序创建对象==>容器创建对象

Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建并组织对象存入IOC容器中,当程序需要使用对象时从容器中取出对象即可

Spring程序

导入jar包

<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.5</version>
</dependency>

编写实体类

public class Hello {
    private String name;
    public Hello(){
        System.out.println("调用无参构造");
    }
    public String getName(){
        return name;
    }
    public void setName(String name){
        this.name=name;
    }
    public void show(){
        System.out.println("Hello,"+name);
    }
}

编写bean配置文件

<?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="hello" class="com.deng.Entity.Hello">
        <property name="name" value="Spring"></property>
    </bean>
</beans>

测试

public void test1(){
       //解析beans.xml配置文件,生成管理bean的对象
        ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");
        //根据bean的id获取bean对象
        Hello hello=(Hello)context.getBean("hello");
        hello.show();
}    

依赖注入

  • 依赖:Bean对象的创建依赖于容器
  • 注入:Bean对象所依赖的资源由容器来设置和装配

构造器注入

<bean id="hello" class="com.deng.Entity.Hello">
<!-- name指参数名 -->
<constructor-arg name="name" value="Spring"/>
</bean>

常量注入

要求被注入的属性必须由set方法才能注入

<bean id="hello" class="com.deng.Entity.Hello">
        <property name="name" value="Spring"></property>
</bean>

Bean注入

   <bean id="address" class="com.deng.Entity.Address">
        <property name="address" value="zhejianghangzhou"></property>
    </bean>
    <bean id="hello" class="com.deng.Entity.Hello">
        <property name="name" value="Spring"></property>
        <property name="address" ref="address"></property>
    </bean>

数组注入

<property name="books">
        <array>
                <value>西游记</value>
                <value>红楼梦</value>
                <value>水浒传</value>
        </array>
</property>

List注入

<property name="hobbys">
     <list>
         <value>西游记</value>
         <value>红楼梦</value>
         <value>水浒传</value>
     </list>
</property>

Map注入

<property name="card">
     <map>
         <entry key="中国邮政" value="456456456465456"/>
         <entry key="建设" value="1456682255511"/>
     </map>
</property>

Set注入

<property name="games">
   <set>
       <value>LOL</value>
       <value>BOB</value>
       <value>COC</value>
   </set>
</property>

null注入

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

properties注入

<property name="info">
   <props>
          <prop key="学号">20190604</prop>
          <prop key="性别"></prop>
          <prop key="姓名">小明</prop>
   </props>
</property>

命名空间注入

p命名空间注入

需要在头文件导入约束文件

<beans xmlns:p="http://www.springframework.org/schema/p">
       <bean id="hello" class="com.deng.Entity.Hello" p:name="dwx"></bean>
</beans>

c命名空间注入

需要在头文件导入约束文件,且必须要有有参构造函数才能使用

<beans xmlns:c="http://www.springframework.org/schema/c">
       <bean id="hello" class="com.deng.Entity.Hello" c:name="dwx"></bean>
</beans>

Bean的作用域

Bean就是IOC容器初始化,装配和管理的对象,有4种作用域:

singleton

bean的作用域为singleton时,IOC容器中只会存在一个共享的Bean实例,对于所有的bean请求,id与该bean相同就会返回同一实例。

在创建容器时就自动创建了一个bean对象,无论是否使用都存在。

singleton是bean的默认作用域,xml中定义如下

<bean id="hello" class="com.deng.Entity.Hello" scope="singleton"></bean>

prototype

prototype作用域的bean会导致每次对该bean对象请求(将该bean注入到另一个bean中,或者调用getBean()方法)时都会创建一个新的实例。在创建容器时,bean并没有实例化,而是在需要获取bean对象时才会去创建一个对象,并且每次获取的对象都不是同一对象。在xml中的定义如下

request

当bean的作用域为request时,表示每一个http请求都会有各自的bean实例,仅在基于web的SpringApplicationContext里有效。当处理请求结束后,request的作用域的bean实例将被销毁,在xml的定义如下

<bean id="hello" class="com.deng.Entity.Hello" scope="request"></bean>

session

bean的作用域为session,表示一个Http Session对应一个bean实例,仅在基于web的SpringApplicationContext里有效。Http Session结束后,bean也会被销毁

Bean的自动装配

Spring会在应用上下文中为某个bean寻找其依赖的bean

bean的三种装配机制:

  • 在xml中显式的配置
  • 在java中显式的配置
  • 自动装配bean

实现自动装配的两个操作:

  • 组件扫描(component scanning):Spring会自动发现应用上下文中创建的bean
  • 自动装配(autowiring):Spring自动满足bean之间的依赖,依赖注入

在xml中配置注入

手动配置xml

3个实体类

//
public class Cat {
    public void shout(){
        System.out.println("miaomiaomiao!!!");
    }
}
//
public class Dog {
    public void shout(){
        System.out.println("wangwangwang!!!");
    }
}
//
@Data
public class User {
    private Cat cat;
    private  Dog dog;
    private String name;
}

编写配置文件

<?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="cat" class="com.deng.Entity.Cat"></bean>
    <bean id="dog" class="com.deng.Entity.Dog"></bean>
    <bean id="user" class="com.deng.Entity.User">
        <property name="cat" ref="cat"></property>
        <property name="dog" ref="dog"></property>
        <property name="name" value="dwx"></property>
    </bean>
</beans>

按名称自动配置xml

修改bean的参数配置,增加属性autowired="byName"

<bean id="cat" class="com.deng.Entity.Cat"></bean>
<bean id="dog" class="com.deng.Entity.Dog"></bean>
<bean id="user" class="com.deng.Entity.User" autowire="byName">
      <property name="name" value="dwx"></property>
</bean>

使用autowired byName属性时步骤:

  • 查找该类中的所有set方法,去掉set,获取set去掉并且首字母小写的字符串,作为匹配对象
  • 去spring容器查找有没有id与此字符串匹配的bean对象
  • 如果有就注入,没有就抛出空指针异常

按类型自动配置xml

使用autowire byType要确保同一类型的对象在Spring容器中唯一,如果不唯一就会抛出异常

<bean id="cat985" class="com.deng.Entity.Cat"></bean>
<bean id="dog211" class="com.deng.Entity.Dog"></bean>
<bean id="user" class="com.deng.Entity.User" autowire="byType">
      <property name="name" value="dwx"></property>
</bean>

使用注解注入

首先要在xml文件中引入context头文件

xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd

然后开启属性注解的支持

<context:annotation-config></context:annotation-config>

@Autowired

  • Autowired默认是按类型(byType)自动装配的
  • 使用它需要导入spring-aop包
public class User {
    @Autowired
    private Cat Cat;
    @Autowired
    private  Dog dog;
    private String name;
}

不需要set方法也可

@Autowired(required=false)//表示允许对象为null

@Qualifier

  • 与@Autowired一起使用,表示按照名称(byName)的方式进行自动装配
  • 不能单独使用
public class User {
    @Autowired
    @Qualifier(value = "cat")
    private Cat Cat;
    @Autowired
    private  Dog dog;
    private String name;
}

@Resource

  • 如果指定name属性,按照该属性进行查找装配
  • 如果没有指定name属性,按照默认的byName方式装配
  • 如果byName装配不成功就按byType的方式装配
  • 如果都不成功就抛出异常
@Data
public class User {
    @Resource(name = "cat")
    private Cat cat;
    @Autowired
    private  Dog dog;
    private String name;
}

@AutoWired与@Resource区别

  • @Autowired默认按照类型装配,由Spring提供,如果想要按名称装配,可以结合@Qulifier使用
  • @Resource默认按照名称装配,由J2EE提供,名称可以通过name指定。如没有指定,按字段属性名来装配,当找不到与名称匹配的bean时就按照类型进行匹配。一旦指定了name就只会按照name来进行匹配和装配。
  • 两者都可以写在字段或set方法上。写在字段上,就按照字段名来装配查找。如果写在set方法上,就按属性名(去掉set,并将首字母小写)来装配查找(不区分首字母大小写)。如果两者都写在字段上,就不需要set方法

使用注解开发

导入spring-aop注解,并在配置文件中引入context约束

使用

在配置文件配置扫描哪些表下的注解

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
">
    <context:component-scan base-package="com.deng.Entity"></context:component-scan>
</beans>

在该包下的类增加注解@Component

@Component("user")
public class User {
    public String name="dwx";
}

测试

 public void test1() {
        ApplicationContext context=new ClassPathXmlApplicationContext("beans1.xml");
        User user=(User) context.getBean("user");
        System.out.println(user.name);
    }

属性注入

  • 直接在字符名添加@Value("值")
@Component("user")
// 相当于配置文件中,
<bean id="user" class="com.deng.Entity.User"/>
public class User {
@Value("dwx")
//相当于配置文件中<property name="
name" value="dwx">
public String name;
}
  • 在set方法上添加@Value("值")
@Component
public class User {
    public String name;
    @Value("dwx")
    public void setName(String name) {
        this.name = name;
    }
}

衍生注解

  • @Controller:web层
  • @Service:service层
  • @Repository:dao层

这些注解都是表示将对应的类交给spring管理

@Scope()作用域

  • siingleton:默认的,单例模型,关闭工厂所有对象都会销毁
  • prototype:多例模型,关闭工厂,对象不会销毁,而是等待垃圾回收器回收
@Component
@Scope("prototype")
public class User {
    public String name;
    @Value("dwx")
    public void setName(String name) {
        this.name = name;
    }
}

基于Java类进行配置

使用

实体类

@Data
public class Cat {
    private String name;
}

编写Config配置类

@Configuration//表示这是一个配置类
public class MyConfig {
    @Bean//通过该方法注册一个bean,bean类型就是返回值,id就是方法名
    public Cat cat(){
        Cat cat=new Cat();
        //注入值
        cat.setName("jiafeimao");
        return cat;
    }
}

测试

public void test1() {
        //根据配置类创建applicationContext来管理bean对象
        ApplicationContext context=new AnnotationConfigApplicationContext(MyConfig.class);
        //获取bean对象
        Cat cat=(Cat)context.getBean("cat");
        System.out.println(cat.getName());
}

导入其他配置类使用

@Import(MyConfig2.class)

代理模式 

代理就是在不改变原来的代码的情况下,对原有的功能进行增强

静态代理:

代理一个角色

//抽象角色:租房
public interface Rent {
    public void rent();
}
//中介
public class StaticProxy {
    private Host host;
    public StaticProxy(Host host){
        this.host=host;
    }
    //租房
    public void rent(){
        seeHouse();
        host.rent();
        fare();
    }
    //看房
    public void seeHouse(){
        System.out.println("看看房子");
    }
    //收中介费
    public void fare(){
        System.out.println("收取中介费");
    }
}
//客户端
public class Client {
    public static void main(String[] args) {
        Host host=new Host();
        StaticProxy staticProxy=new StaticProxy(host);
        staticProxy.rent();
    }
}

动态代理:

代理一类角色,动态代理的代理类是动态生成的,静态代理的代理类是提前写好的,需要了解接口InvocationHandler和类Proxy

InvocationHandler里的invoke()方法:调用处理程序

Proxy里的静态方法newProxyInstance()方法:创建代理实例

public class DtProxy implements InvocationHandler {
    private Rent rent;
    public void setRent(Rent rent){
        this.rent=rent;
    }
    //生成代理类,第二个参数
    public  Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),rent.getClass().getInterfaces(),this);
    }
    //处理代理实例上的方法并将结果返回
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        seeHouse();
        Object result=method.invoke(rent,args);
        fare();
        return result;
    }
    //看房
    public void seeHouse(){
        System.out.println("带房客看房");
    }
    //收中介费
    public void fare(){
        System.out.println("收中介费");
    }
}
//客户端
public class Client {
    public static void main(String[] args) { 
        Host host=new Host();
        DtProxy dtProxy=new DtProxy();
        dtProxy.setRent(host);
        Rent proxy=(Rent)dtProxy.getProxy();
        proxy.rent();
    }
}

AOP

使用AOP织入要导入依赖包

<dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.6</version>
</dependency>

AOP术语通俗解释

  • 通知(Adivce):想加入的功能,如日志,安全等
  • 连接点(JoinPoint):spring允许添加功能的地方
  • 切入点(PointCut):要添加功能的方法
  • 切面(Aspect):通知和切入点的结合,干什么,什么时候干,在哪儿干
  • 目标(Target):被通知的对象
  • 代理(Proxy):给目标对象应用通知后创建的对象
  • 织入(Weaving):将切面和目标对象连接起来,并创建代理对象的过程

通过xml配置的方式实现AOP,

通过Spring的API来实现

public class UserServiceImpl implements UserService{
    public void add() {
        System.out.println("增加用户");
    }
    public void delete() {
        System.out.println("删除用户");
    }
    public void update() {
        System.out.println("更新用户");
    }
    public void search() {
        System.out.println("查询用户");
    }
}

写增强类实现Spring的API

public class Log implements MethodBeforeAdvice {
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println(o.getClass().getName() + "的" + method.getName()
                + "方法被执行了");
    }
}
public class AfterLog implements AfterReturningAdvice {
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println("执行了" + o1.getClass().getName()
                +"的"+method.getName()+"方法,"
                +"返回值:"+o);
    }
}

最后在spring的配置文件中注册并实现aop切入

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
    <bean id="userService" class="com.deng.Service.UserServiceImpl"></bean>
    <bean id="log" class="com.deng.Entity.Log"></bean>
    <bean id="afterLog" class="com.deng.Entity.AfterLog"></bean>
    <aop:config>
        <!--切入点 expression:表达式匹配要执行的方法-->
        <aop:pointcut id="pointcut" expression="execution(*
com.deng.Service.UserServiceImpl.*(..))"/>
        <!--执行环绕; advice-ref执行方法 . pointcut-ref切入点-->
        <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
    </aop:config>
</beans>

自定义方法来实现aop

自定义切入类

public class DiyPointCut {
    public void before(){
        System.out.println("---------方法执行前---------");
    }
    public void after(){
        System.out.println("---------方法执行后---------");
    }
}

在Spring中配置

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
    <bean id="userService" class="com.deng.Service.UserServiceImpl"></bean>
    <bean id="log" class="com.deng.Entity.Log"></bean>
    <bean id="afterLog" class="com.deng.Entity.AfterLog"></bean>
    <bean id="diy" class="com.deng.Entity.DiyPointCut"></bean>
    <aop:config>
        <aop:aspect ref="diy">
            <aop:pointcut id="pointcut" expression="execution(*
com.deng.Service.UserServiceImpl.*(..))"></aop:pointcut>
            <aop:before pointcut-ref="pointcut" method="before"></aop:before>
            <aop:after pointcut-ref="pointcut" method="after"></aop:after>
        </aop:aspect>
    </aop:config>
</beans>

注解方式实现

@Aspect
public class DiyPointCut {
    @Before("execution(* com.deng.Service.UserServiceImpl.*(..))")
    public void before(){
        System.out.println("---------方法执行前---------");
    }
    @After("execution(* com.deng.Service.UserServiceImpl.*(..))")
    public void after(){
        System.out.println("---------方法执行后---------");
    }
}

xml配置

<bean id="userService" class="com.deng.Service.UserServiceImpl"></bean>
<bean id="diy" class="com.deng.Entity.DiyPointCut"></bean>
<aop:aspectj-autoproxy/>

Mybatis整合

mybatis-spring

导入依赖

<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.22</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.2</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
</dependencies>

在Mybatis中是通过SqlSessionFactoryBuilder来创建SqlSessionFactory的,而在MyBatis-Spring中是使用SqlSessionFactoryBean来创建的;

然后使用SqlSessionFactory来获取SqlSession,用他来执行映射语句。SqlSessionFactory有一个唯一的必要属性:用于JDBC的数据源DataSource。

SqlSessionTemplate是Myabtis-Spring的核心,是SqlSession的一个实现

可以使用SqlSessionFactory作为构造方法的参数来创建SqlSessionTemplate对象

整合实现

方式一:通过SqlSessionTemplate实现

beans.xml配置文件

sqlSessionFactory的属性configLocation和mapperLocation指定了mybatis和mapper的xml配置文件路径

<?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="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/mybatis?
useSSL=true&amp;useUnicode=true&amp;characterEncoding=utf8&amp;serverTimezone=UTC"></property>
        <property name="username" value="root"></property>
        <property name="password" value="13476110270dwx"></property>
    </bean>
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <!--关联Mybatis-->
        <property name="configLocation" value="classpath:mybatis-config.xml"></property>
        <property name="mapperLocations" value="classpath:com/deng/dao/*.xml"></property>
    </bean>
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg index="0" ref="sqlSessionFactory"></constructor-arg>
    </bean>
    <bean id="userDao" class="com.deng.dao.UserMapperImpl">
        <property name="sqlSession" ref="sqlSession"></property>
    </bean>
</beans>

增加接口实现类

public class UserMapperImpl implements UserMapper{
    private SqlSessionTemplate sqlSession;

    public SqlSessionTemplate getSqlSession() {
        return sqlSession;
    }
    public void setSqlSession(SqlSessionTemplate sqlSession) {
        this.sqlSession = sqlSession;
    }
    public User getUser(int id) {
        UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
        return userMapper.getUser(id);
    }
}

测试

public void test1(){
        ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");
        UserMapper userMapper=(UserMapper)context.getBean("userDao");
        User user=userMapper.getUser(1);
        System.out.println(user);
}

mybatis-config.xml中的配置文件并没有配置环境信息,SqlSessionFactoryBean会创建只有的mybatis环境

方式二:通过继承SqlSessionDaoSupport类实现

修改实现类

public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper{
    public User getUser(int id){
        UserMapper userMapper=(UserMapper)getSqlSession().getMapper(UserMapper.class);
        return userMapper.getUser(id);
     }
}

修改bean配置

<bean id="userDao2" class="com.deng.dao.UserMapperImpl2">
        <property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
</bean>

测试

   public void test1(){
        ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");
        UserMapper userMapper=(UserMapper)context.getBean("userDao2");
        User user=userMapper.getUser(1);
        System.out.println(user);
    }

声明式事务

编程式事务:将事务管理代码嵌入到业务方法中

声明式事务:将事务管理代码与业务方法分离,以声明的方式管理事务。通过Spring AOP框架支持声明式事务管理

在spring配置文件中,导入头文件tx

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="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
 </bean>

配置事务通知

<!--配置事务通知-->
    <tx:advice id="txAdivce" transaction-manager="transactionManager">
        <tx:attributes>
            <!--配置哪些方法需要使用什么的事务,配置事务的传播特性-->
            <tx:method name="gerUser" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>

事务的传播特性就是多个事务方法相互调用时,事务是如何在这些方法间传播的,Spring支持7种事务传播行为

  • propagation_required:当前没有事务就新建一个事务,如果已存在一个事务,就加入到该事务中
  • propagation_supports:支持当前事务,如果没有事务,就以非事务的方式执行
  • propagation_mandatory:使用当前事务,如果没有事务,抛出异常
  • propagation_required_new:新建事务,如果当前存在事务,将当前事务挂起
  • propagation_not_supported:以非事务的方式执行操作,如果当前存在事务把当前事务挂起
  • propagation_never:以非事务的方式执行操作,如果当前事务存在,抛出异常
  • propagation_nested:如果当前存在事务,则嵌套的事务内执行,如果当前没有事务,则执行与 propagation_required类似的操作

spring默认的事务传播行为是propagation_required

织入事务

<!--配置aop织入事务-->
<aop:config>
        <aop:pointcut id="txPointcut" expression="execution(* com.deng.dao.*.*
         (..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
</aop:config>
原文地址:https://www.cnblogs.com/dwx-study/p/14716807.html