spring

Spring

简介

  • Spring 是一个开源的 Java 框架,主要用于简化企业级应用开发。它提供了全面的基础设施支持,帮助开发者专注于业务逻辑,而不是底层技术细节。
  • Spring 通过依赖注入、AOP 和模块化设计,简化了 Java 开发,提升了代码的可维护性和可扩展性,广泛应用于企业级开发。

优点

  • 免费开源的轻量化框架容器(容器)
  • 轻量性,非入侵性(导入不改变原本代码)
  • 控制反转IOC,面向切面编程AOP
  • 支持事务的处理,对框架整合的支持

导入相关依赖

<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>6.2.3</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>6.2.3</version>
</dependency>

Spring官方文档

Spring Framework Documentation

Spring Framework 中文文档

补充:DAO层和Service层

  • DAO层:直接操作数据库,比如 saveUserfindByUsername
  • Service层:处理业务逻辑,比如检查用户名是否重复,然后调用DAO层保存数据。

在软件开发中,DAO层和Service层是常见的分层设计,各自承担不同的职责。

DAO层(数据访问层)

  • 职责:负责与数据库直接交互,执行数据的增删改查操作。
  • 功能:封装数据库操作,提供简单的接口供Service层调用。
  • 例子:比如保存用户信息、查询订单数据等。

Service层(业务逻辑层)

  • 职责:处理业务逻辑,调用DAO层获取或保存数据,并进行业务处理。
  • 功能:实现核心业务规则,协调多个DAO操作,确保业务逻辑正确。
  • 例子:比如用户注册时,先检查用户名是否已存在,再调用DAO层保存用户信息。

总结

  • DAO层:专注数据库数据处理,sql
  • Service层:专注于业务逻辑处理,判断是否应该执行处理,应该就调用dao的方法
  • Service层一般会new DAO层的对象,调用时用DAO层对象的方法

这种分层设计让代码更清晰、易维护。

控制反转IOC

IOC 的全称是 Inversion of Control,中文翻译为控制反转。它是面向对象编程中的一种设计原则,也是 Spring 框架的核心思想之一。


控制反转(IOC)的核心思想

  1. 传统编程模式
    • 对象的创建和依赖关系的管理由程序代码直接控制。
    • 例如:在代码中直接 new 一个对象,或者手动设置对象的依赖。
  2. 控制反转模式
    • 将对象的创建和依赖关系的管理交给外部容器(如 Spring 框架)来处理。
    • 程序只需要定义好对象的依赖关系,容器负责创建对象并注入依赖。
  • 控制反转

    原来,程序主动创建对象,程序员手动修改代码,控制在程序员手

    实现set后,改成接受用户不同传入,控制在用户手上,程序不再有主动性

    image-20250226234636252

public class UserServiceImpl implements UserService{
    UserDao userDao;

    @Override
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public void getUser() {
        userDao.getUser();
    }
}
package com.zhm.service;

import com.zhm.dao.JavaUserDaoImpl;
import com.zhm.dao.PyUserDaoImpl;
import com.zhm.dao.UserDaoImpl;

public class UserServiceTest {
    public static void main(String[] args) {
        // 用户调用service层就可以
        UserService userService = new UserServiceImpl();
        // 用户自己传入,()内自己选
        userService.setUserDao(new UserDaoImpl());
//        userService.setUserDao(new JavaUserDaoImpl());

        userService.getUser();
    }
}

测试第一个Spring

  1. 写需要的类

  2. 在resources内创建beans.xml

  3. 配置文件

    <?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
            https://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <!--Spring创建对象,用户只用从spring容器中调用需要的对象-->
        <bean id="hello" class="com.zhm.pojo.Hello">
            <!--底层本质就是set方法-->
            <property name="str" value="Spring容器创建了Hello对象"/>
        </bean>
    
    
    </beans>
    
  4. 调用ClassPathXmlApplicationContext 获得spring容器,getbean(id)获得对象

    import com.zhm.pojo.Hello;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class MyTest {
        public static void main(String[] args) {
            // Spring创建对象,用户只用从spring容器中通过getBean调用需要的对象,用户不用new对象了
            ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
            Hello hello = (Hello) context.getBean("hello");
            System.out.println(hello.getStr());
        }
    }
    
  • 用spring实现ioc案例
<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

        <bean id="userDao" class="com.zhm.dao.UserDaoImpl"/>
        <bean id="pyUserDao" class="com.zhm.dao.PyUserDaoImpl"/>
        <bean id="javaUserDao" class="com.zhm.dao.JavaUserDaoImpl"/>

        <bean id="userService" class="com.zhm.service.UserServiceImpl">
            <property name="userDao" ref="javaUserDao"/>
        </bean>


</beans>
package com.zhm.service;

