Spring全套学习笔记

0X0a初识Spring
1、核心概念
使用对象时,由主动new产生对象转换为由外部提供对象,此过程中对象创建控制权由程序转移到外部
Spring提供了一个容器,称为IOC容器,用来充当IOC思想中的外部(dao容器)
IOC容器负责对象的创建、出啊实话等一系列工作,被创建或被管理的对象在IOC容器中称为Bean

在容器中建立bean和bean之间的依赖关系的整个过程称为DI(依赖注入)
2、入门案例
  • 目录结构

<!-- applicationContext.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
        <!--
            1、导入Spring的坐标:spring-context, 对应的版本是5.2.10.RELEASE
            2、配置bean
        -->
    <!-- id:给bean起名字    name:给bean起别名 scope:prototype多例对象	class:给bean定义类型 -->
    <bean id="bookDao" name="dao" class="com.company.dao.impl.BookDaoImpl"/>
    <bean id="bookService" class="com.company.service.impl.BookServiceImpl">
        <!-- name:配置的具体属性   ref:参照的Bean -->
        <property name="bookDao" ref="bookDao"></property>
    </bean>
</beans>
// BookDao 和 BookDaoImpl
public interface BookDao {
    public void save();
}

public class BookDaoImpl implements BookDao {
    public void save() {
        System.out.println("BookDao...");
    }
}
// BookService 和 BookServiceImpl
public interface BookService {
    public void show();
}

public class BookServiceImpl implements BookService {
    private BookDao bookDao;

    public void setBookDao(BookDaoImpl bookDao) {
        this.bookDao = bookDao;
    }

    public void show() {
        System.out.println("ServiceDao...");
        bookDao.save();
    }
}
// App.java
public class App {
    public static void main(String[] args) {
        //1.创建IoC容器对象,加载spring核心配置文件
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //2 从IOC容器中获取Bean对象(BookService对象)
        BookService bookService = (BookService) context.getBean("bookService");
        //3 调用Bean对象(BookService对象)的方法
        bookService.show();
    }
}
0X0bbean实例化
1、FactoryBean
// BookDaoFactory.java
public class BookDaoFactory implements FactoryBean<BookDao> {
    // 代替原来的实例工厂创建实例对象
    public BookDao getObject() throws Exception {
        return new BookDaoImpl();
    }

    public Class<?> getObjectType() {
        return BookDao.class;
    }
}

// 是否为单例对象
    public boolean isSingleton() {
        return true;
    }
<!-- xml配置 -->
<!-- 得到的对象是BookDaoFactory里的getObject的对象 -->
<bean id="bookDao" class="com.company.factory.BookDaoFactory"/>
2、Bean生命周期控制
//BookDao.java
public class BookDaoImpl implements BookDao {
    public void save() {
        System.out.println("BookDao...");
    }

    public void init() {
        System.out.println("Init...");
    }

    public void destory() {
        System.out.println("Destory...");
    }
}
<bean id="bookDao" class="com.company.dao.impl.BookDaoImpl" init-method="init" destroy-method="destory"/>
bean销毁时机
容器关闭之前触发bean销毁
0X0cbean注入
1、setter注入
// BookServiceImpl.java
public class BookServiceImpl implements BookService {
    private BookDao bookDao;
    private int connectionNum;
    private String databaseName;

    public void setConnectionNum(int connectionNum) {
        this.connectionNum = connectionNum;
    }

    public void setDatabaseName(String databaseName) {
        this.databaseName = databaseName;
    }

    public void setBookDao(BookDaoImpl bookDao) {
        this.bookDao = bookDao;
    }

    public void show() {
        System.out.println("ServiceDao..." + connectionNum + ", " + databaseName);
        bookDao.save();
    }
}
<bean id="bookDao" class="com.company.dao.impl.BookDaoImpl"/>
<bean id="bookService" class="com.company.service.impl.BookServiceImpl">
    <!-- 引用类型 -->
    <property name="bookDao" ref="bookDao"/>
    <!-- 简单类型 -->
    <property name="connectionNum" value="10"/>
    <property name="databaseName" value="mysql"/>
</bean>
2、构造器注入
// BookServiceImpl
public class BookServiceImpl implements BookService {
    private BookDao bookDao;
    private int connectionNum;
    private String databaseName;

