欢迎来到顔をしての博客吖,如果文章记|

园龄:粉丝:关注:

2023-03-10 17:00阅读: 17评论: 0推荐: 0

Spring

一、为什么学习Spring


概述:

从配置到安全性,从 Web 应用程序到大数据——无论您的应用程序的基础架构需求是什么,都有一个 Spring 项目可以帮助您构建它。从小处着手,只使用您需要的东西 - Spring 在设计上是模块化的

特点:

  • 简化开发:降低企业开发的复杂性

    • IoC
    • AOP
      • 事务处理
  • 框架整合:高效整合其他技术,提高企业级应用开发于运行效率

    • MyBatis

    • MyBatisPlus

      ...

二、Spring Framework系统架构


Spring Framework 是 Spring 生态圈中最基础的项目 , 是其他项目的根基

image-20230310105332318

  • Core Container: 核心容器
  • AOP: 面向切面编程
  • Aspects: AOP 思想实现
  • Data Access: 数据访问
  • Data lntegration : 数据集成
  • Web: Web 开发
  • Test : 单元测试与集成测试

三、Spring的核心概念


目标:充分解耦

  1. IoC(控制反转)

    使用对象时,由主动new产生对象转换为由外部提供对象,此过程中对象创建控制权由程序转移到外部,此思想称为控制反转

    Spring技术对IoC思想进行了实现

    • spring提供; 一个容器,称为IoC容器(Spring容器),用来充当IoC思想的“外部”
    • IoC容器负责对象的创建、初始化等一系列工作,被创建或被管理的对象在IoC容器中统称为Bean
  2. DI(依赖注入)

    在容器中建立bean与bean之间的依赖关系的整个过程称为依赖注入

最终效果:

​ 使用对象时不仅可以直接从IoC容器中获取,并且获取到的bean已经绑定了所有的依赖关系

1. IoC入门

  1. 导入spring坐标

    <!-- spring-->
    <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.10.RELEASE</version>
    </dependency>
  2. 配置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属性表示给bean起别名
    class属性表示给bean定义类型-->
    <bean id="userDao" class="com.spring_ioc.dao.impl.UserDaoImpl"/>
    <bean id="userService" class="com.spring_ioc.service.impl.UserServiceImpl"/>
    </beans>

    注意:在定义bean时id属性不能重复

  3. 创建IoC容器并获取bean

    //创建IoC容器并获取配置信息
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    //获取bean
    UserDao userDao = (UserDao) applicationContext.getBean("userDao");
    UserService userService = (UserService)applicationContext.getBean("userService");

2. DI入门

  1. 删除业务层中使用new的方式创建的dao对象

    private UserDao userDao;
  2. 提供对应的set方法

    public void setUserDao(UserDao userDao) {
    this.userDao = userDao;
    }
  3. 配置service与dao的关系

    <bean id="userService" class="com.spring_ioc.service.impl.UserServiceImpl">
    <!-- 配置service与dao的关系
    name属性表示配置哪一个具体的属性
    ref属性表示参照哪一个bean-->
    <property name="userDao" ref="userDao"/>
    </bean>

四、核心容器(IoC)


1. bean(配置文件开发)

image-20230311112915734

1. bean的配置
  1. 基础配置

    image-20230310145439688

  2. 别名配置

    image-20230310145905558

    注意事项:

    获取bean无论是通过id还是name获取如果无法获取到将抛出异NoSuchBeanDefinitionException

    NoSuchBeanDefinitionException :NO bean named 'bookServiceImp1 ' available
  3. 作用范围配置

    image-20230310150319980

    • 适合交给容器进行管理的bean

      • 表现层对象
      • 业务层对象
      • 数据层对象
      • 工具对象
    • 不适合交给容器进行管理的bean

      • 封装实体的域对象