import com.zhm.dao.JavaUserDaoImpl;
import com.zhm.dao.PyUserDaoImpl;
import com.zhm.dao.UserDaoImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class UserServiceTest {
    public static void main(String[] args) {
        // 用户调用service层就可以
        UserService userService = new UserServiceImpl();
        // 用户自己传入,()内自己选
        userService.setUserDao(new UserDaoImpl());
//        userService.setUserDao(new JavaUserDaoImpl());

        userService.getUser();
        // 第二种,用spring管理对象,只用改配置文件实现不同调用
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        UserService userService1 = (UserService) context.getBean("userService");
        userService1.getUser();
    }
}
  • 总结

    对象由spring创建(构造器),对象的属性由spring设置(调用set),相对于在spring容器调用需要的对象

    image-20250227132218114

    实现不同的操作,不需要改变程序,直接在beans.xml文件内修改就行了

    ioc:对象的创建,装配,管理都由Spring执行

IOC创建对象

  • spring创对象默认调用无参,如果没有无参,就需要在beans.xml里配置有参

    1. 按下标
    2. 按类型
    3. 按kv(最常用)
    <?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
            https://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <!--    <bean id="user" class="com.zhm.pojo.User">-->
    <!--        <constructor-arg index="0" value="按下标执行有参"/>-->
    <!--    </bean>-->
    
    <!--    <bean id="user" class="com.zhm.pojo.User">-->
    <!--        <constructor-arg type="java.lang.String" value="按类型执行有参"/>-->
    <!--    </bean>-->
    
    <!--一般用这个-->
        <bean id="user" class="com.zhm.pojo.User">
            <constructor-arg name="name" value="按kv键值执行有参"/>
        </bean>
    
    
    </beans>
    
  • spring容器类似婚介公司,对象在容器里都执行构造创建准备好了,需要哪个调用哪个

Spring配置

别名

<!--name是上面的id,alias是别名-->
<alias name="user" alias="user2"/>

bean配置

<!--id:唯一标识符,学过的对象名,调用时要用
    class:bean对象对应的类位置,类限定名,包名 + 类型
    name:别名,可以起多个,用逗号,空格等隔开,别名就是另一个名字-->
    <bean id="userT" class="com.zhm.pojo.UserT" name="t1,t2,t3">
        <constructor-arg name="name" value="按kv键值执行有参"/>
    </bean>

import导入

  • 用于团队开发,把不同的xml汇总到一个applicationContetx.xml里,之后只用一个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
            https://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <import resource="beans.xml"/>
        <import resource="beans2.xml"/>
        <import resource="beans3.xml"/>
    </beans>
    

依赖注入

  • 注入:本质调用set方法,通过spring给属性赋值
  • 依赖:通过Spring=依赖Spring
    1. 构造器注入(上面)
    2. set注入

set注入环境搭建

  1. 创建两个复杂属性的类,实现getset

    package com.zhm.pojo;
    
    public class Address {
        private String address;
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    
        @Override
        public String toString() {
            return "Address{" +
                    "address='" + address + '\'' +
                    '}';
        }
    }
    
    package com.zhm.pojo;
    
    import java.util.*;
    
    public class Student {
        private String name;
        private Address address;
        private String[] books;
        private List<String> hobbys;
        private Map<String,String> cards;
        private Set<String> games;
        private String wife;
        private Properties info;
    ...
    }
    
  2. 创建spring配置文件 beans.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
            https://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="student" class="com.zhm.pojo.Student">
            <property name="name" value="我爱我家"/>
            <property name="address" ref="address"/>
        </bean>
    
        <bean id="address" class="com.zhm.pojo.Address">
            <property name="address" value="和昌森林"/>
        </bean>
    </beans>
    
  3. 测试 CPX

    import com.zhm.pojo.Student;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class MyTest {
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
            Student student = (Student) context.getBean("student");
            System.out.println(student.getName());
            System.out.println(student.getAddress());
    
        }
    }
    