    // 构造器注入,使用构造函数传参
    public BookServiceImpl(BookDao bookDao, int connectionNum, String databaseName) {
        this.bookDao = bookDao;
        this.connectionNum = connectionNum;
        this.databaseName = databaseName;
    }

    public void show() {
        System.out.println("ServiceDao..." + connectionNum + ", " + databaseName);
        bookDao.save();
    }
}  
<bean id="bookDao" class="com.company.dao.impl.BookDaoImpl"/>
<bean id="bookService" class="com.company.service.impl.BookServiceImpl">
    <!-- 引用类型 -->
    <constructor-arg name="bookDao" ref="bookDao"/>
    <!-- 简单类型 -->
    <constructor-arg name="connectionNum" value="10"/>
    <constructor-arg name="databaseName" value="mysql"/>
</bean>
3、依赖自动装配
IOC容器根据bean所依赖的资源在容器中自动查找并注入到bean中的过程称为自动装配
自动装配用于引用型依赖注入,不能对简单类型进行操作
优先级低于setter注入和构造器注入
<bean id="bookService" class="com.company.service.impl.BookServiceImpl" autowire="byType">
按照类型装配,bean对象必须唯一
<bean id="bookService" class="com.company.service.impl.BookServiceImpl" autowire="byName">
按照名称装配,bean里的id值和类里的变量名保持一致时装配
4、集合注入
<bean id="BookDao" class="com.company.dao.impl.BookDaoImpl">
    <property name="array">
        <array>
            <value>100</value>
            <value>200</value>
            <value>300</value>
        </array>
    </property>
    <property name="list">
        <list>
            <value>itcast</value>
            <value>itheima</value>
            <value>boxuegu</value>
            <value>chuanzhihui</value>
        </list>
    </property>
    <property name="set">
        <set>
            <value>itcast</value>
            <value>itheima</value>
            <value>boxuegu</value>
            <value>boxuegu</value>
        </set>
    </property>
    <property name="map">
        <map>
            <entry key="country" value="china"/>
            <entry key="province" value="henan"/>
            <entry key="city" value="kaifeng"/>
        </map>
    </property>
    <property name="properties">
        <props>
            <prop key="country">china</prop>
            <prop key="province">henan</prop>
            <prop key="city">kaifeng</prop>
        </props>
    </property>
</bean>
5、源对象管理
<!-- 数据库连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql:/localhost::3306/myDB"/>
    <property name="username" value="root"/>
    <property name="password" value="root"/>
</bean>
6、加载properities文件
# jdbc.properties
jdbc.driver = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://local:3306/myDB
jdbc.userName = root
jdbc.password = root
<?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
       ">
       
       <!-- 1、开启context命名空间 -->
       <!-- 2、使用context命名空间加载properties文件 -->
       <context:property-placeholder location="jdbc.properities"/>
       <!-- 3、使用属性占位符${}读取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>
</beans>

【补充 BeanFactory初始化】
// App.java
public class App {
    public static void main(String[] args) {
        /*
        // ApplicationContext是Spring容器的核心接口,初始化时bean立即完成加载
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        BookService bookService = (BookService) context.getBean("bookService");
        bookService.show();
        */
        // BeanFactory是IOC容器的顶层接口,创建完毕后,所有的bean均为延迟加载
        Resource resources = new ClassPathResource("applicationContext.xml");
        BeanFactory bf = new XmlBeanFactory(resources);
        // 下面和此代码一样的功能:BookDao bookDao = (BookDao) bf.getBean("bookDao");
        BookDao bookDao = bf.getBean("bookDao", BookDao.class);
        bookDao.show();
    }
}
7、核心容器总结

在这里插入图片描述

0X0d注解开发
1、注解开发定义Bean
Spring提供@Component注解的三个衍生注解
* @Controller 用于表现层bean定义
* @Service 用于业务层bean定义
* @Repository 用于数据层bean定义
<!-- ApplicationContext.xml -->
<?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
">

    <!-- 注解开发扫描含有注解开发的类 -->
    <context:component-scan base-package="com.company"/>

