spring全面详解,狂神说学习笔记。

关注公众号乐享Coding微信获取PDF版资源,计算机网络图解等更多资源,也可联系我加入学习交流群

Spring 框架两大核心机制(IoC、AOP)

  • IoC(控制反转)/ DI(依赖注入)
  • AOP(面向切面编程)

Spring 是一个企业级开发框架,是软件设计层面的框架,优势在于可以将应用程序进行分层,开发者可以自主选择组件。

MVC:Struts2、Spring MVC

ORMapping:Hibernate、MyBatis、Spring Data

Spring管理Bean

  1. 创建对象(反射)
  2. 依赖注入(属性赋值)set方法或有参构造器

IOC的初步使用

  • 创建maven工程,导入jar包依赖。

    <dependencies>
        <!--spring上下文,保存信息-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.8.RELEASE</version>
        </dependency>
        <!--lombok简化开发-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.16</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
    
  • 创建实体类Student

    @Data
    public class Student {
        private int id;
        private String name;
        private int age;
    }
    
  • 通过 IOC 创建对象,在配置文件中添加需要管理的对象,XML 格式的配置文件,文件名可以自定义。

    • Resource文件夹下创建application.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-3.2.xsd
      ">
      
      <!--配置Student实例对象属性-->
      <bean id="student" class="com.Long.Entity.Student">
          <property name="id" value="1"/>
          <property name="name" value="张三"/>
          <property name="age" value="22"/>
      </bean>
      
  • 从 IoC 容器中获取对象,通过 id 获取。

    public class Main {
    public static void main(String[] args) {
    // 从 IoC 中获取对象,通过 id 获取,加载配置文件
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    Student student = (Student) applicationContext.getBean("student");
    System.out.println(student);
    }
    }
    //打印 Student(id=1, name=张三, age=22)
    

IOC思想

(1)控制反转,把对象创建和对象之间的调用过程,交给Spring来处理

(2)目的:为了耦合度降低

(3)IOC 底层原理 (singleton下)

  • 读取XML配置文件,解析 XML。

  • 运用反射机制实例化配置文件中配置所有的 bean(DI)。

(4)设计模式:工厂模式解耦

  • IOC容器底层就是对象工厂(两个接口)

    1. BeanFactory:IOC容器基本实现,是Spring内部的使用接口,不提供开发人员使用。加载配置文件时不会创建对象,在获取对象才去创建对象。

    2. ApplicationContext:BeanFactory接口的子接口,提供更多更强大的功能,一般由开发人员使用。加载配置文件时就会在配置文件对象进行创建。

      实现类

依赖注入(赋值)

