spring框架学习记录(2)

文章目录

    • 注解开发
      • bean相关
        • 注解开发定义bean
        • 纯注解开发
        • 纯注解开发中bean的管理
      • 依赖注入相关
        • 依赖注入
        • 第三方bean管理
        • 第三方bean依赖注入
    • AOP(Aspect Oriented Programming)面向切面编程
      • AOP简介
      • AOP核心概念
      • AOP工作流程
      • AOP切入点表达式
      • 通知类型
      • AOP通知获取数据

注解开发

bean相关

注解开发定义bean
  • 使用@Component定义bean
@Component("bookDao")
public class BookDaoImpl implements BookDao {
}
@Component
public class BookServiceImpl implements BookService {
}
  • 核心配置文件中通过组件扫描加载bean
<context:component-scan base-package="com.itheima"/>
  • String提供@Component注解的三个衍生注解
    • @Controller:用于表现层bean定义
    • @Service:用于业务层bean定义
    • @Repository:用于数据层bean定义
@Repository("bookDao") // 数据层的bean
public class BookDaoImpl implements BookDao {
}
@Service // 业务层的bean
public class BookServiceImpl implements BookService {
}
纯注解开发
  • 在纯注解开发中,使用java类代替spring核心配置文件

    • 核心配置文件如下
    <?xml version="1.0" encoding="UTF-8"?>
    <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">
    
    <!--    核心配置文件中通过组件扫描加载bean-->
        <context:component-scan base-package="com.itheima"/>
    
    </beans>
    
    • java类如下
    package com.itheima.config;
    
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    
    //声明当前类为Spring配置类
    @Configuration
    //设置bean扫描路径,多个路径书写为字符串数组格式
    @ComponentScan({"com.itheima.service","com.itheima.dao"})
    public class SpringConfig {
    }
    
    

其中,java类中的@Configuration完全代替了原来核心配置文件的结构

  • @Configuration注解用于设定当前类为配置类
  • @ConponentScan注解用于设定扫描路径,此注解只能添加一次,多个数据用数组格式
//设置bean扫描路径,多个路径书写为字符串数组格式
@ComponentScan({"com.itheima.service","com.itheima.dao"})
  • 读取spring核心配置文件初始化容器对象切换为读取java配置类初始化容器对象
// 加载配置文件初始化容器
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
// 加载配置类初始化容器
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
纯注解开发中bean的管理
  • bean的作用范围

    • 使用@Scope定义bean作用范围
    //@Scope设置bean的作用范围
    @Scope("singleton")
    public class BookDaoImpl implements BookDao {
    }
    
  • bean的生命周期

    • 使用@PostConstruct、@PreDestroy定义bean生命周期
    @Repository
    //@Scope设置bean的作用范围
    @Scope("singleton")
    public class BookDaoImpl implements BookDao {
    
        public void save() {
            System.out.println("book dao save ...");
        }
        //@PostConstruct设置bean的初始化方法
        @PostConstruct
        public void init() {
            System.out.println("init ...");
        }
        //@PreDestroy设置bean的销毁方法
        @PreDestroy
        public void destroy() {
            System.out.println("destroy ...");
        }
    
    }
    

依赖注入相关

依赖注入
  • 使用@Autowired注解开启自动装配模式(按类型装配)
@Service
public class BookServiceImpl implements BookService {
    //@Autowired:注入引用类型,自动装配模式,默认按类型装配
    @Autowired
    private BookDao bookDao;

    public void save() {
        System.out.println("book service save ...");
        bookDao.save();
    }
}

注意:自动装配基于反射设计创建对象并暴力反射对应属性为私有属性初始化数据,因此无需提供setter方法

注意:自动装配建议使用无参构造方法创建对象(默认),如果不提供对应构造方法,请提供唯一的构造方法

  • 使用@Qualifier注解开启指定名称装配bean
@Service
public class BookServiceImpl implements BookService {
    //@Autowired:注入引用类型,自动装配模式,默认按类型装配
    @Autowired
    //@Qualifier:自动装配bean时按bean名称装配
    @Qualifier("bookDao")
    private BookDao bookDao;
}

注意:@Qualifier注解无法单独使用,必须配合@Autowired注解使用

  • 对于简单类型注入,使用@Value进行装配