2. bean的实例化
  1. 构造方法

    bean本质上就是对象,创建bean对象使用构造方法

    注意:如果无参构造方法不存在将抛出异常BeanCreationException

  2. 静态工厂

    • 通过工厂创建对象

      public class UserDaoFactory {
      public static UserDao getUserDao(){
      return new UserDaoImpl();
      }
      }
    • 配置bean

      <bean id="userDao" class="com.spring_ioc.factory.UserDaoFactory" factory-method="getUserDao"/>
  3. 实例工厂

    • 配置工厂bean

      <bean id="UserDaoFactory" class="com.spring_ioc.factory.UserDaoFactory"/>
    • 通过工厂创建对象

      public class UserDaoFactory {
      public UserDao getUserDao(){
      return new UserDaoImpl();
      }
      }
    • 配置bean

      <bean id="userDao" factory-bean="UserDaoFactory" factory-method="getUserDao"/>
  4. FactoryBean

    • 通过FactoryBean创建对象

      public class UserDaoFactoryBean implements FactoryBean<UserDao> {
      //代替原始实例工厂创建对象的方法
      @Override
      public UserDao getObject() throws Exception {
      return new UserDaoImpl();
      }
      //获取bean的实例对象类型
      @Override
      public Class<?> getObjectType() {
      return UserDao.class;
      }
      //设置bean实例的是否为非单例
      @Override
      public boolean isSingleton() {
      //false:表示单例
      //true:表示非单例
      return false;
      }
      }
    • 配置bean

      <bean id="UserDao" class="com.spring_ioc.factory.UserDaoFactoryBean"/>
3. bean的生命周期
  • 初始化容器

    • 创建对象 ( 内存分配 )

    • 执行构造方法

    • 执行属性注入(set 操作)

    • 执行bean初始化方法

      • xml配置

        image-20230310160847579

      • 接口配置

        image-20230310160943425

  • 使用 bean

    • 执行业务操作
  • 关闭/销毁容器

    image-20230310161551238

    • 执行bean销毁方法

2.容器

image-20230311112755257

  1. 创建容器

    image-20230311111625077

  2. 获取bean

    image-20230311111716974

3.依赖注入

1.普通方法(setter注入)
  1. 引用类型

    image-20230310162533314

  2. 简单类型

    image-20230310163447372

2.构造方法(构造器注入)
  1. 引用类型

    image-20230310164533281

  2. 简单类型

    image-20230310164615094

  3. 参数适配

    image-20230310164717598

3.依赖方式的选择
- 强制依赖使用构造器进行,使用setter注入有概率不进行注入导致null对象出现
- 可选依赖使用setter注入进行,灵活性强
- Spring框架倡导使用构造器,第三方框架内部大多数采用构造器注入的形式进行数据初始化,相对严谨
- 如果有必要可以两者同时使用,使用构造器注入完成强制依赖的注入,使用setter注入完成可选依赖的注入
- 实际开发过程中还要根据实际情况分析,如果受控对象没有提供setter方法就必须使用构造器注入
- 自己开发的模块推荐使用setter注入
4.自动装配

IoC容器根据bean所依赖的资源在容器中自动查找并注入到bean中的过程称为自动装配

  1. 按类型装配

    image-20230311094356028

  2. 按名称装配

  3. 按构造器装配

  4. 不使用自动装配

自动装配特征:

- 1.自动装配用于引用类型依赖注入,不能对简单类型进行操作
- 2. 使用按类型装配时(byType)必须保障容器中相同类型的bean唯一,推荐使用
- 3. 使用按名称装配时(byName)必须保障容器中具有指定名称的bean,因变量名与配置耦合,不推荐使用
- 4. 自动装配优先级低于setter注入与构造器注入,同时出现时自动装配配置失效

4.集合注入

  1. 定义集合

    private int[] array;
    private List<String> list;
    private Set<String> set;
    private Map<String, String> map;
    private Properties properties;
  2. 设置setter

    public void setArray(int[] array) {
    this.array = array;
    }
    public void setList(List<String> list) {
    this.list = list;
    }
    public void setSet(Set<String> set) {
    this.set = set;
    }
    public void setMap(Map<String, String> map) {
    this.map = map;
    }
    public void setProperties(Properties properties) {
    this.properties = properties;
    }
  3. 配置集合

    <bean id="bookDao" class="com.spring_auto.dao.impl.BookDaoImpl">
    <!-- 数组注入-->
    <property name="array">
    <array>
    <value>1</value>
    <value>2</value>
    </array>
    </property>
    <!-- list集合注入-->
    <property name="list">
    <list>
    <value>list1</value>
    <value>list2</value>
    </list>
    </property>
    <!-- set集合注入-->
    <property name="set">
    <set>
    <value>set1</value>
    <value>set2</value>
    <value>set1</value>
    </set>
    </property>
    <!-- map集合注入-->
    <property name="map">
    <map>
    <entry key="key1" value="map1"/>
    <entry key="key2" value="map2"/>
    </map>
    </property>
    <!-- properties注入-->
    <property name="properties">
    <props>
    <prop key="key1">pro1</prop>
    <prop key="key2">pro2</prop>
    </props>
    </property>
    </bean>