实现

  • 常用:普通注入value和bean注入ref

    <?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
            https://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="address" class="com.zhm.pojo.Address">
            <property name="address" value="和昌森林"/>
        </bean>
    
        <bean id="student" class="com.zhm.pojo.Student">
            <!--普通注入,value,常用-->
            <property name="name" value="我爱我家"/>
            <!--bean注入,ref,常用-->
            <property name="address" ref="address"/>
            <!--数组注入,array-->
            <property name="books">
                <array>
                    <value>西游记</value>
                    <value>水浒传</value>
                    <value>红楼梦</value>
                    <value>三国演义</value>
                </array>
            </property>
            <!--list注入-->
            <property name="hobbys">
                <list>
                    <value>玩游戏</value>
                    <value>打电脑</value>
                    <value>用手机</value>
                </list>
            <!--map注入-->
            </property>
            <property name="cards">
                <map>
                    <entry key="身份证" value="420922200103163833"/>
                    <entry key="学生卡" value="1905120428"/>
                </map>
            </property>
            <!--set注入-->
            <property name="games">
                <set>
                    <value>LOL</value>
                    <value>MOBA</value>
                    <value>PUBG</value>
                </set>
            </property>
            <!--null注入-->
            <property name="wife">
                <null/>
            </property>
            <!--配置注入,props prop-->
            <property name="info">
                <props>
                    <prop key="driver">com.mysql.jdbc.Driver</prop>
                    <prop key="url">localhost:3306</prop>
                    <prop key="username">root</prop>
                    <prop key="password">123456</prop>
                </props>
            </property>
    
        </bean>
    
    
    </beans>
    

    测试结果

    import com.zhm.pojo.Student;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class MyTest {
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
            Student student = (Student) context.getBean("student");
            System.out.println(student);
    
            /*
            Student{
            name='我爱我家',
            address=Address{address='和昌森林'},
            books=[西游记, 水浒传, 红楼梦, 三国演义],
            hobbys=[玩游戏, 打电脑, 用手机],
            cards={身份证=420922200103163833, 学生卡=1905120428},
            games=[LOL, MOBA, PUBG],
            wife='null',
            info={password=123456, url=localhost:3306, driver=com.mysql.jdbc.Driver, username=root}}
             */
        }
    }
    

拓展注入方式

  • p注入,对应set注入

  • c注入,对应构造器注入

  • 导入依赖

    <?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:c="http://www.springframework.org/schema/c"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd"> 
       
        <bean id="user" class="com.zhm.pojo.User" c:age="10" c:name="xaxxa" p:age="50" p:name="xamxa"/>
        
    </beans>
    

核心技术

image-20250227174207362

Bean作用域(scope)

image-20250227181526432

  1. singleton 单例模式,对象只有一个(默认就是,不用设置)

    <bean id="user" class="com.zhm.pojo.User" scope="singleton ">
        <constructor-arg name="name" value="nkalxla"/>
        <constructor-arg name="age" value="110"/>
    </bean>
    user==user2 true
    
  2. prototype 原型模式,每个对象都是新创建

    <bean id="user" class="com.zhm.pojo.User" scope="prototype">
        <constructor-arg name="name" value="nkalxla"/>
        <constructor-arg name="age" value="110"/>
    </bean>
    user==user2 false
    

自动装配autowire

  • 环境配置

    人养猫和狗,猫狗各有方法

  • 装配方式

    1. 手动配置beans.xml文件,就是上面的依赖注入

    2. 通过手动配置java

    3. 自动装配beans.xml,加autowire

      • byName:会自动在容器上下文中查找,和自己对象set方法后的值对应的 bean id

        id要唯一

      • byType:会自动在容器上下文中查找,和自己对象属性类型对应的 bean 类型

        不能有多个同类型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
            https://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="cat" class="com.zhm.pojo.Cat"/>
        <bean id="dog" class="com.zhm.pojo.Dog"/>
    <!--    <bean id="dog2" class="com.zhm.pojo.Dog"/>-->
    <!--1.byName 要求set后的对象名和注册bean的id一样,且id要唯一
        2.byType 要求set后的对象类型和支持的bean类型一样,不能有多个相同类型bean-->
        <bean id="person" class="com.zhm.pojo.Person" autowire="byName">
            <property name="name" value="xiaoming"/>
    <!--        <property name="cat" ref="cat"/>-->
    <!--        <property name="dog" ref="dog"/>-->
        </bean>
    
    </beans>
    

注解实现自动装配

  • 用@Autowired实现 @Qualifier进行调整

    1. 导入约束和支持,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"
             xmlns:aop="http://www.springframework.org/schema/aop"
             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
              http://www.springframework.org/schema/aop
              https://www.springframework.org/schema/aop/spring-aop.xsd">
      
      <!--支持,开启注解-->
          <context:annotation-config/>
      
          <bean id="cat2" class="com.zhm.pojo.Cat"/>
          <bean id="cat3" class="com.zhm.pojo.Cat"/>
          <bean id="dog2" class="com.zhm.pojo.Dog"/>
          <bean id="dog3" class="com.zhm.pojo.Dog"/>
      
          <bean id="person" class="com.zhm.pojo.Person">
              <property name="name" value="xiaoming"/>
          </bean>
      
      </beans>
      
    2. 写注解

      @Autowired执行过程:先根据 byname查找bean的id有没有符合,没有就bytype找bean的类型有没有符合,都没用就报错

      或者

      都没有可以用@Qualifier指定指向的id

      public class Person {
          private String name;
          // 如果显式定义required = false 说明该对象可以null,否则不行
          @Autowired(required = false)
          @Qualifier(value = "dog2")
          private Dog dog;
          @Autowired
          @Qualifier(value = "cat3")
          private Cat cat;
      }
      

补充,上面的约束相对于安全执行的规则,下面的支持代表可以使用这个配置

这是一个 Spring 框架的 XML 配置文件,用于定义和管理 Spring 容器中的 Bean 及其相关配置。它的结构和属性有以下意义:


1. xmlns(命名空间声明)

  • 用于定义 XML 文档中使用的命名空间,避免标签名冲突。
  • 例如:
    • xmlns="http://www.springframework.org/schema/beans":默认命名空间,表示没有前缀的标签(如 <bean>)属于 Spring Beans 的命名空间。
    • xmlns:context="http://www.springframework.org/schema/context":定义 context 前缀,用于 Spring 的上下文相关配置(如组件扫描)。
    • xmlns:aop="http://www.springframework.org/schema/aop":定义 aop 前缀,用于 Spring AOP(面向切面编程)的配置。

2. xsi:schemaLocation

  • 用于指定命名空间对应的 XML Schema 文件的位置,帮助验证 XML 文件的正确性。
  • 例如:
    • 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
    • http://www.springframework.org/schema/aop 对应 https://www.springframework.org/schema/aop/spring-aop.xsd

3. 整体意义

  • 这个配置文件告诉 Spring:
    1. 使用 Spring Beans 的核心功能(如定义 <bean>)。
    2. 使用 Spring 的上下文功能(如自动扫描组件 @Component@Service 等)。
    3. 使用 Spring AOP 功能(如定义切面、增强逻辑等)。
  • 通过这种方式,Spring 可以正确加载和解析配置文件,管理应用中的对象(Bean)及其依赖关系。

4. 简单比喻

把这个配置文件想象成一份“说明书”:

  • xmlns 是说明书的“目录”,告诉 Spring 有哪些功能模块(如 Beans、Context、AOP)。
  • xsi:schemaLocation 是“页码”,告诉 Spring 每个模块的具体规则在哪里可以找到。
  • Spring 根据这份“说明书”正确地加载和管理应用程序中的各种组件。

5. 实际使用示例

在这个配置文件中,你可以:

  • 定义 Bean:

    <bean id="myService" class="com.example.MyService"/>
    
  • 开启组件扫描:

    <context:component-scan base-package="com.example"/>
    
  • 配置 AOP:

    <aop:config>
        <aop:aspect ref="myAspect">
            <aop:pointcut id="myPointcut" expression="execution(* com.example.*.*(..))"/>
            <aop:before pointcut-ref="myPointcut" method="beforeAdvice"/>
        </aop:aspect>
    </aop:config>
    

总结

这个配置文件是 Spring 的核心配置文件之一,定义了 Spring 如何管理 Bean、扫描组件以及支持 AOP 等功能。通过命名空间和 Schema 文件,Spring 能够正确解析和执行这些配置。

注解开发

  • 注册环境

    pojo实体类层,dao数据库层,service逻辑处理层,controller用户交互层

    Controller层Service层DAO层是软件开发中常见的三层架构,它们分工明确,各司其职,共同协作完成业务逻辑。它们的关系可以用一个简单的例子来说明:


    1. Controller层(控制层)

    • 作用:负责与用户直接交互,接收用户请求并返回响应。
    • 类比:像餐厅的服务员,负责接收顾客的点单,并把做好的菜端给顾客。
    • 职责
      • 接收用户输入(如HTTP请求)。
      • 调用Service层处理业务逻辑。
      • 将处理结果返回给用户(如JSON数据或页面)。

    2. Service层(服务层)

    • 作用:处理具体的业务逻辑,是核心业务操作的地方。
    • 类比:像餐厅的厨师,负责根据顾客的点单做菜。
    • 职责
      • 实现业务规则(如用户注册、订单计算等)。
      • 调用DAO层获取或保存数据。
      • 处理事务管理(如数据库事务)。

    3. DAO层(数据访问层)

    • 作用:负责与数据库直接交互,执行数据的增删改查操作。
    • 类比:像餐厅的仓库管理员,负责从仓库中取食材或存放食材。
    • 职责
      • 直接操作数据库(如查询用户信息、保存订单等)。
      • 提供简单的数据访问接口,供Service层调用。

    三者的关系

    1. Controller层调用Service层:Controller接收用户请求后,交给Service层处理业务逻辑。
    2. Service层调用DAO层:Service层处理业务时,如果需要操作数据库,就调用DAO层。
    3. DAO层操作数据库:DAO层负责与数据库交互,执行具体的SQL操作。

    举个例子:用户注册功能

    1. Controller层:接收用户提交的注册表单(用户名、密码等)。
    2. Service层:检查用户名是否已存在,如果不存在则调用DAO层保存用户信息。
    3. DAO层:将用户信息插入数据库。
    4. Service层:返回注册成功或失败的结果。
    5. Controller层:将结果返回给用户(如跳转到成功页面或显示错误信息)。

    总结

    • Controller层:负责与用户交互。
    • Service层:负责处理业务逻辑。
    • DAO层:负责与数据库交互。

    它们的关系是:Controller → Service → DAO,层层调用,职责分明,便于维护和扩展!