@Repository("bookDao")
public class BookDaoImpl implements BookDao {
    //@Value:注入简单类型(无需提供set方法)
    @Value("${name}") // name来自于配置文件property
    private String name;

    public void save() {
        System.out.println("book dao save ..." + name);
    }
}
  • 使用@PropertySource注解加载properties文件
@Configuration
@ComponentScan("com.itheima")
//@PropertySource加载properties配置文件
@PropertySource({"jdbc.properties"})
public class SpringConfig {
}

注意:路径仅支持单一文件配置,多文件要使用数组格式配置,不允许使用通配符*

第三方bean管理
  • 使用@Bean配置第三方bean
@Configuration
public class SpringConfig {
	@Bean
    public DataSource dataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(userName);
        ds.setPassword(password);
        return ds;
    }
}
  • 使用独立的配置类管理第三方bean
@Configuration
public class JdbcConfig {
	@Bean
    public DataSource dataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(userName);
        ds.setPassword(password);
        return ds;
    }
}
  • 将独立的配置类加入核心配置

    • 方式一:导入式(推荐使用)
    public class JdbcConfig {
    	@Bean
        public DataSource dataSource(){
            DruidDataSource ds = new DruidDataSource();
            // 相关配置
            return ds;
        }
    }
    

    使用@Import注解手动加入配置类到核心配置,此注解只能添加一次,多个数据请用数组格式

    @Configuration
    @Import({JdbcConfig.class})
    public class SpringConfig {
    }
    
    • 方式二:扫描式**(不推荐使用,隐藏性强,不知道在config中导入过哪些配置类)**
    @Configuration
    public class JdbcConfig {
    	@Bean
        public DataSource dataSource(){
            DruidDataSource ds = new DruidDataSource();
            // 相关配置
            return ds;
        }
    }
    

    使用@ComponentScan注解扫描配置类所在的包,加载对应的配置类信息

    @Configuration
    @ComponentScan({"com.itheima.config", "com.itheima.service", "com.itheima.dao"})
    public class SpringConfig {
    }
    
第三方bean依赖注入
  • 简单类型依赖注入
public class JdbcConfig {
    //1.定义一个方法获得要管理的对象
    @Value("com.mysql.jdbc.Driver")
    private String driver;
    @Value("jdbc:mysql://localhost:3306/spring_db")
    private String url;
    @Value("root")
    private String userName;
    @Value("root")
    private String password;
    //2.添加@Bean,表示当前方法的返回值是一个bean
    //@Bean修饰的方法,形参根据类型自动装配
    @Bean
    public DataSource dataSource(BookDao bookDao){
        System.out.println(bookDao);
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(userName);
        ds.setPassword(password);
        return ds;
    }
}
  • 引用类型依赖注入
@Bean
    public DataSource dataSource(BookDao bookDao){
        System.out.println(bookDao);
        DruidDataSource ds = new DruidDataSource();
        // 属性设置
        return ds;
    }

引用类型注入只需要为bean定义方法设置形参即可,容器会根据类型自动装配对象

AOP(Aspect Oriented Programming)面向切面编程

AOP简介

  • AOP:面向切面编程,一种编程范式,指导开发者如何组织程序结构

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

  • spring理念:无入侵式编程

AOP核心概念

  • 连接点:程序执行过程中的任意位置,粒度为执行方法、抛出异常、设置变量等
    • 在SpringAOP中,理解为方法的执行
  • 切入点:匹配连接点的式子
    • 在SpringAOP中,一个切入点可以只描述一个具体方法,也可以匹配多个方法
  • 通知:在切入点处执行的操作,也就是共性功能
    • 在SpringAOP中,功能最终以方法的形式呈现
  • 通知类:定义通知的类
  • 切面:描述通知与切入点的对应关系

在这里插入图片描述

AOP工作流程

1.Spring容器启动

2.读取所有切面配置中的切入点

//通知类必须配置成Spring管理的bean
@Component
//设置当前类为切面类类
@Aspect
public class MyAdvice {
    // 设置切入点,要求配置在方法上方
    @Pointcut("execution(void com.itheima.dao.BookDao.update())")
    private void ptx(){}
    
    @Pointcut("execution(void com.itheima.dao.BookDao.update())")
    private void pt(){}
    
