Spring Framework 学习

2023-05-16

Spring Framework 学习

  • 1. Spring 核心概念
    • 1.1 IOC、IOC容器、Bean、DI
  • 2. 入门案例
    • 2.1 IOC入门案例
    • 2.2 DI 入门案例
  • 3. IOC 基本内容
    • 3.1 bean 基础配置
    • 3.2 bean 实例化
  • 4. DI 依赖注入
    • 4.1 setter 注入
    • 4.2 构造器注入
    • 4.3 依赖自动装配
    • 4.4 集合注入
      • 4.4.1 数组
      • 4.4.2 List
      • 4.4.3 Set
      • 4.4.4 Map
      • 4.4.5 Properties 类型
  • 5. IOC/DI 配置管理第三方 bean
    • 5.1 加载 properties 文件
  • 6. 核心容器
  • 7. IOC/DI注解开发
    • 7.1 注解开发定义 bean
    • 7.2 配置文件的注解
    • 7.3 注解开发依赖注入
    • 7.4 细节
  • 8. Spring 结合 MyBatis
  • 9 AOP
    • 9.1 快速入门
    • 9.2 AOP 配置方式
      • 9.2. 1 切入点表达式
      • 9.2.2 AOP 通知类型
      • 9.2.3 通知中获取参数
    • 9.3. AOP 事务管理
      • 9.3.1 事务配置
  • n 总出错

1. Spring 核心概念

Spring 官网:https://spring.io
在这里插入图片描述

1.1 IOC、IOC容器、Bean、DI

  1. IOC(Inversion of Control)控制反转
  • 使用对象时,由主动new产生对象转换为由外部提供对象,此过程中对象创建控制权由程序转移到外部,此思想称为控制反转。
  • Spring技术对IOC思想进行了实现
    • Spring提供了一个容器,称为IOC容器,用来充当IOC思想中的"外部"
    • 被创建或被管理的对象在IOC容器中统称为Bean
  1. DI(Dependency Injection)依赖注入
  • 在容器中建立bean与bean之间的依赖关系的整个过程,称为依赖注入(eg: 如业务层需要依赖数据层,service就要和dao建立依赖关系)

小结: 这两个概念的最终目标就是:充分解耦

  • 最终结果为:使用对象时不仅可以直接从IOC容器中获取,并且获取到的bean已经绑定了所有的依赖关系.

2. 入门案例

2.1 IOC入门案例

  1. 创建Maven的java项目
  2. pom.xml添加Spring的依赖jar包
<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.12</version>
        <scope>test</scope>
    </dependency>
</dependencies>
  1. 创建BookService,BookServiceImpl,BookDao和BookDaoImpl四个类
    在这里插入图片描述
public interface BookDao {
    public void save();
}
public class BookDaoImpl implements BookDao {
    public void save() {
        System.out.println("book dao save ...");
    }
}
public interface BookService {
    public void save();
}
public class BookServiceImpl implements BookService {
    private BookDao bookDao = new BookDaoImpl(); // 这个和另一个BookDao 不是同一个
    public void save() {
        System.out.println("book service save ...");
        bookDao.save();
    }
}
  1. resources下添加spring配置文件 applicationContext.xml,并完成bean的配置
    在这里插入图片描述

注意:此时可能没有Spring Config,可能是因为没有右击模块,然后 Add Framework Support,点开后 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 http://www.springframework.org/schema/beans/spring-beans.xsd">
        <!--bean标签标示配置bean
        id属性标示给bean起名字,名字任意
        class属性表示给bean定义类型
        -->
    <bean id="bookDao" class="com.qxd.dao.impl.BookDaoImpl"/>
    <bean id="bookService" class="com.qxd.service.impl.BookServiceImpl"/>
</beans>
  1. 使用Spring提供的接口完成IOC容器的创建
  2. 从容器中获取对象进行方法调用