开启包扫描

扫描到该包内有组件,自动注册

image-20250228110932021

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

<?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"
       xmlns:aop="http://www.springframework.org/schema/aop"
       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
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">

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

</beans>

bean

  • @Component 注解

    注解注册bean,id就是class小写

    等价

// 注解注册bean,id就是class小写 == <bean id="uesr" class="com.zhm.pojo.User"/>
@Component
@Scope("prototype|singleton")
public class User {
     public String name;

     public String getName() {
          return name;
     }
}
  • @Component衍生

    DAO层 @Repository

    Service层 @Service

    Controller层 @Controller

    都是注册bean,注解用法一样image-20250228111428367

依赖注入

  • @Value("")

  • 注解注入属性,set方法上,value后面就算注入的值

    等价

public class User {
     public String name;

     public String getName() {
          return name;
     }
     // 注解注入属性,set方法上,value后面就算注入的值 == <property name="name" value="value注解"/>
     @Value("value注解")
     public void setName(String name) {
          this.name = name;
     }
}

自动装配

用@Autowired实现 @Qualifier进行调整

作用域

  • 单列或者原型
@Scope("prototype|singleton")

总结

  • 优点:方便

  • 缺点:不能实现ref调用其他bean,维护困难

  • xml更加万能,复杂的还是要用xml

  • 注意点:开启注解支持和约束条件

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

纯java配置Spring

image-20250228115932183

  • @Configuration注解

    把该config类对应成beans.xml

    @ComponentScan("com.zhm.pojo") 扫包

    package com.zhm.config;
    
    import com.zhm.pojo.User;
    import org.springframework.context.annotation.*;
    
    // 把这个类变成beans.xml,本质这个类也是被spring容器托管
    @Configuration
    @ComponentScan("com.zhm.pojo")
    //@Import(ZConfig.class)
    public class ZConfig {
    
        @Bean
        // 注册bean
        // 方法名是id class是实际返回类型 return new User();
        public User getUser(){
            return new User();
        }
    }
    
  • 原注解一样使用

  • package com.zhm.pojo;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Component;
    
    @Component
    public class User {
        private String name;
    
        public String getName() {
            return name;
        }
    
        @Value("axkax")
        public void setName(String name) {
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }
    
  • 测试

    修改处

    ApplicationContext context = new AnnotationConfigApplicationContext(ZConfig.class);

    import com.zhm.config.ZConfig;
    import com.zhm.pojo.User;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    
    public class MyTest {
        @Test
        public void test1(){
            // 修改处
            ApplicationContext context = new AnnotationConfigApplicationContext(ZConfig.class);
            User user = context.getBean("getUser", User.class);
            System.out.println(user);
        }
    }
    

代理模式

  • 23种设计模式之一

静态代理

  • 案例:租房

    image-20250228124517139

  • 角色分析:

    1. 抽象角色(租房方法,接口)
    2. 真实角色,被代理的角色(房东)
    3. 代理角色,代理真实角色(中介)
    4. 客户,访问代理对象(租房人)
  • 两个类实现同一接口

  • 步骤

    1. 接口
    2. 真实角色实现接口
    3. 代理角色实现接口,组合真实角色,在实现方法中调用真实角色的实现方法,自己补充需要方法
    4. 客户,面对中介就行

    image-20250228125557393

    package com.zhm.demo01;
    
    // 抽象代理方法
    public interface Rent {
        void rent();
    }
    
    package com.zhm.demo01;
    
    // 房东,被代理,更纯粹做事情
    public class Master implements Rent{
        @Override
        public void rent() {
            System.out.println("房东出租房");
        }
    }
    
    package com.zhm.demo01;
    
    // 中介,代理者,可以附加自己的操作
    public class Proxy implements Rent{
    
        private Master master;
    
        public Proxy() {
        }
    
        public Proxy(Master master) {
            this.master = master;
        }
    
        public Master getMaster() {
            return master;
        }
    
        public void setMaster(Master master) {
            this.master = master;
        }
    
        @Override
        public void rent() {
            tip();
            master.rent();
            getMoney();
        }
    
        public void tip(){
            System.out.println("签合同");
        }
    
        public void getMoney(){
            System.out.println("收房租");
        }
    
    
    }
    
    package com.zhm.demo01;
    
    // 用户,只用面对中介
    public class Client {
        public static void main(String[] args) {
            Master master = new Master();
            new Proxy(master).rent();
        }
    }
    
  • 好处

    1. 真实角色更纯粹,不用关注公共业务
    2. 公共业务交给代理模式,实现分工
    3. 公共业务拓展方便
  • 坏处

    一个真实角色就要有一个代理角色,代码量翻倍,开发效率低

动态代理

  • 实现InvocationHandler接口 处理代理实例

    调用Proxy类静态方法 通过代理获得代理类

    只用传入实现代理类的接口就行

  • 万能类,当成工具

    package com.zhm.demo2;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class ProxyInvocationHandler implements InvocationHandler {
    
        private Object object;
    
        public void setObject(Object object) {
            this.object = object;
        }
    
        // 得到代理类
        public Object getProxy(){
            // 参数1类加载器 只有三种,随意Class对象.getClassLoader()获取就行
            // 2 反射获取需要代理的接口
            // 3 InvocationHandler处理代理实例,返回结果,
            // 这里这个类继承了InvocationHandler 所以可以用this
            return Proxy.newProxyInstance(this.getClass().getClassLoader(), object.getClass().getInterfaces(), this);
        }
    
        // 处理代理实例,返回结果
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            myFront();
            Object o = method.invoke(object, args);
            myBehind();
            return o;
        }
        public void myFront(){
    //        System.out.println("front");
        }
    
        public void myBehind(){
    //        System.out.println("behind");
        }
    }
    
    
    
  • 上面的例子,不手动创建代理类,自动创建

    package com.zhm.demo2;
    
    // 用户,只用面对中介
    public class Client {
        public static void main(String[] args) {
            Master master = new Master();
            ProxyInvocationHandler pih = new ProxyInvocationHandler();
            pih.setObject(master);
            Rent proxy = (Rent) pih.getProxy();
            proxy.rent();
        }
    }
    