</beans>
// BookDaoImpl.java
@Repository("bookDao")
public class BookDaoImpl implements BookDao {
    public void show() {
        System.out.println("bookDao...");
    }
}
// BookServiceImpl.java
@Service("bookService")
public class BookServiceImpl implements BookService {
    private BookDao bookDao;

    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }

    public void show() {
        bookDao.show();
        System.out.println("bookService...");
    }
}
2、纯注解开发
// SpringConfig.java	用配置类代替了xml配置文件
package com.company.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.company")
public class SpringConfig {
}
// App.java
public class App {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
        BookService bookService = context.getBean("bookService", BookService.class);
        System.out.println(bookService);
    }
}
3、bean作用范围和生命周期
单例对象或者多例对象
在类前加@Scope("singleton")或者prototype

对于init和destroy方法,@PostConstruct和@PreDestory放在函数的前面
4、注解开发依赖注入
// BookServiceImpl.java
@Service("bookService")
public class BookServiceImpl implements BookService {
    @Autowired
    // @Qualifier("bookDao")如果有多个BookDao类,我们可以根据bean的名称进行区分
    private BookDao bookDao;
    
    // 对于简单类型,使用@value即可
    @value("hello")	// 如果通过外部.properties文件引入值,则在配置类里加上@PropertySource("文件名"),然后@value("${对应的名称}")
    private String name;

//    自动装配无需提供set方法
//    public void setBookDao(BookDao bookDao) {
//        this.bookDao = bookDao;
//    }

    public void show() {
        bookDao.show();
        System.out.println("bookService...");
    }
}
5、注解开发管理第三方
  • 方法一
// SpringConfig.java
@Configuration
public class SpringConfig {

    // 1、定义一个方法获得要管理的对象
    // 2、添加@Bean,表示当前方法的返回值是一个bean
    @Bean("dataSource")
    public DataSource dataSource() {
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://localhost::3306/myDB");
        ds.setUsername("root");
        ds.setPassword("root");
        return ds;
    }
}
// APP.java
public class App {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
        DataSource dataSource = context.getBean("dataSource", DataSource.class);
        System.out.println(dataSource);
    }
}
  • 方法二
// JdbcConfig.java 独立的配置类加入核心配置
public class JdbcConfig {
    @Bean("dataSource")
    public DataSource dataSource() {
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://localhost::3306/myDB");
        ds.setUsername("root");
        ds.setPassword("root");
        return ds;
    }
}
// SpringConfig.java	使用@Import注解手动加入配置类到核心配置
@Configuration
@Import(JdbcConfig.class)
public class SpringConfig {
}
6、注解开发总结

在这里插入图片描述

0X0eSpring整合
1、整合MyBatis
  • 目录结构(不需要applicationContext.xml,此为完全注解开发)
    在这里插入图片描述

  • 代码内容

//JdbcConfig.java
package com.company.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;

import javax.sql.DataSource;

public class JdbcConfig {
    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.userName}")
    private String userName;
    @Value("${jdbc.password}")
    private String password;


    @Bean("dataSource")
    public DataSource dataSource() {
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(userName);
        ds.setPassword(password);
        return ds;
    }
}
// MybatisConfig.java
package com.company.config;

import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.context.annotation.Bean;

import javax.sql.DataSource;

public class MybatisConfig {

    //定义bean,SqlSessionFactoryBean,用于产生SqlSessionFactory对象
    @Bean
    public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource) {
        SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();
        ssfb.setTypeAliasesPackage("com.company.domain");
        ssfb.setDataSource(dataSource);
        return ssfb;
    }

    //定义bean,返回MapperScannerConfigurer对象
    @Bean
    public MapperScannerConfigurer mapperScannerConfigurer() {
        MapperScannerConfigurer msc = new MapperScannerConfigurer();
        msc.setBasePackage("com.company.dao");
        return msc;
    }
}
// SpringConfig.java
package com.company.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.*;

import javax.sql.DataSource;

@Configuration
@ComponentScan("com.company")
@Import({JdbcConfig.class, MybatisConfig.class})
@PropertySource("jdbc.properties")
public class SpringConfig {
}
// AccountDao.java
package com.company.dao;

import com.company.domain.Account;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

import java.util.List;