    // 设置在切入点pt()的前面运行当前操作(前置通知)
    @Before("pt()")
    public void method(){
        System.out.println(System.currentTimeMillis());
    }
}

3.初始化bean,判定bean对应的类中的方法是否匹配到任意切入点

  • 匹配失败,则创建对象
  • 匹配成功,则创建原始对象(目标对象)的代理对象

注:只要有一个切入点匹配成功,就算匹配上了

4.获取bean执行方法

  • 获取bean,调用方法并执行,完成操作
  • 获取的bean是代理对象时,根据代理对象的运行模式运行原始方法与增强的内容,完成操作

AOP切入点表达式

切入点:要进行增强的方法

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

  • 方式一:执行接口中的无参数方法
  • 方式二:执行实现类中的无参数方法

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

execution(public User com.itheima.service.UserService.findById(int))
  • 动作关键字:描述切入点的行为动作,例如execution表示执行到指定切入点
  • 访问修饰符:public、private等,可省略
  • 返回值
  • 包名
  • 类/接口名
  • 方法名
  • 参数
  • 异常名:方法定义中抛出指定异常,可以省略

可以使用通配符描述切入点,实现快速描述

  • *****:单个独立的任意符号,可以独立出现,也可以作为前缀或者后缀的匹配符出现
execution(public * com.itheima.*.UserService.find*(*))

匹配com.itheima包下的任意包中的UserService类或接口中所有find开头的带有一个参数的方法

  • :多个连续地任意符号,可以对出现,常用于化简包名与参数的书写
execution(public User com..UserService.findById(..))

匹配com包下的任意包中的UserService类或接口中所有名称为findById的方法

  • +:专用于匹配子类类型
execution(* *..*Service+.*(..))

书写技巧

  • 描述切入点通常描述接口,而不描述实现类,可以降低耦合度
  • 访问控制修饰符针对接口开发均采用public描述(可省略public)
  • 返回值类型对于增删改类使用精准类型加速匹配,对于查询类使用*通配快速描述
  • 包名书写尽量不使用…匹配,效率过低,常用*做单个包描述匹配,或精准匹配
  • 接口名/类名书写名称与模块相关的采用*****匹配,例如UserService书写成:*Service,绑定业务层接口名
  • 方法名书写以动词进行精准匹配,名词采用*****匹配,例如getById书写成getBy*,selectAll书写成selectAll
  • 通常不使用异常作为匹配规则

通知类型

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

  • AOP通知共分为5种类型

    • 前置通知

    • 后置通知

    • 环绕通知(常用)

      • 名称:@Around
      • 类型:方法注解
      • 位置:通知方法定义上方
      • 作用:设置当前通知方法与切入点之间的绑定关系,当前通知方法在原始切入点方法前后运行
      • 范例
      @Around("pt()")
      public Object around(ProceedingJoinPoint pjp) throws Throwable {
          System.out.println("around before advice ...");
          Object ret = pjp.proceed(); // 表示对原始操作的调用
          System.out.println("around after advice ...");
          return ret;
      }
      
    • 返回后通知(不常用)

    • 抛出异常后通知(不常用)

@Around注意事项

  • 环绕通知必须依赖形参ProceedingJoinPoint才能实现对原始方法的调用,进而实现原始方法调用前后同时添加通知
  • 通知中如果未使用ProceedingJoinPoint对原始方法进行调用,将跳过原始方法的执行
  • 对原始方法的调用可以不接收返回值,通知方法设置成void即可,如果接收返回值,通知方法必须设定为Object类型
  • 原始方法的返回值如果是void类型,通知方法的返回值可以设置成void,也可以设置成Object
  • 由于无法预知原始方法运行后是否会抛出异常,因此环绕通知方法必须抛出Throwable对象