public class app2 {
    public static void main(String[] args) {
        // 获取 IoC 容器
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 获取 bean
        BookDao bookDao = (BookDao)ctx.getBean("bookDao");
        bookDao.save();
        System.out.println("==============");
        BookService bookService = (BookService) ctx.getBean("bookService");
        bookService.save();
    }
}

2.2 DI 入门案例

  1. 去除代码中的new
  2. 为属性提供setter方法
public class BookServiceImpl implements BookService {
    // 删除业务层中使用 new 方式创建的 Dao 对象
    private BookDao bookDao;
    public void save() {
        System.out.println("book service save ...");
        bookDao.save();
    }
    // 提供对应的 set 方法
    public void setBookDao (BookDao bookDao) {
        this.bookDao = bookDao;
    }
}
  1. 修改配置 ( applicationContext.xml ) 完成注入
	<bean id="bookDao" class="com.qxd.dao.impl.BookDaoImpl"/>
	<bean id="bookService" class="com.qxd.service.impl.BookServiceImpl">
	    <!--配置 sever 与 Dao 的关系
	    1.property 标签表示配置当前 bean 的属性
	    2.name 属性表示配置哪一个具体的属性
	        (下面 name 的名称 "bookDao" 指 BookServiceImpl 中的 BookDao 类型的属性名字
	        是为了找到 BookServiceImpl 的 setBookDao来注入的,如果变成bookDaoqxd,那 BookServiceImpl 的 set函数名字变成 setBookDaoq 就行)
	    3.ref 表示参照哪一个 bean
	        (下面 ref 中的 "bookDao" 指向 BookDao 的配置的id,也就是上一行代码里面的 id,随便取名字也成)
	    -->
	    <property name="bookDao" ref="bookDao"/>
	</bean>
</beans>
  • 小结注意:
  1. 如果一个地址 bean 了两个,id名不同,这会是两个不同的实例,一个 bean 一个(或者多个)实例。
  2. bookService 里面的 bookDao 和他引用的那个 bookDao 是同一个实例

3. IOC 基本内容

3.1 bean 基础配置

  1. 别名配置
	<!--name:为bean指定别名,别名可以有多个,使用逗号,分号,空格进行分隔,有 name 属性了,可以不要 id 属性-->
	<bean id="bookService" name="service service4 bookEbi" class="com.itheima.service.impl.BookServiceImpl">
		<!-- ref 也可以指向别名,通常指相 id  -->
		<property name="bookDao" ref="bookDao"/>
	</bean>
	<!--scope:为bean设置作用范围,可选值为单例singloton(默认),非单例prototype-->
	<bean id="bookDao" name="dao" class="com.itheima.dao.impl.BookDaoImpl" scope="prototype"/>
</beans>

3.2 bean 实例化

Spring 创建 bean 时底层使用的是类的无参构造方法。
Spring的IOC实例化对象的三种方式分别是:

  • 构造方法(常用)
  • 静态工厂(了解)
  • 实例工厂(了解)
    • FactoryBean(实用)
  1. 构造方法就是上面介绍过的
  2. 下面写一个 FactoryBean的例子
public class BookDaoFactoryBean implements FactoryBean {
    // 代替原始实例工厂中创建对象的方法
    public BookDao getObject() throws Exception {
        return new BookDaoImpl();
    }
    // 返回所创建的 Class 对象
    public Class<?> getObjectType() {
        return BookDao.class;
    }
    // 是否单例,不写这个方法就默认单例
    public boolean isSingleton() {
        return true;
    }
}
<bean id="bookDao2" class="com.qxd.factory.BookDaoFactoryBean"/>

在这里插入图片描述

4. DI 依赖注入

Spring为我们提供了两种注入方式,分别是:

  • setter注入
    • 简单类型
    • 引用类型
  • 构造器注入
    • 简单类型
    • 引用类型

4.1 setter 注入

前面已经讲过了怎么将 bookDao 注入到 bookService,如果需要注入属性,只需要把 property 中的 ref 换成 value
eg:

private int connectionNumber;
<property name="connectionNumber" value="10"/>

4.2 构造器注入

在这里插入图片描述
在这里插入图片描述

4.3 依赖自动装配

  • 按类型(常用)
  • 按名称
  • 按构造方法
  • 不启用自动装配
  1. 按照类型
    在这里插入图片描述
    只要提供了 setter 方法,配置这边只需要加上 autowire 即可。
  2. 按名称
    有的时候一个地址 bean 了多个,按照类型就找不到是匹配哪一个 bean 了,此时就需要按照名称的方法
    在这里插入图片描述
    在这里插入图片描述
  • 配置特征:
    1. 自动装配用于引用类型依赖注入,不能对简单类型(属性值这些)进行操作
    2. 使用按类型装配时(byType)必须保障容器中相同类型的bean唯一,推荐使用
    3. 使用按名称装配时(byName)必须保障容器中具有指定名称的bean,因变量名与配置耦合,不推荐使用
    4. 自动装配优先级低于setter注入与构造器注入,同时出现时自动装配配置失效

4.4 集合注入

public class BookDaoImpl implements BookDao {
	private int[] array;
	private List<String> list;
	private Set<String> set;
	private Map<String,String> map;
	private Properties properties;
	// 各种setter方法...

4.4.1 数组

<bean ...>
	<property name="array"> <!-- array 是上面的变量名-->
		<array>
			<value>100</value>
			<value>200</value>
			<value>300</value>
		</array>
	</property>
</bean>

4.4.2 List

<property name="list">
	<list>
		<value>itcast</value>
		<value>itheima</value>
		<value>boxuegu</value>
		<value>chuanzhihui</value>
	</list>
</property>

4.4.3 Set

<property name="set">
	<set>
		<value>itcast</value>
		<value>itheima</value>
		<value>boxuegu</value>
		<value>boxuegu</value>
	</set>
</property>

4.4.4 Map

<property name="map">
	<map>
		<entry key="country" value="china"/>
		<entry key="province" value="henan"/>
		<entry key="city" value="kaifeng"/>
	</map>
</property>

4.4.5 Properties 类型

<property name="properties">
	<props>
		<prop key="country">china</prop> <!-- key:"country" value:"china"-->
		<prop key="province">henan</prop>
		<prop key="city">kaifeng</prop>
	</props>
</property>

5. IOC/DI 配置管理第三方 bean

5.1 加载 properties 文件

  1. 准备properties配置文件
    resources下创建一个jdbc.properties文件,并添加对应的属性键值对
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring_db
jdbc.username=root
jdbc.password=qxd
  1. 开启context命名空间
    在applicationContext.xml中开context命名空间
    在这里插入图片描述
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd
            ">
</beans>
  1. 加载properties配置文件
    在配置文件中使用context命名空间下的标签来加载properties配置文件
<context:property-placeholder location="jdbc.properties"/>
  1. 完成属性注入
    使用${key}来读取properties配置文件中的内容并完成属性注入
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
 </bean>

注意:
在这里插入图片描述

1. 不加载系统属性
<context:property-placeholder location="jdbc.properties“ system-properties-mode="NEVER"/>
2. 加载多个 properties 文件
<context:property-placeholder location="jdbc.properties,jdbc2.properties"/>
3. 加载所有 properties 文件
<context:property-placeholder location="*.properties"/>
4. 加载 properties 的标准格式
<context:property-placeholder location="classpath:*.properties" system-properties-mode="NEVER"/>
5. 从类路径或 jar 包种搜索并加载 properties 文件
<context:property-placeholder location="classpath*:*.properties" />

最后长这个样子哦
在这里插入图片描述

6. 核心容器