public interface AccountDao {
    @Insert("insert into tbl_account(name,money)values(#{name},#{money})")
    void save(Account account);
    @Delete("delete from tbl_account where id = #{id} ")
    void delete(Integer id);
    @Update("update tbl_account set name = #{name} , money = #{money} where id = #{id} ")
    void update(Account account);
    @Select("select * from tbl_account")
    List<Account> findAll();
    @Select("select * from tbl_account where id = #{id} ")
    Account findById(Integer id);
}
// Account.java
package com.company.domain;

import java.io.Serializable;

public class Account implements Serializable {

    private Integer id;
    private String name;
    private Double money;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Double getMoney() {
        return money;
    }

    public void setMoney(Double money) {
        this.money = money;
    }

    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", money=" + money +
                '}';
    }
}
// AccountService.java
package com.company.service;

import com.company.domain.Account;
import java.util.List;

public interface AccountService {
    void save(Account account);
    void delete(Integer id);
    void update(Account account);
    List<Account> findAll();
    Account findById(Integer id);
}
// AccountServiceImpl.java
package com.company.service.impl;

import com.company.dao.AccountDao;
import com.company.domain.Account;
import com.company.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service("accountService")
public class AccountServiceImpl implements AccountService {
    @Autowired
    private AccountDao accountDao;

    public void save(Account account) {
        accountDao.save(account);
    }
    public void update(Account account){
        accountDao.update(account);
    }
    public void delete(Integer id) {
        accountDao.delete(id);
    }
    public Account findById(Integer id) {
        return accountDao.findById(id);
    }
    public List<Account> findAll() {
        return accountDao.findAll();
    }
}
// App.java
package com.company;

import com.company.config.SpringConfig;
import com.company.domain.Account;
import com.company.service.AccountService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import javax.sql.DataSource;

public class App {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
        AccountService account = context.getBean("accountService", AccountService.class);
        Account ac = account.findById(1);
        System.out.println(ac);
    }
}
# jdbc.properties
jdbc.driver = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://local:3306/myDB
jdbc.userName = root
jdbc.password = root
<!-- pom.xml -->
<?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</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.16</version>
        </dependency>

        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.6</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</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>

</project>
0X0fAOP
1、AOP简介
AOP是面相切片编程,一种编程范式
作用:在不惊动原始设计的基础上为其进行功能的增强

在这里插入图片描述

* 连接点(JoinPoint):正在执行的方法,例如:update()、delete()、select()等都是连接点。
* 切入点(Pointcut):进行功能增强了的方法,例如:update()、delete()方法,select()方法没有被增强所以不是切入点,但是是连接点。
	* 在SpringAOP中,一个切入点可以只描述一个具体方法,也可以匹配多个方法
    * 一个具体方法:com.itheima.dao包下的BookDao接口中的无形参无返回值的save方法
    * 匹配多个方法:所有的save方法,所有的get开头的方法,所有以Dao结尾的接口中的任意方法,所有带有一个参数的方法
* 通知(Advice):在切入点前后执行的操作,也就是增强的共性功能
	* 在SpringAOP中,功能最终以方法的形式呈现
* 通知类:通知方法所在的类叫做通知类
* 切面(Aspect):描述通知与切入点的对应关系,也就是哪些通知方法对应哪些切入点方法。
2、AOP入门案例
  • 代码结构
    在这里插入图片描述
// BookDao.java

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

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

    public void update() {
        System.out.println("BookDao update....");
    }
}
// MyAdvice.java

@Component
@Aspect
public class MyAdvice {
    // 切入点,在执行到BookDao的update函数的时候
    // 切入点定义依托一个不具有实际意义的方法进行,即五参数,无返回值,方法无实际逻辑
    @Pointcut("execution(void com.company.dao.BookDao.update())")
    private void pt() {}

    // 绑定这个方法在切入点之前
    @Before("pt()")
    public void method() {
        System.out.println(System.currentTimeMillis());
    }
}
// SpringConfig.java