5.加载properties文件

image-20230311110847553

<?xml version="1.0" encoding="UTF-8"?>
<!-- 开启context命名空间-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
">
<!--使用context空间加载properties-->
<context:property-placeholder location="classpath*:*.properties" system-properties-mode="NEVER"/>
<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
<!-- 使用属性占位符读取properties文件中的属性-->
<property name="driverClassName" value="${driverClassName}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
<property name="initialSize" value="${initialSize}"/>
<property name="minIdle" value="${minIdle}"/>
<property name="maxActive" value="${maxActive}"/>
<property name="maxWait" value="${maxWait}"/>
</bean>
</beans>

6.注解开发

1. bean

image-20230311115151342

注意:spring提供@Component注解的三个衍生注解

@Controller:用于表现层bean定义
@Service:用于业务层bean定义
@Repository:用于数据层bean的定义
2. bean的管理
  1. bean的作用范围

    默认值singleton(单例),可选值prototype(非单例)

    image-20230311140229846

  2. bean的生命周期

    image-20230311140249899

3. 配置类

image-20230311135335217

//创建容器,并读取配置类
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
4. 依赖注入(自动装配)
  1. 引用类型

    image-20230311141033548

    注意:如果想加载指定的bean,可以使用以下方法

    image-20230311141121711

  2. 简单类型

    image-20230311141540612

5.加载properties文件

image-20230311142041611

7.配置文件开发与注解开发的对比

image-20230311144449139

五、Spring整合


1. 整合MyBatis

  1. 引入相应坐标

    <dependencies>
    <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.10.RELEASE</version>
    </dependency>
    <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.32</version>
    </dependency>
    <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.10</version>
    </dependency>
    <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.5</version>
    </dependency>
    <!-- spring操作jdbc-->
    <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.2.10.RELEASE</version>
    </dependency>
    <!-- spring整合mybatis-->
    <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>1.3.0</version>
    </dependency>
    </dependencies>
  2. 配置Druid.properties

    #key=value
    driverClassName=com.mysql.jdbc.Driver
    url=jdbc:mysql://root@localhost:3306/spring_db?rewriteBatchedStatements=true
    username=root
    password=123456
    #initial connection Size
    initialSize=10
    #min idle connecton size
    minIdle=5
    #max active connection size
    maxActive=20
    #max wait time (5000 mil seconds)
    maxWait=5000
  3. 配置JdbcByDruidConfig

    /**
    * @Author: XIYAN
    * @Date: 2023/3/11 16:25
    * @注释:Spring整合JdbcByDruid
    */
    public class JdbcByDruidConfig {
    //注册驱动
    @Value("${driverClassName}")
    private String driver;
    //数据库连接源
    @Value("${url}")
    private String url;
    //用户名
    @Value("${username}")
    private String username;
    //密码
    @Value("${password}")
    private String password;
    //初始连接大小
    @Value("${initialSize}")
    private int initialSize;
    //最小空闲连接大小
    @Value("${minIdle}")
    private int minIdle;
    //最大活动连接大小
    @Value("${maxActive}")
    private int maxActive;
    //最长等待时间
    @Value("${maxWait}")
    private int maxWait;
    /**
    * 初始化jdbcByDruid数据源连接池
    *
    * @return 返回初始化后的DruidDataSource对象
    */
    @Bean
    public DataSource druidDataSource() {
    DruidDataSource druidDataSource = new DruidDataSource();
    druidDataSource.setDriverClassName(driver);
    druidDataSource.setUrl(url);
    druidDataSource.setUsername(username);
    druidDataSource.setPassword(password);
    druidDataSource.setInitialSize(initialSize);
    druidDataSource.setMinIdle(minIdle);
    druidDataSource.setMaxActive(maxActive);
    druidDataSource.setMaxWait(maxWait);
    return druidDataSource;
    }
    }
  4. 配置MyBatisConfig

    /**
    * @Author: XIYAN
    * @Date: 2023/3/11 16:28
    * @注释:Spring整合MyBatis
    */
    public class MyBatisConfig {
    /**
    * 初始化SqlSessionFactory并设置相关参数
    *
    * @param jdbcByDruidConfig 传入jdbcByDruid的数据库连接池对象
    * @return 返回初始化后的SqlSession对象
    */
    @Bean
    public SqlSessionFactoryBean sqlSessionFactory(JdbcByDruidConfig jdbcByDruidConfig) {
    //创建SqlSessionFactoryBean对象
    SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
    //设置类型别名的包路径
    sqlSessionFactoryBean.setTypeAliasesPackage("com.spring_mybatis.model");
    //设置数据源
    sqlSessionFactoryBean.setDataSource(jdbcByDruidConfig.druidDataSource());
    return sqlSessionFactoryBean;
    }
    /**
    * 设置Mapper自动代理的映射文件
    *
    * @return 返回初始化后的Mapper自动代理映射对象
    */
    @Bean
    public MapperScannerConfigurer mapperScannerConfigurer() {
    //创建mapper自动代理对象
    MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
    //设置包扫描路径
    mapperScannerConfigurer.setBasePackage("com.spring_mybatis.dao");
    return mapperScannerConfigurer;
    }
    }
  5. 配置SpringConfig

    /**
    * @Author: XIYAN
    * @Date: 2023/3/11 16:12
    * @注释:Spring配置
    */
    @Configuration
    @ComponentScan("com.spring_mybatis")
    @PropertySource("classpath:druid.properties")
    @Import({JdbcByDruidConfig.class, MyBatisConfig.class})
    public class SpringConfig {
    }
  6. 测试

    //获取Spring配置信息
    ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
    //获取bean
    AccountService accountService = applicationContext.getBean(AccountService.class);
    System.out.println(accountService.findAll());