  • 容器创建的两种方式
    • ClassPathXmlApplicationContext[掌握]
    • FileSystemXmlApplicationContext[知道即可]
  • 容器类层次结构
    • 只需要知晓容器的最上级的父接口为 BeanFactory即可
  • 获取Bean的三种方式
    • getBean(“名称”):需要类型转换
    • getBean(“名称”,类型.class):多了一个参数
    • getBean(类型.class):容器中不能有多个该类的bean对象 (不然此时不知道找哪一个)
  • BeanFactory
    • 使用BeanFactory创建的容器是延迟加载(了解)
    • 使用ApplicationContext创建的容器是立即加载

7. IOC/DI注解开发

7.1 注解开发定义 bean

    1. 使用 @Component 定义 bean
@Component("bookDao")
public class BookDaoImpl implements BookDao {
}
@Component // 不要括号也可以,这个时候创建 bean 要用 BookService.class
public class BookServiceImpl implements BookService {
}
    1. 核心配置文件种通过组件扫描加载 bean
<context:component-scan base-package="com.qxd"/>  <!-- 记住要配置好 contex,前文有讲怎么配置这个 -->

7.2 配置文件的注解

步骤

    1. Java类替换Spring核心配置文件
      在这里插入图片描述
    1. @Configuration注解用于设定当前类为配置类
    1. @ComponentScan注解用于设定扫描路径,此注解只能添加一次,多个数据请用数组格式

@ComponentScan({“com.itheima.service”,“com.itheima.dao”})

    1. 读取Spring核心配置文件初始化容器对象切换为读取Java配置类初始化容器对象
//加载配置文件初始化容器
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//加载配置类初始化容器
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);

7.3 注解开发依赖注入

  1. 将 @Autowired写在属性上方(此时不需要 setter 方法)
    在这里插入图片描述
  2. 若 BookDao 接口如果有多个实现类,此时可能会找不到它注入的是哪一个,解决方案如下:(通常不需要用到)
    • (1)此时@Component注解(或者另外三个)后面带名称,这样就会找到和 bookDao 名称一样的那个 bean 了
    • (2)如果不叫作 bookDao,则可以加一个按名称查找的注解 @Qualifier(“bookDao1”) ,如下:
      在这里插入图片描述
  3. 简单数据类型注入 @Value
    在这里插入图片描述
    @Value一般会被用在从properties配置文件中读取内容进行使用,详细看 细节第四点

7.4 细节

  1. 对于@Component注解,还衍生出了其他三个注解@Controller、@Service、@Repository
    在这里插入图片描述
    这三个注解和@Component注解的作用是一样的,为什么要衍生出这三个呢?
    方便我们后期在编写类的时候能很好的区分出这个类是属于表现层、业务层还是数据层的类。
  2. 要想将BookDaoImpl变成非单例,只需要在其类上添加@scope注解
    在这里插入图片描述
  3. 生命周期的注解 (在BookDaoImpl中添加两个方法,init和destroy ,方法名可以任意)
    只需要在对应的方法上添加@PostConstruct和@PreDestroy注解即可
    在这里插入图片描述
    注意: destroy只有在容器关闭的时候,才会执行,所以如下(非单例也不会执行)

如果@PostConstruct和另个标红,加入以下依赖即可(@PostConstruct和@PreDestroy注解位于 java.xml.ws.annotation包是Java EE的模块的一部分。J2EE已经在Java 9中被弃用,并且计划在Java 11中删除它。)

<dependency>
      <groupId>javax.annotation</groupId>
      <artifactId>javax.annotation-api</artifactId>
      <version>1.3.2</version>
    </dependency>
    

在这里插入图片描述
4. @Value一般会被用在从properties配置文件中读取内容进行使用

  • 步骤1:resource下准备 properties 文件 jdbc.properties (自己命名)

name=itheima888

  • 步骤2: 使用注解加载properties配置文件,在配置类上添加 @PropertySource 注解,如果有多个则 @PropertySource({“qxd1.properties”,"qxd2.properties "}) (注意: 这里不可以用通配符 * )
    在这里插入图片描述
  • 步骤3:使用@Value读取配置文件中的内容
    在这里插入图片描述
  1. 注解开发管理第三方bean
  • 方案1:(方案2更简洁)