Spring实现AOP

AOP(Aspect-Oriented Programming,面向切面编程)是一种编程范式,旨在将横切关注点(如日志、事务管理、安全等)与核心业务逻辑分离,以提升代码的模块化和可维护性。

  • 核心概念:
  1. 切面(Aspect):封装横切关注点的模块,包含通知和切点。
  2. 通知(Advice):切面在特定时机执行的操作,如方法调用前后。
  3. 切点(Pointcut):定义通知应用的特定位置,通常通过表达式指定。
  4. 连接点(Join Point):程序执行中的特定点,如方法调用或异常抛出。

理解:程序执行就是一个个切面执行,代理就是在某个切入点加上需要的切面

使用原生Spring API,实现Spring API

  1. 导入依赖

    <dependencies>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.7</version>
        </dependency>
    </dependencies>
    
  2. service业务层 接口和对应实现

    package com.zhm.service;
    
    public interface UserService {
        void insert();
        void delete();
        void update();
        void query();
    }
    
    package com.zhm.service;
    
    public class UserServiceImpl implements UserService{
    
        @Override
        public void insert() {
            System.out.println("插入一个用户");
        }
    
        @Override
        public void delete() {
            System.out.println("删除一个用户");
    
        }
    
        @Override
        public void update() {
            System.out.println("更新一个用户");
    
        }
    
        @Override
        public void query() {
            System.out.println("查询一个用户");
    
        }
    }
    
  3. 创建两个实现类,实现MethodBeforeAdvice,AfterReturningAdvice

    写代理后实现类 的 方法前和方法后需要增加的业务

    实现就行了,实现before就是业务前,After就是后

    package com.zhm.log;
    
    import org.springframework.aop.AfterReturningAdvice;
    
    import java.lang.reflect.Method;
    
    public class BehindLog implements AfterReturningAdvice {
        @Override
        public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
            System.out.println("我是后面:类"+target.getClass().getName()+"调用了方法"+method.getName()+"返回是"+returnValue);
        }
    }
    
    package com.zhm.log;
    
    import org.springframework.aop.MethodBeforeAdvice;
    
    import java.lang.reflect.Method;
    
    public class FrontLog implements MethodBeforeAdvice {
        @Override
        public void before(Method method, Object[] args, Object target) throws Throwable {
            System.out.println("我是前面:类"+target.getClass().getName()+"调用了方法"+method.getName());
        }
    }
    
  4. 配置beans.xml

    加约束和支持

    pointcut设置切面,就是作用域

    advisor就是环绕

    <?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"
           xmlns:aop="http://www.springframework.org/schema/aop"
           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
            http://www.springframework.org/schema/aop
            https://www.springframework.org/schema/aop/spring-aop.xsd">
    
        <bean id="userService" class="com.zhm.service.UserServiceImpl"/>
        <bean id="behindLog" class="com.zhm.log.BehindLog"/>
        <bean id="frontLog" class="com.zhm.log.FrontLog"/>
    
        <aop:config>
    <!--设置切面点,execution(* com.zhm.service.UserServiceImpl.*(..))代表类下所有方法,*(..)方法名随意(参数任意)-->
            <aop:pointcut id="point" expression="execution(* com.zhm.service.UserServiceImpl.*(..))"/>
    <!--设置环绕-->
            <aop:advisor advice-ref="behindLog" pointcut-ref="point"/>
            <aop:advisor advice-ref="frontLog" pointcut-ref="point"/>
        </aop:config>
    
    </beans>
    
    
    
  5. 测试

    import com.zhm.service.UserService;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class MyTest {
        @Test
        public void test01(){
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
            // 动态代理代理的是接口,注意点
            UserService userService = (UserService) context.getBean("userService");
            userService.insert();
        }
    }
    