AOP通知获取数据

  • 获取切入点方法的参数

    • JoinPoint:适用于前置、后置、返回后、抛出异常后通知
    @Before("pt()")
    public void before(JoinPoint jp) {
        Object[] args = jp.getArgs();
        System.out.println(Arrays.toString(args));
        System.out.println("before advice ..." );
    }
    
    • ProceedingJointPoint:适用于环绕通知
    @Around("pt()")
    public Object around(ProceedingJoinPoint pjp) {
        Object[] args = pjp.getArgs();
        System.out.println(Arrays.toString(args));
        args[0] = 666;
        Object ret = null;
        try {
            ret = pjp.proceed(args);
        } catch (Throwable t) {
            t.printStackTrace();
        }
        return ret;
    }
    

    注:ProceedingJointPoint是JointPoint的子类

  • 获取切入点方法返回值

    • 返回后通知
    • 环绕通知
  • 获取切入点方法运行异常信息

    • 抛出异常后通知
    • 环绕通知

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/593252.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Day19 代码随想录打卡|字符串篇---反转字符串II

题目&#xff08;leecode T541&#xff09;&#xff1a; 给定一个字符串 s 和一个整数 k&#xff0c;从字符串开头算起&#xff0c;每计数至 2k 个字符&#xff0c;就反转这 2k 字符中的前 k 个字符。 如果剩余字符少于 k 个&#xff0c;则将剩余字符全部反转。如果剩余字符小…

OceanBase 轻量级数仓关键技术解读

码到三十五 &#xff1a; 个人主页 为了更好地聚合和治理跨域数据&#xff0c;帮助企业用较低的成本快速聚合分析&#xff0c;快速决策&#xff0c;不断的让企业积累的数据产生价值&#xff0c;从全域海量数据抓取&#xff0c;高性能流批处理&#xff0c;元数据血缘治理等等方面…

数据分析从入门到精通 1.numpy 剑客修炼

会在某一瞬间突然明白&#xff0c;有些牢笼是自己给自己的 —— 24.5.5 一、数据分析秘笈介绍 1.什么是数据分析 是把隐藏在一些看似杂乱无章的数据背后的信息提炼出来&#xff0c;总结出所研究对象的内在规律。使得数据的价值最大化 案例&#xff1a; 分析用户的消…

Kotlin: Expecting a ‘>‘

数组值为任意类型&#xff0c;声明报错: Kotlin: Expecting a > var anyArr1: Array<Any?> arrayOf("a", "b", "c", true, 34)原因是&#xff1a; // var anyArr1: Array<Any?> arrayOf("a", "b", "c…

概念解析 | 威胁建模与DREAD评估:构建安全的系统防线

注1:本文系"概念解析"系列之一,致力于简洁清晰地解释、辨析复杂而专业的概念。本次辨析的概念是:威胁建模和DREAD模型 概念解析 | 威胁建模与DREAD评估:构建安全的系统防线 What Is Threat Modeling? Definition, Process, Examples, and Best Practices - Spic…

蓝桥杯-路径之谜

题目描述 小明冒充X星球的骑士&#xff0c;进入了一个奇怪的城堡。城堡里面什么都没有&#xff0c;只有方形石头铺成的地面。 假设城堡的地面时n*n个方格。如下图所示。 按习俗&#xff0c;骑士要从西北角走到东南角。可以横向或者纵向移动&#xff0c;但是不能斜着走&#x…

SpringBoot自定义定时任务

通常&#xff0c;在我们的项目中需要定时给前台发送一些提示性消息或者我们想要的定时信息&#xff0c;这个时候就需要使用定时任务来实现这一功能&#xff0c;实现也很简单&#xff0c;接下来具体来看看吧~ 简单定时任务 首先&#xff0c;你需要在你的启动类上加上开启定时任…

贪吃蛇(下)游戏的实现

感谢大佬的光临各位&#xff0c;希望和大家一起进步&#xff0c;望得到你的三连&#xff0c;互三支持&#xff0c;一起进步 个人主页&#xff1a;LaNzikinh-CSDN博客 文章目录 前言一.蛇和食物的打印二.游戏的运行逻辑三.结束游戏 &#xff08;善后工作&#xff09;四.游戏的测…

K8S-Dashboard安装并创建普通用户

参考&#xff1a;在centos stream 9上搭建k8s最新版本&#xff08;当前&#xff1a;v1.26.1&#xff09;集群环境 查找dashboard 对应的版本 https://github.com/kubernetes/dashboard/releases 下载 kubernetes-dashboard.yaml 使用的2.7.0 wget https://raw.githubuserconte…

mac安装虚拟机linux系统