可以在配置文件下写一个 @bean的代码,但是都放在一起不好管理,所以如下:
(1)我们新建一个JdbcConfig配置类,并把数据源配置到该类下。(扩展:下面那些String可以用细节4的配置文件搞定)
在这里插入图片描述

(2)在Spring的配置类上添加包扫描 @ComponentScan(“com.itheima.config”)

注意: 和那些 bean扫描一个单词
JdbcConfig类要放入到com.itheima.config包下,需要被Spring的配置类扫描到即可)

在这里插入图片描述

  • 方案2
    优点:此方案可以不用加@Configuration注解,但是必须在Spring配置类上使用@Import注解手动引入需要加载的配置类
    (1)步骤1:去除JdbcConfig类上的 @Configuration 注解
    (2)在 Spring 配置类中引入 @Import (此时对于该配置类的扫描可以不要)
    在这里插入图片描述
  1. 注解小结
    在这里插入图片描述

8. Spring 结合 MyBatis

  1. pom.xml (其实就在 上面学的 Spring + 之前学的 MyBatis 配置基础上 加了最后两个配置)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.example</groupId>
    <artifactId>spring_myBatis</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <!-- mybatis 依赖-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.5</version>
        </dependency>
        <!-- mysql 驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.46</version>
        </dependency>
        <!-- junit 单元测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.16</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.3.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>
    </dependencies>
</project>
  1. 将原来的 mybatis-config.xml 改成第三步,此时这个配置文件可以删除 (注意:2 框上有个 type,后面事务处理会学习)
    在这里插入图片描述
  2. 改之后: 在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述

9 AOP

AOP是在不改原有代码的前提下对其进行增强。
可以被增强的方法叫做连接点,想要增强的方法叫做切入点,通知就是切入点执行的操作,通知类就是定义通知的类,切面是描述通知与切入点的对应关系。(切入点就是被通知追加功能的连接点)

9.1 快速入门

    1. 添加依赖
<dependencies>
         <dependency>
	         <groupId>org.springframework</groupId>
	         <artifactId>spring-context</artifactId>
	         <version>5.2.10.RELEASE</version>
         </dependency>
        <dependency>
	            <groupId>org.aspectj</groupId>
	            <artifactId>aspectjweaver</artifactId>
	            <version>1.9.4</version>
        </dependency>
    </dependencies>

context 里面包含了 AOP 的,所以不用单独添加的

    1. 在这里插入图片描述
    1. 代码
@Configuration
@ComponentScan("com.qxd")
@EnableAspectJAutoProxy
public class SpringConfig {
}

@Repository
public class BookDaoImpl implements BookDao {
    public void save() {
        System.out.println(System.currentTimeMillis());
        System.out.println("book dao save ...");
    }

    public void update() {
        System.out.println("book dao update ...");
    }
}

public interface BookDao {
    void save();
    void update();
}

public class App {
    public static void main(String[] args) {
        ApplicationContext ctx = new
            AnnotationConfigApplicationContext(SpringConfig.class);
            BookDao bookDao = ctx.getBean(BookDao.class);
//            bookDao.save();
            bookDao.update();
        }
}

@Component
@Aspect
public class MyAdvice {
    @Pointcut("execution(void com.qxd.dao.BookDao.update())")
    private void pt() {}
    @Before("pt()")
    public void MyMethod() {
        System.out.println("hi...");
    }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

SpringAOP是在不改变原有设计(代码)的前提下对其进行增强的,它的底层采用的是代理模式实现的,所以要对原始对象进行增强,就需要对原始对象创建代理对象,在代理对象中的方法把通知 [如:MyAdvice中的MyMethod方法] 内容加进去,就实现了增强,这就是我们所说的代理 (Proxy)。

9.2 AOP 配置方式

9.2. 1 切入点表达式

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

  1. 切入点的描述
    在这里插入图片描述

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