动态代理代理的是接口,注意点

自定义切面实现AOP

  • 新建要加的业务类

    package com.zhm.diycut;
    
    public class MyCut {
        public void beforePoint(){
            System.out.println("方法执行前");
        }
        public void afterPoint(){
            System.out.println("方法执行后");
        }
    }
    
  • 注册业务类bean,配置beans.xml的aop配置,用业务类当切面

        <aop:config>
    <!--将注册的class抽成切面-->
            <aop:aspect id="cut" ref="myCut">
    <!--切入点-->
    <!--第一个*表示返回类型任意,第二个*表示该类下的所有方法-->
                <aop:pointcut id="point" expression="execution(* com.zhm.service.UserServiceImpl.*(..))"/>
    <!--通知,需要执行的方法-->
                <aop:before method="beforePoint" pointcut-ref="point"/>
                <aop:after method="afterPoint" pointcut-ref="point"/>
            </aop:aspect>
        </aop:config>
    

注解实现AOP

  1. 新建要加的业务类,注册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"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:aop="http://www.springframework.org/schema/aop"
           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
            http://www.springframework.org/schema/aop
            https://www.springframework.org/schema/aop/spring-aop.xsd">
    
        <bean id="userService" class="com.zhm.service.UserServiceImpl"/>
        <bean id="behindLog" class="com.zhm.log.BehindLog"/>
        <bean id="frontLog" class="com.zhm.log.FrontLog"/>
        <bean id="myCut" class="com.zhm.diycut.MyCut"/>
        <bean id="annoCut" class="com.zhm.diycut.AnnoCut"/>
    
    <!--开启注解使用(先约束)-->
        <aop:aspectj-autoproxy/>
    
  2. 加注解,@aspect 标注类是切面,@Before@After后面写切入点

    package com.zhm.diycut;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.Signature;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    
    // 标注类是切面
    @Aspect
    public class AnnoCut {
        // 定义切入点(作用域)和切入位置
        @Before("execution(* com.zhm.service.UserServiceImpl.*(..))")
        public void annoBefore(){
            System.out.println("方法执行前业务");
        }
    
        @After("execution(* com.zhm.service.*.*(..))")
        public void annoAfter(){
            System.out.println("方法执行后业务");
        }
    
        @Around("execution(* com.zhm.service.*.*(..))")
        public void annoAround(ProceedingJoinPoint joinPoint) throws Throwable {
            System.out.println("前业务");
            // 执行业务
            Object proceed = joinPoint.proceed();
            System.out.println("后业务");
        }
    
    
    }
    
    

Spring-Mybatis

Mybatis回顾

  1. 导入依赖,连接数据库
  2. mybatis-config.xml,mybatis配置文件
  3. MybatisUtils类,配置获取sqlsession的工具类,静态代码块和静态方法
  4. pojo User @lombok
  5. mapper UserMapper和对应UserMapper.xml配置实现类
  6. UserMapper.xml 命名空间,mapper实现方法,mybatis-config.xml注册UserMapper.xml
  7. 资源导出问题
  8. 测试