需要下载的有&#xff1a;centos8镜像 , 虚拟器 VMware 软件包 , Termius 或者xshell 1. CentOS系统下载 linux系统一般有&#xff1a; CentOS、ubuntu、redhat&#xff0c;选择一种进行安装就可以 CentOS 2024 年开始停止维护和发布 CentOS8的下载与安装(windows下安装) 镜…

【网络安全产品】---应用防火墙(WAF)

what Web应用防火墙&#xff08;Web Application Firewall) WAF可对网站或者App的业务流量进行恶意特征识别及防护&#xff0c;在对流量清洗和过滤后&#xff0c;将正常、安全的流量返回给服务器&#xff0c;避免网站服务器被恶意入侵导致性能异常等问题&#xff0c;从而保障…

3.10设计模式——Template Method 模版方法模式(行为型)

意图 定义一个操作中的算法骨架&#xff0c;而将一些步骤延迟到子类中&#xff0c;Template Method 使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定步骤。 结构 AbstractClass&#xff08;抽象类&#xff09;定义抽象的原语操作&#xff0c;具体的子类将重定…

C++:set和map的介绍

目录 关联式容器 键值对 set介绍&#xff1a; set的模板参数列表 set的双向迭代器&#xff1a; insert的使用和set的特性&#xff1a; set的删除&#xff1a; set的find&#xff1a; lower_bound 、 upper_bound&#xff1a; multiset&#xff1a; map介绍&#xff…

C语言——指针的奥秘(1.0)

指针 一.内存和地址1.内存2.编址 二.指针变量和指针1.取地址操作符&#xff08;&&#xff09;2.指针变量和解引用操作符&#xff08;*&#xff09;1.指针变量2.拆解指针类型3.解引用操作符4.指针变量的大小 三.指针变量的类型和意义1.指针的解引用2.指针 - 整数3.void* 指针…

JVM笔记1--Java内存区域

1、运行时数据区域 从上图可以看出来&#xff0c;Java虚拟机运行时数据区域整体上可以分成5大块&#xff1a; 1.1、程序计数器 程序计数器是一块较小的内存空间。它可以看做当前线程所执行的字节码的行号指示器。在Java虚拟机的概念模型里&#xff0c;字节码解释器工作时就是…

OpenAI下周将发布ChatGPT搜索引擎,挑战谷歌搜索!

目前&#xff0c;多方位消息证实&#xff0c;OpenAI将会在5月9日上午10点公布该消息&#xff0c;大约是北京时间周五的凌晨2点。 5月3日&#xff0c;前Mila研究员、麻省理工讲师Lior S爆料&#xff0c;根据OpenAI最新的SSL证书日志显示&#xff0c;已经创建了search.chatgpt.c…

Java集合排序

1. 集合排序API 1.1 集合排序概述 集合排序是指对一个集合中的元素按照特定规则进行重新排列&#xff0c;以使得集合中的元素按照预定义的顺序呈现。 在集合排序中&#xff0c;通常需要定义一个比较规则&#xff0c;这个比较规则用于决定集合中的元素在排序后的顺序。元素之间…

KIE基于图模型的关键信息抽取源码详解

1.数据集准备 下载数据集 https://download.openmmlab.com/mmocr/data/wildreceipt.tar WildReceiptOpenset 准备好 WildReceipt。 转换 WildReceipt 成 OpenSet 格式: # 你可以运行以下命令以获取更多可用参数: # python tools/dataset_converters/kie/closeset_to_opens…

程序的机器级表示——Intel x86 汇编讲解

往期地址&#xff1a; 操作系统系列一 —— 操作系统概述操作系统系列二 —— 进程操作系统系列三 —— 编译与链接关系操作系统系列四 —— 栈与函数调用关系操作系统系列五 —— 目标文件详解操作系统系列六 —— 详细解释【静态链接】操作系统系列七 —— 装载操作系统系列…

java下乡扶贫志愿者招募管理系统springboot-vue

计算机技术在现代管理中的应用&#xff0c;使计算机成为人们应用现代技术的重要工具。能够有效的解决获取信息便捷化、全面化的问题&#xff0c;提高效率。 技术栈 前端&#xff1a;vue.jsElementUI 开发工具&#xff1a;IDEA 或者eclipse都支持 编程语言: java 框架&#xff1…