  • eg:
execution(public User com.itheima.service.UserService.findById(int))
    • execution:动作关键字,描述切入点的行为动作,例如execution表示执行到指定切入点
    • public:访问修饰符,还可以是public,private等,可以省略
    • User:返回值,写返回值类型
    • com.itheima.service:包名,多级包使用点连接
    • UserService:类/接口名称
    • findById:方法名
    • int:参数,直接写参数的类型,多个类型用逗号隔开
    • 异常名:方法定义中抛出指定异常,可以省略

切入点表达式就是要找到需要增强的方法,所以它就是对一个具体方法的描述,但是方法的定义会有很多,所以如果每一个方法对应一个切入点表达式,想想这块就会觉得将来编写起来会比较麻烦,所以学到了下面的 通配符
9.2.1.2 通配符

  1. * :单个独立的任意符号,可以独立出现,也可以作为前缀或者后缀的匹配符出现
// 匹配com.itheima包下的任意包中的UserService类或接口中所有find开头的带有一个参数的
方法
execution(public * com.itheima.*.UserService.find*(*))
  1. ..多个连续的任意符号,可以独立出现,常用于简化包名与参数的书写
// 匹配com包下的任意包中的UserService类或接口中所有名称为findById的方法
execution(public User com..UserService.findById(..)) 1
  1. +:专用于匹配子类类型(很少用)
// 表示所有以Service结尾的接口的子类
execution(* *..*Service+.*(..))

9.2.1.3 书写技巧

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

9.2.2 AOP 通知类型

在这里插入图片描述

  • 前置通知
    • 在这里插入图片描述
  • 后置通知
    • 在这里插入图片描述
  • 返回后通知(了解)
    • 在这里插入图片描述
  • 抛出异常后通知(了解)
    • 在这里插入图片描述
  • 环绕通知(重点)(这个得加上ProceedingJoinPoint 和 抛出异常,不然电脑咋知道你怎么去环绕咧~)
    • 在这里插入图片描述
@Around("pt()")
public void around(ProceedingJoinPoint pjp) throws Throwable{
	System.out.println("around before advice ...");
	//表示对原始操作的调用
	pjp.proceed();
	System.out.println("around after advice ...");
}

注意:如果原函数含有参数,那么环绕的这个函数也得有参数并返回,例子如下:

// 原函数:
public int select() {
	System.out.println("book dao select is running ...");
	return 100;
}

@Around("pt2()")
	 public Object aroundSelect(ProceedingJoinPoint pjp) throws Throwable {
	 System.out.println("around before advice ...");
	 //表示对原始操作的调用
	 Object ret = pjp.proceed();
	 System.out.println("around after advice ...");
}

环绕通知更多注意:

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

9.2.3 通知中获取参数

  • 获取切入点方法的参数,所有的通知类型都可以获取参数
    • JoinPoint:适用于前置、后置、返回后、抛出异常后通知
    • ProceedingJoinPoint:适用于环绕通知
  • 获取切入点方法返回值,前置和抛出异常后通知是没有返回值,后置通知可有可无,所以不做研究
    • 返回后通知
    • 环绕通知
  • 获取切入点方法运行异常信息,前置和返回后通知是不会有,后置通知可有可无,所以不做研究
    • 抛出异常后通知
    • 环绕通知

9.3. AOP 事务管理

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

在这里插入图片描述

在这里插入图片描述
eg:不仅加了注解还有

//配置事务管理器,mybatis使用的是jdbc事务
    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource) {

        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
        transactionManager.setDataSource(dataSource);
        return transactionManager;
    }

9.3.1 事务配置