XML配置文件方式
无参构造器注入属性值
  • 通过配置 <bean> 标签来完成对象的管理。

    • id:对象名。

    • class:对象的模版类(所有交给 IoC 容器来管理的类必须有无参构造函数,因为 Spring 底层是通过反射机制来创建对象,调用的是无参构造)

  • 对象的成员变量通过 <property> 标签完成赋值。

    • name:成员变量名。
    • value:成员变量值(基本数据类型,String 可以直接赋值,如果是其他引用类型,不能通过 value 赋值)
    • ref:将 IoC 中的另外一个 bean 赋给当前的成员变量(DI)
    <bean id="student" class="com.Long.Entity.Student">
        <property name="id" value="1"/>
        <property name="name" value="张三"/>
        <property name="age" value="22"/>
        <property name="address" ref="address"/>
    </bean>
    <bean id="address" class="com.Long.Entity.Address">
        <property name="value" value="范阳路"/>
    </bean>`
    

简化无参构造器配置文件依赖注入(赋值)

p命名空间
xmlns:p="http://www.springframework.org/schema/p"
<bean id="student" class="com.Long.Entity.Student" p:id="1" p:age="22" p:name="张三" p:address-ref="address">
<!--        <property name="id" value="1"/>-->
<!--        <property name="name" value="张三"/>-->
<!--        <property name="age" value="22"/>-->
</bean>
<bean id="address" class="com.Long.Entity.Address" p:value="范阳路">
<!--        <property name="value" value="范阳路"/>-->
</bean>

上述配置无参构造器实现对象的属性值注入底层是调用set方法实现注入的,也可通过有参构造器注入属性值

注意实体类中添加有参构构造器后一定要再写一个无参构造器

有参构造注入属性值
<bean id="student" class="com.Long.Entity.Student">
<constructor-arg index="0" value="1" />
<constructor-arg index="1" value="小肖" />
<constructor-arg index="2" value="18" />
<constructor-arg index="3" ref="address" />
</bean>
<bean id="address" class="com.Long.Entity.Address">
<property name="value" value="范阳路"/>
</bean>

简化有参构造器配置文件依赖注入(赋值)

c命名空间
xmlns:c="http://www.springframework.org/schema/c"
<bean id="student" class="com.Long.Entity.Student" c:id="1" c:age="22" c:name="张三" c:address-ref="address">
<!--        <constructor-arg name="id" value="1" />-->
<!--        <constructor-arg name="name" value="张三" />-->
<!--        <constructor-arg name="age" value="22" />-->
<!--        <constructor-arg name="address" ref="address" />-->
</bean>
<bean id="address" class="com.Long.Entity.Address" c:value="范阳路">
<!--        <constructor-arg name="value" value="范阳路" />-->
</bean>

扩展三种方式:

下标(index)

<constructor-arg index="0" value="小明"></constructor-arg>

类型(type)不建议使用 只能赋值一个参数

<constructor-arg type="java.lang.String" value="小明"></constructor-arg>

参数名(name)

<constructor-arg name="string" value="大雄"></constructor-arg>
通过运行时类获取 bean(创建bean对象)
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); // singleton下
Student student = (Student) applicationContext.getBean(Student.class);// prototype下
System.out.println(student);

这种方式存在一个问题,配置文件中一个数据类型的对象只能有一个实例,否则会抛出异常,因为没有唯一的 bean。

注解实现依赖注入

(1)【概念】代码的特殊标记

(2)【格式】@注解名称(属性名称=属性值,属性名称=属性值…)

(3)【范围】 方法上面,属性上面,类上面

(4)【目的】简化XML文件配置

创建对象

以下四个注解功能都是一样的,不同名字为了表达更清晰

@Component

  • 所有类都可以自动创建对象

@Service

  • 业务逻辑层

@Controller

  • 控制层

@Repository

  • Dao持久化数据层
具体使用
  1. 引入jar包依赖

    <!--springAop-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>5.2.8.RELEASE</version>
    </dependency>
    
  2. 配置文件中开启组件扫描

    <?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:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
    ">
    <!--开启组件扫描-->
    <context:component-scan base-package="com.Long"/>
    </beans>
    
  3. 类中添加注解

    //value属性默认值是首字母小写userService
    @Component(value = "UserService") // 等于xml中配置<bean id ="UserService",class=...>
    //只有value属性时也可以这样写@Component("UserService")
    public class UserService {
        public void is(){
            System.out.println("我是UserService!");
        }
    }
    
  4. 测试

    @Test
    public void Test() {
    // 从 IoC 中获取对象,通过 id 获取,加载配置文件
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    UserService UserService = (UserService) applicationContext.getBean("UserService");
    UserService.is();
    }
    
组件扫描优化,避免扫描多余组件
<!--开启组件扫描优化,避免扫描不必要组件-->
<context:component-scan base-package="com.Long" use-default-filters="false">
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
</context:component-scan>
属性注入
四个注解
注入对象属性,可以调用注入对象方法

@Autowired 根据属性类型进行自动装配

@Qualifier 与@Autowired一起使用,根据名称进行注入,解决Dao接口多个实现类,一般不需要。

@Resource 可以根据类型注入,也可根据名称注入@Resource(name=“{bean的名称}”)

注入普通类型属性,可以给当前对象属性赋值

@Value 注入普通类型(String,int,float…)属性

@Service
public class UserService {

    @Resource
    private UserService userService;

    @Autowired
//    @Qualifier("userDaoImpl")
    private userDao userDao;

    @Value("小红")
    private String name;

    public void is() {
        System.out.println("我是userService");
        userDao.add();//增加了一个用户
        System.out.println(userService.name); //小红
    }
}

完全注解开发(类似Springboot开发)

  • 新建Config配置类,添加类注解,脱离XML文件解析配置

    @Configuration //当前类作为配置类,替代xml配置文件
    @ComponentScan(basePackages = {"com.Long"}) //替代<context:component-scan base-package="com.Long">
    

  • 测试

    @Test
    public void test1(){
       ApplicationContext applicationContext= new AnnotationConfigApplicationContext(SpringConfig.class);
        UserService userService = applicationContext.getBean("userService", UserService.class);
        userService.is();
    }
    

scope 作用域

Spring 管理的 bean 是根据 scope 来生成的,表示 bean 的作用域,共4种,默认值是 singleton。

  • singleton:单例,表示通过 IOC 容器获取的 bean 是唯一的,解析配置文件时完成所有Bean创建**【默认】**
  • prototype:原型,表示通过 IOC 容器获取的 bean 是不同的,getBean()方法时创建对象。
  • request:请求,表示在一次 HTTP 请求内有效。
  • session:会话,表示在一个用户会话内有效。

request 和 session 只适用于 Web 项目,大多数情况下,使用单例和原型较多。

singletonprototype 创建对象的方式不同)Dubeg模式调试可见:

  • prototype 模式当业务代码获取 IoC 容器中的 bean 时,Spring 才去调用无参构造创建对应的 bean。

  • singleton 模式无论业务代码是否获取 IoC 容器中的 bean,Spring 在加载 applicationContext.xml 时就会创建 bean。

Spring 的继承

与 Java 的继承不同,Java 是类层面的继承,子类可以继承父类的内部结构信息;Spring 是对象层面的继承,子对象可以继承父对象的属性值。

<bean id="student" class="com.Long.Entity.Student">
<property name="id" value="1"/>
<property name="name" value="张三"/>
<property name="age" value="22"/>
<property name="addressList">
    <list>
        <ref bean="address"/>
        <ref bean="address2"/>
    </list>
</property>
</bean>

<bean id="address" class="com.Long.Entity.Address">
<property name="value" value="科技路"/>
</bean>

<bean id="address2" class="com.Long.Entity.Address">
<property name="value" value="范阳路"/>
</bean>

<bean id="stu" class="com.Long.Entity.Student" parent="student"> //继承了student的所有属性值
<property name="name" value="李四"/> //修改了name属性值
</bean>

Spring 的继承关注点在于具体的对象,而不在于类,即不同的两个类的实例化对象可以完成继承,前提是子对象必须包含父对象的所有属性,同时可以在此基础上添加其他的属性。

Spring 的依赖

与继承类似,依赖也是描述 bean 和 bean 之间的一种关系,配置依赖之后,被依赖的 bean 一定先创建,再创建依赖的 bean,student 依赖于 address,无论代码顺序怎样,一定先创建 address,再创建 student。

<bean id="student" class="com.Long.Entity.Student" depends-on="address"/>
<bean id="address" class="com.Long.Entity.Address"/>

bean的创建顺序不会从上到下,而是address一定比student对象先创建。

Bean的生命周期

从对象创建到对象销毁的过程

添加后置处理器有七步(可选),不添加为五步

(1)通过构造器创建bean实例(无参构造)

(2)为bean的属性设置值和对其他bean引用(调用set方法)

(3)把bean实例传递后置处理器的方法

(4)调用bean的初始化方法(需要进行配置初始化方法)

(5)把bean实例传递后置处理器的方法

(6)bean可以使用了(对象获取到了)

(7)当容器关闭时调用bean的销毁方法

  • bean对象
public class Student {
    private int id;
    private String name;
    private int age;

    private Address address;

    public void setId(int id) {
        this.id = id;
        System.out.println("第二步调用了Set方法");
    }

    public Student() {
        System.out.println("第一步执行了无参构造,创建Student对象");
    }

    public void initMethod(){
        System.out.println("第三步执行了初始化方法");
    }

    public void destroyMethod(){
        System.out.println("第五步执行了销毁方法");
    }
}
  • xml配置文件
<bean id="student" class="com.Long.Entity.Student" p:id="1" init-method="initMethod" destroy-method="destroyMethod"/>

<!--配置后置处理器-->
    <bean id="myBeanPost" class="com.Long.postBean.myPostbean"/>
  • 创建后置处理器类,实现BeanPostProcessor接口

  • 测试

@Test
public void Test() {
// 从 IoC 中获取对象,通过 id 获取,加载配置文件
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Student student = (Student) applicationContext.getBean("student");
System.out.println("第四步获取创建bean对象的实例");
System.out.println(student);
applicationContext.close();
}

AOP

通俗描述:不修改源代码,在主干功能里面添加新功能

底层原理
动态代理
  • 有接口情况,使用JDK动态代理

    创建接口实现类代理对象,增强类的方法

    使用JDK动态代理,使用Proxy类里面的newProxyInstance静态方法创建代理对象

    三个参数

    • 类加载器

    • 增强方法所在类,这个类实现的接口,支持多个接口

    • 实现接口InvocationHandler,创建对象,写增强逻辑

    通过JDK动态代理增强实现类的功能,【不改变源代码!!!】

    public class JDKproxy {
    
    public static void main(String[] args) {
        userDaoImpl userDao = new userDaoImpl();
        Class[] interfaces ={userDao.class};
        userDao Dao =(userDao) Proxy.newProxyInstance(JDKproxy.class.getClassLoader(), interfaces, new ProxyBean(userDao));
        int res = Dao.add(1, 2);
        System.out.println(res);
    }
    }
    class ProxyBean implements InvocationHandler {
    
    private Object obj;
    
    public ProxyBean(Object obj) {
        this.obj=obj;
    }
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //新增功能
        System.out.println(method.getName()+"新增了日志功能!参数为"+ Arrays.toString(args));
        Object res = method.invoke(obj,args);
        return res;
    }
    }
    
    public class userDaoImpl implements userDao {
    public int add(int a,int b) {
        return a+b;
    }
    
  • 没有接口情况,使用CGLIB动态代理

    创建子类的代理对象,增强类的方法

术语
  1. 连接点(可以被增强的方法)
  2. 切入点(已被实现的增强方法)
  3. 通知(增强方法的逻辑)
  4. 切面 (增强方法属于的类)

Spring框架一般都是基于AspectJ实现AOP操作

AspectJ
  • 不是Spring组成部分,独立AOP框架,一般把AspectJ和Spring框架一起使用执行AOP操作
基于注解使用

代理类

@Component
@Aspect //生成代理对象
@Order(1) //指定代理顺序,数字越低,优先级越高
public class userProxy {

    @Pointcut("execution(* com.Long.Dao.userDao.add(..))")
    public void Point(){
    }

    @Before("Point()") //前置通知
    public void before(){
        System.out.println("前置通知Before");
    }

    @After("Point()") //最终通知
    public void after(){
        System.out.println("最终通知After");
    }

    @AfterReturning("Point()") //后置通知
    public void afterReturning(){
        System.out.println("后置通知AfterReturning");
    }

    @Around("Point()")//环绕通知
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
        System.out.println("around环绕通知前");
        proceedingJoinPoint.proceed();
        System.out.println("around环绕通知后");
    }

    @AfterThrowing("Point()")
    public void AfterThrowing(){
        System.out.println("异常通知AfterThrowing");
    }
}

实现类

public class userDaoImpl implements userDao {
public void add(int id) {
    System.out.println("我是add方法,增加了"+id+"号用户");
}
}

测试

@Test
public void testAOP(){
ApplicationContext applicationContext= new ClassPathXmlApplicationContext("applicationContext.xml") ;
//动态代理的是接口,增强的是实现类bean方法
userDao userDao= (userDao) applicationContext.getBean("userDaoImpl");
userDao.add(2);
}

测试结果

//around环绕通知前
//前置通知Before
//我是add方法,增加了2号用户
//后置通知AfterReturning
//最终通知After
//around环绕通知后

JDBCtemplate

导入依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>

<!--针对事务相关操作依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>

<!--整合Mybatis等其他框架需要-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.22</version>
</dependency>

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
xml配置数据源
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name="url" value="jdbc:mysql://localhost:3306/bank?useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="77549252"/>
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
</bean>

<!--配置JdbcTemplate对象-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!--注入dataSource-->
<property name="dataSource" ref="dataSource"/>
简单使用
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public void addMoney(int money,String name) {
String sql ="update t_account set money=money+? where name =?";
jdbcTemplate.update(sql,money,name);
}

事务

事务是数据库操作的基本单元,逻辑上一组操作,要么都成功,要么都失败。

四个特性(ACID)
(1)原子性
(2)一致性
(3)隔离性
(4)持久性

事务添加到JavaEE三层结构里面Service层(业务逻辑层)

事务管理操作
  • 编程式事务
  • 声明式事务(Spring使用)
事务管理API

(1)提供一个PlatformTransactionManager接口,代表事务管理器,这个接口针对不同框架有不同实现类。

声明式事务管理(底层AOP)
(1)注解
  1. xml配置文件中配置事务管理器

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <!--注入dataSource-->
    <property name="dataSource" ref="dataSource"/>
    </bean>
    
  2. 在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
    
    <!--开启事务注解-->
    <tx:annotation-driven transaction-manager="transactionManager"/>
    
  3. 在Service类上面或类里面的方法添加事务注解

    • 类上面:类中方法都添加事务

    • 方法上面:仅该方法添加了事务

    @Transactional注解

    重要参数

    (1)propagation:事务传播行为

    • 多事务方法之间调用,这个过程事务是如何进行管理的。

    (2)isolation:事务隔离级别

    • 多事务操作之间不会产生影响。不考虑隔离性产生很多问题。

    • 三个读问题

      【脏读】:一个未提交事务读取到另一个未提交事务的数据

      【不可重复读】:一个未提交事务读取到另一提交事务修改数据。

      【虚读】:一个未提交事务读取到另一提交事务添加数据。

    • 通过设置事务隔离性,解决读问题

      默认未可重复读

    (3)timeout:超时时间

    (1)事务需要在一定时间内进行提交,如果不提交就进行回滚。

    (2)默认值是-1,设置时间以秒为单位进行计算

    (4)readOnly:是否只读

    (1)读:查询操作,写:添加修改删除操作

    (2)readOnly 默认值false。表示可以查询,可以添加修改删除操作

    (3)设置readOnly值是true,设置成true之后,只能查询

    (5)rollbackFor:回滚

    (1)设置出现哪些异常进行事务回滚

    (6)noRollbackFor:不回滚

    (1)设置出现哪些异常不进行事务回滚

(2)XML配置文件
  1. xml配置文件中配置事务管理器

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <!--注入dataSource-->
    <property name="dataSource" ref="dataSource"/>
    </bean>
    
  2. 在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
    
    <!--开启事务注解-->
    <tx:annotation-driven transaction-manager="transactionManager"/>
    
  3. 配置切入点和切面

    <!--配置通知-->
    <tx:advice id="txAdvice">
        <tx:attributes>
            <!--指定哪种规则的方法上面添加事务-->
            <tx:method name="transferMoney" propagation="REQUIRED"/>
            <!--<tx:method name="transfer*" propagation="REQUIRED"/> 配置以transfer开头的所有方法-->
        </tx:attributes>
    </tx:advice>
    
    <!--配置切入点和切面-->
    <aop:config>
        <!--配置切入点-->
        <aop:pointcut id="pt" expression="execution(* com.Long.Service.UserService.*(..))"/>
        <!--配置切面-->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pt"/>
    </aop:config>
    
完全注解开发
新建配置类txconfig
@Configuration //当前类作为配置类,替代xml配置文件
@ComponentScan(basePackages = {"com.Long"}) //替代<context:component-scan base-package="com
@EnableTransactionManagement //开启事务管理
public class txconfig {

@Bean //配置数据源
public DruidDataSource getDataSource(){
    DruidDataSource druidDataSource = new DruidDataSource();
    druidDataSource.setUrl("jdbc:mysql://localhost:3306/bank?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC");
    druidDataSource.setUsername("root");
    druidDataSource.setPassword("77549252");
    druidDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
    return druidDataSource;
}

@Bean//配置JdbcTemplate
public JdbcTemplate getJdbcTemplate(DataSource dataSource){
    JdbcTemplate jdbcTemplate = new JdbcTemplate();
    jdbcTemplate.setDataSource(dataSource); //建议,到IOC容器中去拿dataSource对象
//        jdbcTemplate.setDataSource(getDataSource()); //不建议这样,重复创建对象
    return jdbcTemplate;
}

@Bean //配置DataSourceTransactionManager
public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource){
    DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
    dataSourceTransactionManager.setDataSource(dataSource);
    return dataSourceTransactionManager;
}
}
测试:
@Service
@Transactional //声明式事务
public class UserService {

@Autowired
private userDao userDao;

public void transferMoney(){
    userDao.addMoney(100,"小肖");
    //模拟异常
    int error= 1/0;
    userDao.reduceMoney(100,"小明");
}
}
@Test
public void testTransactionAnnotation() {
ApplicationContext context = new AnnotationConfigApplicationContext(txconfig.class);
UserService  UserService = context.getBean("userService",UserService.class);
UserService.transferMoney();
}
e对象
//        jdbcTemplate.setDataSource(getDataSource()); //不建议这样,重复创建对象
    return jdbcTemplate;
}

@Bean //配置DataSourceTransactionManager
public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource){
    DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
    dataSourceTransactionManager.setDataSource(dataSource);
    return dataSourceTransactionManager;
}
}
测试:
@Service
@Transactional //声明式事务
public class UserService {

@Autowired
private userDao userDao;

public void transferMoney(){
    userDao.addMoney(100,"小肖");
    //模拟异常
    int error= 1/0;
    userDao.reduceMoney(100,"小明");
}
}
@Test
public void testTransactionAnnotation() {
ApplicationContext context = new AnnotationConfigApplicationContext(txconfig.class);
UserService  UserService = context.getBean("userService",UserService.class);
UserService.transferMoney();
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Steve_hanhaiLong

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

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

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

打赏作者

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

抵扣说明:

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

余额充值