2.整合Junit

  1. 引入相应坐标

    <dependencies>
    <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.10.RELEASE</version>
    </dependency>
    <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    <scope>test</scope>
    </dependency>
    <!-- spring整合junit-->
    <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.2.10.RELEASE</version>
    </dependency>
    </dependencies>
  2. 配置测试类

    //标记该类为spring的类运行器
    @RunWith(SpringJUnit4ClassRunner.class)
    //载入spring的配置信息
    @ContextConfiguration(classes = SpringConfig.class)
  3. 测试

    public class AccountServiceTest {
    @Autowired
    private AccountService accountService = new AccounServiceImpl();
    @Test
    public void testFind() {
    System.out.println(accountService.findAll());
    }
    }

六、通知(AOP)


AOP(Aspect Oriented programming) 面向切面编程,一种编程范式,指导开发者如何组织程序结构

作用:在不惊动原始设计的基础上为其进行功能增强

Spring理念:无入侵式/无侵入式 Spring的本质:代理模式

1. 核心概念

  • 连接点(JoinPoint):程序执行过程中的任意位置,粒度为执行方法、抛出异常、设置变量等

    • 在SpringAOP中,理解为方法的执行
  • 切入点(Pointcut):匹配连接点的式子

    • 在SpringAOP中,一个切入点可以描述一个具体方法,也可也匹配多个方法

      • 一个具体的方法:如com.itheima.dao包下的BookDao接口中的无形参无返回值的save方法
      • 匹配多个方法:所有的save方法,所有的get开头的方法,所有以Dao结尾的接口中的任意方法,所有带有一个参数的方法

      注意:连接点范围要比切入点范围大,是切入点的方法也一定是连接点,但是是连接点的方法就不一 定要被增强,所以可能不是切入点。

  • 通知(Advice):在切入点处执行的操作,也就是共性功能

    • 在SpringAOP中,功能最终以方法的形式呈现
  • 通知类:定义通知的类

  • 切面(Aspect):描述通知与切入点的对应关系。

  • 目标对象(Target):原始功能去掉共性功能对应的类产生的对象,这种对象是无法直接完成最终 工作的

  • 代理(Proxy):目标对象无法直接完成工作,需要对其进行功能回填,通过原始对象的代理对象实 现