在这里插入图片描述

  • 上面这些属性都可以在@Transactional注解的参数上进行设置。
    • readOnly:true只读事务,false读写事务,增删改要设为false,查询设为true.
    • timeout:设置超时时间单位秒,在多长时间之内事务没有提交成功就自动回滚,-1表示不设置超时时间。
    • rollbackFor:当出现指定异常进行事务回滚
    • noRollbackFor:当出现指定异常不进行事务回滚 (并不是所有的异常都会回滚事务)
    • rollbackForClassName等同于rollbackFor,只不过属性为异常的类全名字符串
    • noRollbackForClassName等同于noRollbackFor,只不过属性为异常的类全名字符串
    • isolation设置事务的隔离级别\
      • DEFAULT :默认隔离级别, 会采用数据库的隔离级别
      • READ_UNCOMMITTED : 读未提交
      • READ_COMMITTED : 读已提交
      • REPEATABLE_READ : 重复读取
      • SERIALIZABLE: 串行化
  • propagation: 事务传播行为:事务协调员对事务管理员所携带事务的处理态度。
    eg: 下面这样就是开了新的事物,其他的不成功这个成功了也会保存数据
//propagation设置事务属性:传播行为设置为当前操作需要新事务
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void log(String out,String in,Double money ) {
	logDao.log("转账操作由"+out+"到"+in+",金额:"+money);
}

事务传播行为的可选值:
在这里插入图片描述
对于我们开发实际中使用的话,因为默认值需要事务是常态的。根据开发过程选择其他的就可以了,例如案例中需要新事务就需要手工配置。其实入账和出账操作上也有事务,采用的就是默认值。

n 总出错

  1. 老说我语言有问题,加上这个把它定死
<properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring Framework 学习 的相关文章