@Configuration
@ComponentScan("com.company")
// 通知Spring有用注解开发的AOP
@EnableAspectJAutoProxy
public class SpringConfig {
}
// App.java
public class App {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
        BookDao bookDao = context.getBean("bookDao", BookDao.class);
        bookDao.update();
    }
}
3、切入点表达式
切入点:要进行增强的方法
切入点表达式:要进行增强的方法的描述方式
标准格式:动作关键字(访问修饰符 返回值 包名.类/接口名.方法名(参数)异常名)
通配符表达式
目的:可以使用通配符描述切入点,快速描述。
  • :单个独立的任意符号,可以独立出现,也可以作为前缀或者后缀的匹配符出现

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

execution(public * com.itheima.*.UserService.find*(*))
  • … :多个连续的任意符号,可以独立出现,常用于简化包名与参数的书写

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

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

    @Pointcut("execution(* com.company.dao.BookDao.show())")
    public void pt() {}
    
    @Pointcut("execution(* com.company.dao.BookDao.select())")
    public void pt2() {}
    
    // 前置通知
    //@Before注解表示作为前置通知
    @Before("pt()")
    public void before(){
        System.out.println("Before...");
    }

    // 在方法之后执行,有没有异常都执行
    @After("pt()")
    public void after(){
        System.out.println("Aftering");
    }
    
    @Around("pt()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable{
        System.out.println("before Around...");
        // 表示对原始操作的调用,原始操作的返回值被放在了ret里
        /*
        * 获得执行的方法的数字签名
        * Signature signature = pjp.getSignature();
        * System.out.println(signature.getDeclaringType());  输出:com.company.dao.BookDao
        * System.out.println(signature.getName());     输出:show
        */
        // 获得原始操作的参数
        Object[] args = pjp.getArgs();
        Object ret = pjp.proceed();		// 可以写成:Object ret = pjp.proceed(args);因此参数可以改变,对参数进行修改
        System.out.println("aftering Around...");
        return ret;
    }

    // 在方法返回值之后执行,有异常不执行
    @AfterReturning("pt2()")
    public void afterReturning(){
        System.out.println("AfterReturning");
    }

    // 异常之后执行
    @AfterThrowing("pt()")
    public void afterThrowing(){
        System.out.println("AfterThrowing");
    }
}
0X0gSpring事务
1、Spring事务简介
作用:在数据层或者业务层保障一系列的数据库操作同成功同失败
// AccountDao.java
public interface AccountDao {
    // 多钱的方法
    @update("UPDATE users SET money = money + #{money} WHERE username = #{username}")
    public void addMoney(@Param("username") String username, @Param("money") int money);

    // 少钱的方法
    @update("UPDATE users SET money = money - #{money} WHERE username = #{username}")
    public void reduceMoney(@Param("username") String username, @Param("money") int money){
        String sql = "UPDATE users SET money=money-? WHERE username=?";
        jdbcTemplate.update(sql, money, username);
    }
}
// AccountService.java
public interface AccountService {
    // 创建事务
    @Transactional
    public void transfer(String out, String in, int money);
}
// AccountServiceImpl.java
public class AccountServiceImpl implements AccountService {
    
    @Autowired
    private AccountDao accountDao;
    
    public void transfer(String out, String in, int money) {
        accountDao.addMoney(in, money);
        accountDao.reduceMoney(in, money);
    }
}
//JdbcConfig.java

public class JdbcConfig {
    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.userName}")
    private String userName;
    @Value("${jdbc.password}")
    private String password;


    @Bean("dataSource")
    public DataSource dataSource() {
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(userName);
        ds.setPassword(password);
        return ds;
    }
    
    //配置事务管理器,mybatis使用的是jdbc事务
    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource){
        DataSourceTransactionManager dtm = new DataSourceTransactionManager();
        transactionManager.setDataSource(dataSource);
        return transactionManager;
    }
}
// SpringConfig.java
@Configuration
@ComponentScan("com.itheima")
@PropertySource("jdbc.properties")
@Import({JdbcConfig.class,MybatisConfig.class})
//开启注解式事务驱动
@EnableTransactionManagement
public class SpringConfig {
}
2、Spring事务相关配置

在这里插入图片描述

3、事务传播行为

在这里插入图片描述

对于需要新建的事务,需要@Transactional(propagation = Propagation.REQUIRES_NEW)
//propagation设置事务属性:传播行为设置为当前操作需要新事务
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

horizonTel

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

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

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

打赏作者

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

抵扣说明:

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

余额充值