2. AOP入门

  1. 导入相应坐标

    <dependencies>
    <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.10.RELEASE</version>
    </dependency>
    <!-- aop切面-->
    <dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.4</version>
    </dependency>
    </dependencies>
  2. 定义AOP

    //声明该类是一个bean
    @Component
    //声明当前类为AOP切面类
    @Aspect
    public class MyAdvice {
    //定义切入点
    @Pointcut("execution(void com.spring_aop.dao.BookDao.update())")
    private void ad(){}
    //绑定当前通知方法与切入点之间的绑定关系(在原始切入点方法前运行)
    @Before("ad()")
    public void method(){
    System.out.println(System.currentTimeMillis());
    }
    }
  3. 配置AOP

    @Configuration
    @ComponentScan("com.spring_aop")
    //使用注解开发AOP
    @EnableAspectJAutoProxy
    public class SpringConfig {
    }

3. AOP的工作流程

  1. Spring容器启动
  2. 读取所有切面配置中的切入点
  3. 初始化bean

注意第1步在容器启动的时候,bean对象还没有被创建成功

- 匹配失败,创建原始对象
匹配失败说明不需要增强,直接调用原始对象的方法即可。
- 匹配成功,创建原始对象(目标对象)的代理对象
匹配成功说明需要对其进行增强
# 对哪个类做增强,这个类对应的对象就叫做目标对象
# 因为要对目标对象进行功能增强,而采用的技术是动态代理,所以会为其创建一个代理对象
# 最终运行的是代理对象的方法,在该方法中会对原始方法进行功能增强
  1. 获取bean执行方法
    • 获取的bean是原始对象时,调用方法并执行,完成操作 获取的bean是代理对象时,根据代
    • 理对象的运行模式运行原始方法与增强的内容,完成操作

4. AOP切入点表达式

切入点表达式标准格式:动作关键字(访问修饰符[可省略] 返回值 包名.类/接口名.方法名(参数) 异常名[可省略])

​ 切入点:要进行增强的方法 切入点表达式:要进行增强的方法的描述方式

image-20230313103146774

通配符:

image-20230313103628056

书写技巧:

- 所有代码按照标准规范开发,否则以下技巧全部失效
- 描述切入点通常描述接口,而不描述实现类,如果描述到实现类,就出现紧耦合了
- 访问控制修饰符针对接口开发均采用public描述(可省略访问控制修饰符描述)
- 返回值类型对于增删改类使用精准类型加速匹配,对于查询类使用\*通配快速描述
- 包名书写尽量不使用..匹配,效率过低,常用\*做单个包描述匹配,或精准匹配
- 接口名/类名书写名称与模块相关的采用\*匹配,例如UserService书写成\*Service,绑定业务
- 层接口名 方法名书写以动词进行精准匹配,名词采用匹配,例如getById书写getBy,selectAll书写成 selectAll
- 参数规则较为复杂,根据业务方法灵活调整
- 通常不使用异常作为匹配规则

5. AOP通知类型

AOP通知描述了抽取的共性功能,根据共性功能抽取的位置不同,最终运行代码时要将其加入到合理的位置

image-20230313141139952

名称 说明
前置通知[@Before] 追加功能到方法执行前,类似于在代码1或者代码2添加内容
后置通知[@After] 追加功能到方法执行后,不管方法执行的过程中有没有抛出异常都会执行,类似于在代 码5添加内容
环绕通知[@Around] 环绕通知功能比较强大,它可以追加功能到方法执行的前后,这也是比较常用的方式, 它可以实现其他四种通知类型的功能
返回后通知[@AfterReturning] 追加功能到方法执行后,只有方法正常执行结束后才进行,类似于在代码3添加内容, 如果方法执行抛出异常,返回后通知将不会被添加
抛出异常后通知[@AfterThrowing] 追加功能到方法抛出异常后,只有方法执行出异常才进行,类似于在代码4添加内 容,只有方法抛出异常后才会被添加

环绕通知:

  • 环绕通知依赖形参ProceedingJoinPoint才能实现对原始方法的调用
  • 环绕通知可以隔离原始方法的调用执行
  • 环绕通知返回值设置为Object类型
  • 环绕通知中可以对原始方法调用过程中出现的异常进行处理