随机推荐

  • MyBatis 传递多个参数的4种方式

    MyBatis 传递多个参数的4种方式 方式1 xff1a 顺序传参 xff08 不推荐 xff09 span class token class name Employee span span class token function s
  • Java中String类的常用方法

    文章目录 Java 中 String 类的常用方法一 String 类的概念二 常用的构造方法三 常用方法1 toString 2 length 3 getBytes 4 toCharArray 5 charAt int index 6 i
  • ASR项目实战-数据

    使用机器学习方法来训练模型 xff0c 使用训练得到的模型来预测语音数据 xff0c 进而得到识别的结果文本 xff0c 这是实现语音识别产品的一般思路 本文着重介绍通用语音识别产品对于数据的诉求 对数据的要求 训练集 相关要求 xff0c
  • 如何写一棵简单的二叉查找树

    二叉查找树 完整代码 xff1a https github com problemin Algorithm blob master src Tree BSTree java 二叉排序树 xff08 Binary Sort Tree xff0
  • Redis常见的数据类型命令

    文章目录 Redis 常见的数据类型及命令一 常见的NoSQL二 Redis 简介三 key 键的一些操作命令四 Redis的五种基本数据结构1 String xff08 字符串 xff09 介绍常用命令1 1 set get1 2 app
  • Redis 的主从复制机制

    文章目录 Redis 的主从复制机制主从复制概述主从复制的作用主从复制环境的搭建主从复制的原理 哨兵模式概述哨兵模式的作用哨兵模式环境的搭建哨兵模式的原理 Cluster 模式 Redis 的主从复制机制 主从复制 概述 主从复制 xff0
  • Nginx 详解

    文章目录 Nginx 详解一 简介二 四大应用场景1 HTTP 服务器2 反向代理3 负载均衡4 动静分离 三 Linux 环境下安装Nginx四 Nginx 服务常用命令五 Nginx 配置文件1 全局块1 1 user1 2 worke
  • RabbitMQ 详解

    文章目录 RabbitMQ 详解一 MQ 简介1 MQ优缺点2 MQ应用场景3 AMQP 和 JMS4 常见的 MQ 产品 二 RabbitMQ 工作原理三 Linux环境安装RabbitMQ1 安装 Erlang2 安装 RabbitMQ
  • AndroidStudio卸载删除干净

    文章目录 前言一 卸载AndroidStudio程序二 删除目录 android三 xff0c 删除AndroidStudio xff0c Sdk目录在这里插入图片描述 这样文件目录就删除干净了 xff0c 接下来的教程是将配置删除 xff
  • 视图绑定ActivityMainBinding

    使用视图绑定 xff0c 可以更轻松的写与视图交互的代码 在模块中启动视图绑定之后 xff0c 系统会为每个模块中的每个XML布局文件生成一个绑定类 绑定类的实例包含对在相应布局中具有ID的所有视图的直接引用 可以代替findViewByI
  • 【FTP服务搭建】使用windows虚拟机搭建ftp服务,并能够使用ftp进行传输文件的操作

    参考了两位大佬写的教程 xff0c 自己实践了一下 xff0c 整理了一下操作步骤 使用机器 xff1a win10虚拟机 win7虚拟机 实验准备 win10下载filezilla下载地址 win10虚拟机关闭防火墙 两台机器可以相互 p
  • 操作系统经典问题——消费者生产者问题

    今日在学习操作系统的过程中遇到了这个问题 xff0c 实在是很苦恼一时间对于这种问题以及老师上课根据这个问题衍生的问题实在是一头雾水 在网络上寻找了一些大佬的讲解之后算是暂时有了点茅塞顿开的感觉 首先第一点什么是生产者 消费者问题 xff1
  • jar包的运行结果和源代码运行结果不一样

    问题 xff1a 我的A模块依赖了B模块 xff0c B模块更新了代码之后 xff0c 把A模块打包成jar包 xff0c 但是运行的时候我的B模块还是我修改之前的样子 报错 原因 xff1a 是因为我的B模块在更新了之后没有把它放到mav
  • Tensorflow数据读取篇之一 ——字节与张量的区别

    前言 字节串 xff08 bytes xff09 类型和张量 xff08 tensor xff09 类型是两种不同的数据类型 xff0c 它们在数据类型 内存分配和计算方式等方面有所不同 一 区别 数据类型 xff1a 字节串是一种特殊的不
  • O3DE社区发布2305.0版本

    O3DE社区发布了23年的第一个版本 xff0c 版本号为2305 0 2305 0版本对应的代码标签 xff0c 见链接 2305 0版本发布说明 xff0c 见链接 直接下载标签2305 0对应的源码 xff0c 命令如下 xff1a
  • 【机器学习】周志华西瓜书第八章集成学习习题8.3--编程实现AdaBoost模型,以不剪枝决策树为基学习器,在西瓜数据集3.0a上训练一个AdaBoost集成,并与教材图8.4进行比较

    xff08 1 xff09 问题理解与分析 编程实现AdaBoost模型 xff0c 不剪枝决策树为基学习器 xff0c 在西瓜数据集3 0a上训练一个AdaBoost集成 xff0c 并与教材图8 4进行比较 xff08 2 xff09
  • 【机器学习】周志华西瓜书第七章贝叶斯分类器习题--实现AODE分类器,以西瓜数据集3.0为训练集,对“测1”进行判别。

    from numpy import import numpy as np import pandas as pd 读取文件格式为xlsx的数据 def dataLoad filename df 61 pd read excel fliena
  • linux ubuntu版本下桌面图标过小或过大调整

    最近用虚拟机弄了个ubuntu系统 xff0c 但是在全屏状态下系统的桌面图标很小 xff08 如下图 xff09 后来发现是虚拟机的分辨率设置过大 xff08 大分辨率一般对应比较大的屏幕 xff09 xff0c 所以导致图标过小 更改方
  • css选择器定位元素

    CSS选择器是CSS语言的基本组成部分 xff0c 用于选择HTML或XML文档中要应用样式的元素 以下是一些常用的CSS选择器及其用法介绍 xff1a 元素选择器 xff1a 选择所有指定元素类型的元素 例如 xff1a p选择所有的段落
  • Spring Framework 学习

    Spring Framework 学习 1 Spring 核心概念1 1 IOC IOC容器 Bean DI 2 入门案例2 1 IOC入门案例2 2 DI 入门案例 3 IOC 基本内容3 1 bean 基础配置3 2 bean 实例化