连接方法1

  1. 导入依赖

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.33</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.19</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.39</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.3.39</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.7</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.6</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.36</version>
        </dependency>
    
    </dependencies>
    
  2. 创建spring-dao.xml spring的bean配置,把原来mybatis-config的配置整合到这里

    注意点:

    一些类

    源=DriverManagerDataSource

    工厂=SqlSessionFactoryBean

    sqlsession=SqlSessionTemplate

    <?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"
           xmlns:aop="http://www.springframework.org/schema/aop"
           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
            http://www.springframework.org/schema/aop
            https://www.springframework.org/schema/aop/spring-aop.xsd">
    
        <!--1 配置连接数据库的数据源-->
        <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=utf8"/>
            <property name="username" value="root"/>
            <property name="password" value="123456"/>
        </bean>
        <!--2 配置sqlSessionFactory,连上mybatis配置文件-->
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource"/>
            <property name="configLocation" value="mapper-config.xml"/>
            <property name="mapperLocations" value="classpath:com/zhm/mapper/*.xml"/>
        </bean>
    
        <!--3 配置SqlSessionTemplate(sqlSession的实现,等价),没有set方法和无参,用有参构造方法创建-->
        <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
            <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"/>
        </bean>
    
        <!--4 配置userMapperImpl,ref配置SqlSessionTemplate结合set,以后只用这个id userMapperImpl就可以了-->
        <bean id="userMapperImpl" class="com.zhm.mapper.UserMapperImpl">
            <property name="sqlSession" ref="sqlSession"/>
        </bean>
    
    
    </beans>
    
  3. 创建UserMapperImpl实现类,配合SqlSessionTemplate(等价sqlsession)完成getMapper方法,注册bean

    package com.zhm.mapper;
    
    import com.zhm.pojo.User;
    import org.mybatis.spring.SqlSessionTemplate;
    
    import java.util.List;
    
    public class UserMapperImpl implements UserMapper{
        private SqlSessionTemplate sqlSession = null;
    
        public void setSqlSession(SqlSessionTemplate sqlSession) {
            this.sqlSession = sqlSession;
        }
    
        @Override
        public List<User> queryUser() {
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            return mapper.queryUser();
        }
    }
    
  4. 测试

    @Test
    public void test01(){
        ApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml");
        UserMapper userMapper = context.getBean("userMapperImpl", UserMapper.class);
        List<User> users = userMapper.queryUser();
        for (User user : users) {
            System.out.println(user);
        }
    }
    
  5. 附加

    可以把spring-dao.xml分成两个spring配置,一个只负责spring-mybatis配置,一个只负责注册需要的类bean

    最后用import导入

    <?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"
           xmlns:aop="http://www.springframework.org/schema/aop"
           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
            http://www.springframework.org/schema/aop
            https://www.springframework.org/schema/aop/spring-aop.xsd">
    
        <import resource="spring-dao.xml"/>
    
        <!--专注注册bean,新的类-->
    
        <!--4 配置userMapperImpl,ref配置SqlSessionTemplate结合set,以后只用这个id userMapperImpl就可以了-->
        <bean id="userMapperImpl" class="com.zhm.mapper.UserMapperImpl">
            <property name="sqlSession" ref="sqlSession"/>
        </bean>
    
    
    </beans>
    
    <?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"
           xmlns:aop="http://www.springframework.org/schema/aop"
           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
            http://www.springframework.org/schema/aop
            https://www.springframework.org/schema/aop/spring-aop.xsd">
        <!--专注数据库-->
    
        <!--1 配置连接数据库的数据源-->
        <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=utf8"/>
            <property name="username" value="root"/>
            <property name="password" value="123456"/>
        </bean>
        <!--2 配置sqlSessionFactory,连上mybatis配置文件-->
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource"/>
            <property name="configLocation" value="mapper-config.xml"/>
            <property name="mapperLocations" value="classpath:com/zhm/mapper/*.xml"/>
        </bean>
    
        <!--3 配置SqlSessionTemplate(sqlSession的实现,等价),没有set方法和无参,用有参构造方法创建-->
        <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
            <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"/>
        </bean>
    
    </beans>
    
    

连接方法2

  • 修改方法1的第三步,继承SqlSessionDaoSupport,注册时属性传入sqlsessionfactory

    package com.zhm.mapper;
    
    import com.zhm.pojo.User;
    import org.mybatis.spring.support.SqlSessionDaoSupport;
    
    import java.util.List;
    
    public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper{
    
        @Override
        public List<User> queryUser() {
            return getSqlSession().getMapper(UserMapper.class).queryUser();
        }
    }
    
    <bean id="userMapperImpl2" class="com.zhm.mapper.UserMapperImpl2">
        <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
    </bean>
    

事务

ACID

一句话本质,要么都成功,要么都失败

  1. 原子性 要么都成功,要么都失败
  2. 一致性 前后结果要一致,取钱总和一样
  3. 隔离性 两个线程操作同一数据,保证数据一致
  4. 持久性 事务一旦提交就永久化,即便系统故障也不会丢失

Spring声明式事务

  • 用切面织入实现
  1. 导入约束 tx和aop

  2. 配置事务管理器

  3. 结合aop实现事务的织入

  4. spring实现aop 动态代理

    <?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"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xmlns:tx="http://www.springframework.org/schema/tx"
           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
            http://www.springframework.org/schema/aop
            https://www.springframework.org/schema/aop/spring-aop.xsd
            http://www.springframework.org/schema/tx
            https://www.springframework.org/schema/aop/spring-tx.xsd">
        <!--专注数据库-->
        
    <!--配置事务管理器-->
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource"/>
        </bean>
    
    <!--结合aop实现事务的织入-->
        <tx:advice id="txAdvice" transaction-manager="transactionManager">
            <tx:attributes>
                <tx:method name="insert" propagation="REQUIRED"/>
                <tx:method name="delete" propagation="REQUIRED"/>
                <tx:method name="update" propagation="REQUIRED"/>
                <tx:method name="query" read-only="true"/>
                <tx:method name="*" propagation="REQUIRED"/>
            </tx:attributes>
        </tx:advice>
    
    <!--spring实现aop 动态代理-->
        <aop:config>
            <aop:pointcut id="txPoint" expression="execution(* com.zhm.mapper.*.*(..))"/>
            <aop:advisor advice-ref="txAdvice" pointcut-ref="txPoint"/>
        </aop:config>
    
    </beans>
    
posted @ 2025-04-22 22:09  学习java的白菜  阅读(7)  评论(0)    收藏  举报