//声明该类是一个bean
@Component
//声明当前类为AOP切面类
@Aspect
public class MyAdvice {
//定义切入点
@Pointcut("execution(void *..*Dao+.*(..))")
private void ad() {
}
//绑定当前通知方法与切入点之间的绑定关系(在原始切入点方法前运行)
@Around("ad()")
public Object arund(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
//获取当前目标对象的签名信息
Signature signature = proceedingJoinPoint.getSignature();
//通过签名信息获取类型名称(接口名称)
String typeName = signature.getDeclaringTypeName();
//通过签名信息获取方法名称
String name = signature.getName();
System.out.println(System.currentTimeMillis());
//表示对原始方法的调用
Object proceed = proceedingJoinPoint.proceed();
System.out.println(System.currentTimeMillis());
//返回原始方法的值
return proceed;
}
}

注意:

  1. 环绕通知必须依赖形参ProceedingJoinPoint才能实现对原始方法的调用,进而实现原始方法调用前后同时添加通知

  2. 通知中如果未使用ProceedingJoinPoint对原始方法进行调用将跳过原始方法的执行

  3. 对原始方法的调用可以不接收返回值,通知方法设置成void即可,如果接收返回值,最好设定为 Object类型

  4. 原始方法的返回值如果是void类型,通知方法的返回值类型可以设置成void,也可以设置Object

  5. 由于无法预知原始方法运行后是否会抛出异常,因此环绕通知方法必须要处理Throwable异常

6. AOP获取数据

6-1. 获取切入点方法参数
  • JoinPoint:适用于前置、后置、返回后、抛出异常后通知
  • ProceedingJoinPoint:适用于环绕通知
@Before("ad()")
public void before(JoinPoint joinPoint) {
//获取目标对象的参数
Object[] args = joinPoint.getArgs();
}
@After("ad()")
public void after(JoinPoint joinPoint) {
//获取目标对象的参数
Object[] args = joinPoint.getArgs();
}
@Around("ad()")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
//获取目标对象的参数
Object[] args = proceedingJoinPoint.getArgs();
Object proceed = proceedingJoinPoint.proceed();
return proceed;
}
6-2. 获取切入点方法的返回值
  • 返回后通知
  • 环绕通知
@Around("ad()")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
//获取目标对象的返回值
Object proceed = proceedingJoinPoint.proceed();
return proceed;
}
//如果返回后通知存在返回值,则将返回值传入形参o中
@AfterReturning(value = "ad()", returning = "o")
public void afterReturning(Object o) {
}

注意:在返回后通知里如果需要同时获取参数和返回值,JoinPoint或ProceedingJoinPoint形参必须写在第一位

6-3. 获取切入点方法运行异常信息
  • 抛出异常后通知
  • 环绕通知
@Around("ad()")
public Object around(ProceedingJoinPoint proceedingJoinPoint) {
//获取异常
Object proceed = null;
try {
proceed = proceedingJoinPoint.proceed();
} catch (Throwable e) {
throw new RuntimeException(e);
}
return proceed;
}
//在抛出异常后通知执行时,则将异常信息传入形参throwable中
@AfterThrowing(value = "ad()",throwing = "throwable")
public void afterThrowing(Throwable throwable) {
}

七、Spring事务(PlatformTransactionManager)


事务作用:在数据层保障一系列的数据库操作同成功同失败

Spring事务作用:在数据层或业务层保障一系列的数据库操作同成功同失败

开启spring事务的步骤:

  1. 在业务层上添加Spring事务管理

    @Service
    public class AccountServiceImpl implements AccountService {
    @Autowired
    private AccountDao accountDao;
    //使用spring事务
    @Transactional
    public void transfer(String out,String in ,Double money) {
    accountDao.outMoney(out,money);
    int i = 1/0;
    accountDao.inMoney(in,money);
    }
    }

    注意:- spring注解式事务通常添加在业务层接口中而不会添加到业务层实现类中,降低耦合

    ​ - 注解式事务可以添加到业务方法上表示当前方法开启事务,也可以添加到接口上表示当 前接口所有方法开启事务

  2. 设置spring事务管理器

    public class JdbcByDruidConfig {
    /**
    * 设置Spring事务管理器
    *
    * @param dataSource 传入数据库连接池对象
    * @return 返回配置好的事务处理器
    */
    @Bean
    public PlatformTransactionManager platformTransactionManager(DataSource dataSource) {
    DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
    dataSourceTransactionManager.setDataSource(dataSource);
    return dataSourceTransactionManager;
    }
    }

    注意:- 事务管理器要根据实现技术进行选择

    ​ - MyBaits框架使用的是JDBC事务

  3. 开启注解式事务驱动

    @Configuration
    @ComponentScan("com.spring_mybatis")
    //开启注解式事务驱动
    @EnableTransactionManagement
    public class SpringConfig {
    }

1. Spring事务角色

image-20230314093830495

事务管理员:发起事务方,在Spring中通常指代业务层开启事务的方法

事务协调员:加入事务方,在Spring中通常指代数据层方法,也可以是业务层方法

2. Spring事务的属性

image-20230314094230744

3. Spring事务的传播行为

事务协调员对事务管理员所携带事务的处理态度。

例子:

@Service
public class LogServiceImpl implements LogService {
@Autowired
private LogDao logDao;
//propagation设置事务属性:传播行为设置为当前操作需要新事务 @Transactional(propagation = Propagation.REQUIRES_NEW)
public void log(String out,String in,Double money ) {
logDao.log("转账操作由"+out+"到"+in+",金额:"+money);
}
}

事务传播行为的可选值:

image-20230314095911355

所有的笔记来源于:黑马程序员的个人空间_哔哩哔哩_bilibili

本文作者:顔をして

本文链接:https://www.cnblogs.com/ynxiyan/p/17204045.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   顔をして  阅读(17)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起
  1. 1 I Really Want to Stay at Your House Samuel Kim,Lorien
  2. 2 将月亮藏进躯体 豆芽鱼(庄东茹)
  3. 3 辞九门回忆 解忧草,冰幽
  4. 4 I'M Not Girl 伊晗
I'M Not Girl - 伊晗
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

作词 : 伊晗

作曲 : 伊晗

编曲:Fsy小诺

制作人:李晨

和声编写:卢晓武

和声配唱:伊晗

录音师:箱子君

混音师:卢晓武

母带工程师:Clarence

制作公司:Clever Music

海报设计:牛牛

文案:翠翠

出品人:王婷婷

昨晚的啤酒续杯

昨晚的啤酒续杯

跟黑夜默视宿醉

感官世界永远

太嚣张永持领导地位

没想跟世界敌对

却上身太多误会

情绪总是感性化

理性不受控制

太绝对 太狼狈

为什么不给我次解释的机会

当思绪被放大

当梦想被撕碎

当一切都在 say no

I&apos;m not girl not girl not girl not girl

我却选择了沉默

我却选择了沉默

路人甲乙丙在发言

路人甲乙丙在发言

不过是新鲜感

Why not all right

Why not all right

I&apos;m not girl not girl not girl not girl

I&apos;m not girl not girl not girl not girl

这次我不再沉默

这次我不再沉默

我不强求你的青睐

我不强求你的青睐

如果你不喜欢

Goodbye again oh oh

I&apos;m a queen

昨晚的啤酒续杯

昨晚的啤酒续杯

跟黑夜默视宿醉

感官世界永远

太嚣张永持领导地位

没想跟世界敌对

却上身太多误会

情绪总是感性化

理性不受控制

太绝对 太狼狈

为什么不给我次解释的机会

当思绪被放大

当梦想被撕碎

当一切都在 say no

I&apos;m not girl not girl not girl not girl

我却选择了沉默

我却选择了沉默

路人甲乙丙在发言

路人甲乙丙在发言

不过是新鲜感

Why not all right

I&apos;m not girl not girl not girl not girl

I&apos;m not girl not girl not girl not girl

这次我不再沉默

我不强求你的青睐

我不强求你的青睐

如果你不喜欢

Goodbye again oh oh

I&apos;m a queen

I&apos;m not girl not girl not girl not girl

I&apos;m not girl not girl not girl not girl

我却选择了沉默

路人甲乙丙在发言

不过是新鲜感

Why not all right

I&apos;m not girl not girl not girl not girl

I&apos;m not girl not girl not girl not girl

这次我不再沉默

我不强求你的青睐

我不强求你的青睐

如果你不喜欢

Goodbye again oh oh

I&apos;m a queen