javaee开发之spring框架整合2(完结撒花)(代码片段)

nuist__NJUPT nuist__NJUPT     2023-03-16     326

关键词:

随着时代发展,软件规模与功能都呈几何式增长,开发难度也在不断递增,该如何解决?
Spring可以简化开发,降低企业级开发的复杂性,使开发变得更简单快捷随着项目规模与功能的增长,遇到的问题就会增多,为了解决问题会引入更多的框架,这些框架如何协调工作?Spring可以框架整合,高效整合其他技术,提高企业级应用开发与运行效率,综上所述,Spring是一款非常优秀而且功能强大的框架。
 

 

目录

一、IOC/DI注解开发

1.1、注解开发定义bean

1.2、纯注解开发模式

1.3、注解开发bean的作用范围与生命周期管理

1.4、注解开发的依赖注入

1.5、注解开发管理第三方的bean

1.6、XML配置和注解方式的对比 

二、Spring整合

2.1、Spring整合MyBatis

2.2、Spring整合Junit

三、面向切面编程(AOP)

3.1、AOP的基本概念

 3.2、AOP的入门案例

3.3、AOP工作流程

3.4、AOP配置管理

四、Spring事务管理

4.1、Spring事务简介

4.2、Spring事务属性


一、IOC/DI注解开发

1.1、注解开发定义bean

1、创建maven项目,在dao层和service分别定义一个接口和一个实现类,并使用注解标记bean。

public interface BookDao 
    public void save() ;

import com.dao.BookDao;
import org.springframework.stereotype.Repository;

@Repository("bookDao")
public class BookDaoImpl implements BookDao 

    public void save() 
        System.out.println("book dao save ...");
    


public interface BookService 
    public void save() ;


import com.dao.BookDao;
import com.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class BookServiceImpl implements BookService 
    @Autowired
    BookDao bookDao ;

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

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


2)在sping的配置文件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"
       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 https://www.springframework.org/schema/context/spring-context.xsd">
    <context:component-scan base-package="com" />

</beans>

3)编写测试类,获取IOC容器,根据bean对象访问对应的方法,如下:

import com.dao.BookDao;
import com.service.BookService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;


public class app 
    public static void main(String[] args) 
        //获取IOC容器
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml") ;
        //获取bean对象,并执行相应的方法
        BookDao bookDao = (BookDao) applicationContext.getBean("bookDao");
        bookDao.save();
        BookService bookService = applicationContext.getBean(BookService.class) ;
        bookService.save();

    

1.2、纯注解开发模式

spring3.0之后升级了纯注解开发模式,不用写配置文件了,使用java类替代spring的核心配置文件。

1)将上述的spring配置文件applicationContext.xml替换为如下类:
@Configuration注解用于设定当前类为配置类
@ComponentScan注解用于设定扫描路径,此注解只能添加一次,多个数据请用数组格式

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

@Configuration
@ComponentScan("com")
public class SpringConfig 

2)编写测试类,加载IOC容器,进行测试即可,这次直接配置类。

import com.SpringConfig;
import com.dao.BookDao;
import com.service.BookService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;


public class app1 
    public static void main(String[] args) 
        //获取IOC容器
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class) ;
        //获取bean对象,并执行相应的方法
        BookDao bookDao = (BookDao) applicationContext.getBean("bookDao");
        bookDao.save();
        BookService bookService = applicationContext.getBean(BookService.class) ;
        bookService.save();

    

1.3、注解开发bean的作用范围与生命周期管理

对于bean的作用范围加@scope注解,对于生命周期的初始化和销毁分别加@PostConstruct和@PreDestroy注解。

import com.dao.BookDao;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Repository;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

@Repository("bookDao")
@Scope
public class BookDaoImpl implements BookDao 

    public void save() 
        System.out.println("book dao save ...");
    
    @PostConstruct
    public void init()
        System.out.println("init ...");
    
    @PreDestroy
    public void destroy()
        System.out.println("destroy ...");
    



1.4、注解开发的依赖注入

1)直接使用@Autowired进行自动装配,完成注入,setter方法可以省略,如下:

该注解和@Qualifier注解组合使用,开启指定名称装配bean。

import com.dao.BookDao;
import com.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class BookServiceImpl implements BookService 
    @Autowired
    BookDao bookDao ;

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


2)上面是对引用类型的注入,下面使用@Value注解对简单类型进行注入,如下:
 

import com.dao.BookDao;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;


@Repository("bookDao")
public class BookDaoImpl implements BookDao 
    @Value("一起学习吧")
    private String name ;

    public void save() 
        System.out.println("book dao save ..." + name);
    


3)读取外部的Properties文件,首先创建一个jdbc.properties文件,然后再配置类使用注解@PropertySource加载文件,然后使用@Value注解获取jdbc.properties文件的值。


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

@Configuration
@ComponentScan("com")
@PropertySource("jdbc.properties")
public class SpringConfig 

import com.dao.BookDao;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;


@Repository("bookDao")
public class BookDaoImpl implements BookDao 
    @Value("$jdbc.username")
    private String name ;

    public void save() 
        System.out.println("book dao save ..." + name);
    


文件jdbc.properties如下:

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/spring_db
jdbc.username=root
jdbc.password=root

1.5、注解开发管理第三方的bean

1)创建外部资源对象,使用@Bean注解标注为bean。

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

import javax.sql.DataSource;

public class JdbcConfig 
    @Bean
    public DataSource dataSource()
        DruidDataSource dataSource = new DruidDataSource() ;
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/spring_db");
        dataSource.setUsername("root");
        dataSource.setPassword("root");
        return dataSource ;
    

2)在spring的配置类中直接扫描@ComponentScan或者导入@Import的形式加载外部资源,如下:

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

@Configuration
@ComponentScan("com")
@Import(JdbcConfig.class)
public class SpringConfig 

3)对应简单类型的注入,使用成员变量,对于引用类型的注入使用方法形参。


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

import javax.sql.DataSource;

public class JdbcConfig 
    @Value("com.mysql.jdbc.Driver")
    private String driveClassName ;

    @Value("jdbc:mysql://127.0.0.1:3306/spring_db")
    private String url ;

    @Value("root")
    private String username ;

    @Value("root")
    private String password ;

    @Bean
    public DataSource dataSource(BookDao bookDao)
        System.out.println(bookDao);
        DruidDataSource dataSource = new DruidDataSource() ;
        dataSource.setDriverClassName(driveClassName);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource ;
    

1.6、XML配置和注解方式的对比 

从如下5个角度进行对比,看图即可:

二、Spring整合

Spring有一个容器,叫做IoC容器,里面保存bean。在进行企业级开发的时候,其实除了将自己写的类让Spring管理之外,还有一部分重要的工作就是使用第三方的技术。前面已经讲了如何管理第三方bean了,下面结合IoC和DI,整合2个常用技术,进一步加深对Spring的使用理解。

2.1、Spring整合MyBatis

本次使用纯注解的方式在Spring中整合mybatis,把配置文件换成了java类+注解的方式,提高了开发效率,如果想看基于配置文件的方式整合mybatis,可以看我之前写的博客,地址如下:MyBatis与Spring的整合(Eclipse版本和IDEA版本)_nuist__NJUPT的博客-CSDN博客

1)创建一个数据库和表,如下:
 

create database if not exists spring_db character set utf8;
use spring_db;
create table if not exists tbl_account(
 id int primary key auto_increment,
 name varchar(35),
 money double
);
insert into tbl_account VALUES(null,'张三',100.00);
insert into tbl_account VALUES(null,'李四',200.00);
insert into tbl_account VALUES(null,'王五',300.00);

2)创建maven项目,并在pom.xml文件中添加相关依赖jar包,如下:

<?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>java02</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>

        <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>
    </dependencies>

</project>

3)创建数据源配置,mybatis配置,以及spring配置,不使用配置文件,这里直接使用注解的方式进行,如下:

数据源的配置:

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring_db
jdbc.username=root
jdbc.password=123456
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
    public DataSource dataSource() 
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(userName);
        ds.setPassword(password);
        return ds ;
    

mybatis配置:

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 sqlSessionFactory(DataSource dataSource)
    SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();
    //设置模型类的别名扫描
    ssfb.setTypeAliasesPackage("com.domain");
    ssfb.setDataSource(dataSource);
    return ssfb;

//定义bean,返回MapperScannerConfigurer对象
  @Bean
  public MapperScannerConfigurer mapperScannerConfigurer()
    MapperScannerConfigurer msc = new MapperScannerConfigurer();
    msc.setBasePackage("com.dao");
    return msc;
  

spring配置:

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

@Configuration
@ComponentScan("com")
@PropertySource("jdbc.properties")
@Import(JdbcConfig.class,MybatisConfig.class)
public class SpringConfig 

4)创建实体对象,要保证和数据库中一致,如下:
 

import java.io.Serializable;

public class Account implements Serializable 
    private Integer id ;
    private String name ;
    private Double money ;

    public int getId() 
        return id;
    

    public void setId(int 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 +
                '';
    

5)创建创建数据访问层,执行sql语句,如下:

import com.domain.Account;
import org.apache.ibatis.annotations.*;

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) ;

6)业务层,将数据访问层bean注入业务层,调用数据访问层的方法,执行业务操作:

import com.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) ;


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

import java.util.List;
@Service
public class AccountServiceImpl implements AccountService 
    @Autowired
    private AccountDao accountDao ;
    public void save(Account account) 
        accountDao.save(account);
    

    public void delete(Integer id) 
        accountDao.delete(id);
    

    public void update(Account account) 
        accountDao.update(account);
    

    public List<Account> findAll() 
        return accountDao.findAll();
    

    public Account findById(Integer id) 
        return accountDao.findById(id);
    

7)编写测试类进行测试,如下:

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

public class App 
    public static void main(String[] args) 
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class) ;
        AccountService accountService = applicationContext.getBean(AccountService.class);
        List<Account> list = accountService.findAll() ;
        for(Account account : list)
            System.out.println(account);
        
        System.out.println(accountService.findById(1)) ;
        accountService.delete(1);

    

2.2、Spring整合Junit

1)首先需要在pom.xml文件中田间test的相关jar包依赖,如下:

<?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>com.mybatis</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>

        <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>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>
    </dependencies>

</project>

2)编写测试类进行测试,需要加载测试运行器,设置spring文件的位置,对需要的测试的bean进行自动装配,然后调用方法进行测试。

import com.config.SpringConfig;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

//设置运行器类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class AccountServiceTest 

    @Autowired
    private AccountService accountService ;

    @Test
    public void findAll()
        System.out.println(accountService.findAll());
    

三、面向切面编程(AOP)

3.1、AOP的基本概念

AOP(Aspect Oriented Programming)面向切面编程,一种编程范式,指导开发者如何组织程
序结构。
OOP(Object Oriented Programming)面向对象编程,我们都知道OOP是一种编程思想,那么AOP也是一种编程思想,编程思想主要的内容就是指导程序员该如何编写程序,所以它们两个是不同的 编程范式 。

作用:在不惊动原始设计的基础上为其进行功能增强,前面咱们有技术就可以实现这样的功能即代
理模式。

通过下图:我们可以形象的学习AOP中的一些名词的含义,通知类中定义的增强功能的方法叫做通知,连接点表示原始所有方法,切入点是进行增强的方法,切面是进行通知和切入点进行绑定的。

 3.2、AOP的入门案例

1)创建maven项目,在pom.xml文件中添加相应的依赖jar包。

<?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">
    <parent>
        <artifactId>com.mybatis</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>com.aop</artifactId>

    <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>


</project>

2)在dao层编写接口和实现类,需要加相应的数据访问层注解,如下:

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

import com.dao.BookDao;
import org.springframework.stereotype.Repository;

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

    public void update() 
        System.out.println("bookDao update ...");
    

3)编写通知类,通知类中编写通知,通过切面对切入点进行绑定。对update方法进行增强。

@Component
@Aspect
public class MyAdvice 
    @Pointcut("execution(void com.dao.BookDao.update())")
    private void pt()

    @Before("pt()")
    public void method()
        System.out.println(System.currentTimeMillis());
    

4)编写spring配置类,加上相应的注解。


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

@Configuration
@ComponentScan("com")
@EnableAspectJAutoProxy
public class SpringConfig 

5)编写测试类进行测试。


import com.config.SpringConfig;
import com.dao.BookDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class App 
    public static void main(String[] args) 
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class) ;
        BookDao bookDao = applicationContext.getBean(BookDao.class) ;
        bookDao.update();
    

3.3、AOP工作流程

流程1:Spring容器启动,容器启动就需要去加载bean,哪些类需要被加载呢?
需要被增强的类,如:BookServiceImpl,通知类,如:MyAdvice。注意此时bean对象还没有创建成功。

流程2:读取所有切面配置中的切入点。

流程3:始化bean,判定bean对应的类中的方法是否匹配到任意切入点,注意第1步在容器启动的时候,bean对象还没有被创建成功。要被实例化bean对象的类中的方法和切入点进行匹配。匹配成功,创建原始对象(目标对象)的代理对象,如: BookDao匹配成功说明需要对其进行增强
对哪个类做增强,这个类对应的对象就叫做目标对象,因为要对目标对象进行功能增强,而采用的技术是动态代理,所以会为其创建一个代理对象最终运行的是代理对象的方法,在该方法中会对原始方法进行功能增强。

流程4:获取的bean是代理对象时,根据代理对象的运行模式运行原始方法与增强的内容,完成操作。

目标对象(Target):原始功能去掉共性功能对应的类产生的对象,这种对象是无法直接完成最终
工作的
代理(Proxy):目标对象无法直接完成工作,需要对其进行功能回填,通过原始对象的代理对象实

3.4、AOP配置管理

1)切入点表达式

对于切入点表达式可以采用通配符的方式书写,通过符的书写一般采用如下格式:

 2)AOP通知类型

前置通知:@Before
后置通知:@After
环绕通知(重点):@Around
返回后通知(了解):@AfterReturning
抛出异常后通知(了解):@AfterThrowing

前置通知案例:

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class MyAdvice 
    @Pointcut("execution(void com.dao.BookDao.update())")
    private void pt()

    @Before("pt()")
    public void method()
        System.out.println(System.currentTimeMillis());
    

后置通知案例:

import com.config.SpringConfig;
import com.dao.BookDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class App 
    public static void main(String[] args) 
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class) ;
        BookDao bookDao = applicationContext.getBean(BookDao.class) ;
        bookDao.update();
    

环绕通知案例:

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class MyAdvice 
    @Pointcut("execution(void com.dao.BookDao.update())")
    private void pt()

    @Around("pt()")
    public Object method(ProceedingJoinPoint pjp) throws Throwable 
            System.out.println(System.currentTimeMillis());
            Object object = pjp.proceed() ;
            System.out.println(System.currentTimeMillis());
            return object ;
    

3)测量接口万次代码执行效率:用环绕通知实现

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class MyAdvice 
    @Pointcut("execution(void com.dao.BookDao.update())")
    private void pt()

    @Around("pt()")
    public void method(ProceedingJoinPoint pjp) throws Throwable 
            Signature signature = pjp.getSignature() ;
            String className = signature.getDeclaringTypeName() ;
            String methodName = signature.getName() ;
            long start = System.currentTimeMillis() ;
            for(int i=0; i<10000; i++) 
                pjp.proceed();
            
            long end = System.currentTimeMillis() ;
        System.out.println("万次执行" + className + "." + methodName + "------->" + "时间为:" + (end-start) + "ms");
    

四、Spring事务管理

4.1、Spring事务简介

事务作用:在数据层保障一系列的数据库操作同成功同失败
Spring事务作用:在数据层或业务层保障一系列的数据库操作同成功同失败
数据层有事务我们可以理解,为什么业务层也需要处理事务呢?
举个简单的例子,
转账业务会有两次数据层的调用,一次是加钱一次是减钱
把事务放在数据层,加钱和减钱就有两个事务
没办法保证加钱和减钱同时成功或者同时失败
这个时候就需要将事务放在业务层进行处理。
Spring为了管理事务,提供了一个平台事务管理器 PlatformTransactionManager

下面看一个简单的转账案例

1)创建数据库的表,并添加两条记录用于模拟转账,如下:


create database if not exists spring_db character set utf8;
use spring_db;
create table if not exists tbl_account(
 id int primary key auto_increment,
 name varchar(35),
 money double
);

insert into tbl_account values(1,'Tom',1000);
insert into tbl_account values(2,'Jerry',1000);

2)创建maven项目,加载相关依赖jar包,如下:

<?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">
    <parent>
        <artifactId>com.mybatis</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>com.transaction</artifactId>

    <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>

        <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>
    </dependencies>
</project>

3)添加数据的配置文件jdbc.properties,如下:

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/spring_db?characterEncoding=utf-8
jdbc.username=root
jdbc.password=123456

4)添加Account实体类。

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 +
                '';
    

5)创建数据层,执行操作数据库的操作。

import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Update;


public interface AccountDao 
    @Update("update tbl_account set money = money + #money where name = #name")
    void inMoney(@Param("name") String name, @Param("money") Double money) ;
    @Update("update tbl_account set money = money - #money where name = #name")
    void outMoney(@Param("name") String name, @Param("money") Double money) ;

6)创建业务层的接口和实现类,实现数据层注入和调用数据层的方法等业务操作,需要在接口添加事务注解。

import org.springframework.transaction.annotation.Transactional;

@Transactional
public interface AccountService 
    public void transfer(String out,String in ,Double money) ;

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

@Service
public class AccountServiceImpl implements AccountService 
    @Autowired
    private AccountDao accountDao ;

    public void transfer(String out, String in, Double money) 
        accountDao.outMoney(out,money);
//        int a = 1 / 0 ;
        accountDao.inMoney(in,money);
    

7)完成数据源,mybatis以及spring的配置,在mybatis配置中配置事务管理器,在spring配置中启动事务管理器。

数据源配置:

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

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
    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 transactionManager = new DataSourceTransactionManager();
         transactionManager.setDataSource(dataSource);
         return transactionManager;
    

mybatis配置:

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 sqlSessionFactory(DataSource dataSource)
        SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();
        //设置模型类的别名扫描
        ssfb.setTypeAliasesPackage("com.domain");
        ssfb.setDataSource(dataSource);
        return ssfb;
    
    //定义bean,返回MapperScannerConfigurer对象
    @Bean
    public MapperScannerConfigurer mapperScannerConfigurer()
        MapperScannerConfigurer msc = new MapperScannerConfigurer();
        msc.setBasePackage("com.dao");
        return msc;
    

spring配置:


import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@ComponentScan("com")
@PropertySource("jdbc.properties")
@Import(JdbcConfig.class,MybatisConfig.class)
@EnableTransactionManagement
public class SpringConfig 

8)编写测试类,测试事务管理。

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

public class App 
    public static void main(String[] args) 
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class) ;
        AccountService accountService = applicationContext.getBean(AccountService.class) ;
        accountService.transfer("Tom","Jerry",100.00);
    

4.2、Spring事务属性

1)事务配置,我们可以对事务设置属性,特别是回滚属性,可以设置在什么异常下产生回滚。

 2)事务的传播行为,如果事务管理员已经开启事务,事务协调员不想加入,就需要另外开辟一个事务,通过设置事务传播属性是实现。

 3)事务传播属性设置案例

需求:在以上的基础上,无论转账是否成功,都记录转账日志信息。

第一步,在上述的数据库中创建一个表用于记录转账信息,如下:

create table tbl_log(
 id int primary key auto_increment,
 info varchar(255),
 createDate datetime
)

然后,添加数据层接口,如下:

import org.apache.ibatis.annotations.Insert;

public interface LogDao 
    @Insert("insert into tbl_log (info,createDate) values(#info,now())")
    void log(String info);

然后添加业务层接口和实现类,需要设置事务为另外开启一个新的事务,即修改事务的传播行为:

import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Transactional(propagation = Propagation.REQUIRES_NEW)
public interface LogService 
    void log(String out, String in, Double money);

import com.dao.LogDao;
import com.service.LogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class LogServiceImpl implements LogService 
    @Autowired
    private LogDao logDao;

    public void log(String out, String in, Double money) 
        logDao.log("转账操作由"+out+"到"+in+",金额:"+money);
    

然后需要转账业务中添加日志记录业务,如下:

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

@Service
public class AccountServiceImpl implements AccountService 
    @Autowired
    private AccountDao accountDao ;

    @Autowired
    private LogService logService ;

    public void transfer(String out, String in, Double money) 
        try 
            accountDao.outMoney(out, money);
          int a = 1 / 0 ;
            accountDao.inMoney(in, money);
        finally 
            logService.log(out,in,money);
        
    

javaee(ssm框架,黑马程序员)p193~p201完结

一、SSM框架整合1.1原始方式整合1.准备工作2.创建Maven工程3.导入Maven坐标<!--spring相关--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version> 查看详情

javaee框架整合技术之spring01-ioc教程(代码片段)

Spring一.Spring概述1.什么是SpringSpring是分层的JavaEE应用full-stack(全栈)轻量级开源框架。Spring的核心是IOC(InverseOfControl:控制反转)和AOP(AspectOrientedProgramming:面向切面编程)Spring一个全栈应用框架,提供 查看详情

javaee框架整合技术之spring01-ioc教程(代码片段)

Spring一.Spring概述1.什么是SpringSpring是分层的JavaEE应用full-stack(全栈)轻量级开源框架。Spring的核心是IOC(InverseOfControl:控制反转)和AOP(AspectOrientedProgramming:面向切面编程)Spring一个全栈应用框架,提供 查看详情

javaee框架技术之14ssm综合案例(代码片段)

...理解SSM综合案例表的结构5.【掌握】产品管理二、SSM整合Spring+SpringMVC+Mybatis–>SSMSpring+Struts2+Hibernate-->SSH2.1简单整合在学习springmvc时我们发现,spring 查看详情

javaee框架整合技术之spring02-aop面向切面编程技术(代码片段)

Spring新注解Spring5.0之后的注解称为新注解使用上面的注解还不能全部替代xml配置文件,还需要使用注解替代的配置注解说明@Configuration表示当前类是一个配置类,用于代替配置文件,相当于applicationContext.xml@Bean作用于... 查看详情

javaee框架整合技术之spring02-aop面向切面编程技术(代码片段)

Spring新注解Spring5.0之后的注解称为新注解使用上面的注解还不能全部替代xml配置文件,还需要使用注解替代的配置注解说明@Configuration表示当前类是一个配置类,用于代替配置文件,相当于applicationContext.xml@Bean作用于... 查看详情

javaee框架整合技术之spring03-springjdbctemplate模板技术和事务处理(代码片段)

SpringJdbcTemplateSpring的JdbcTemplate是一个对JDBC的模板封装,它提供了一套JDBC的模板,能让我们写持久层代码时减少多余的代码,简化JDBC代码,使代码看起来更简洁。在介绍Spring的JdbcTemplate使用方法之前我们先来讨论... 查看详情

javaee框架技术之14ssm综合案例产品管理crud(代码片段)

...理解SSM综合案例表的结构5.【掌握】产品管理二、SSM整合Spring+SpringMVC+Mybatis–>SSMSpring+Struts2+Hibernate-->SSH2.1简单整合在学习springmvc时我们发现,spring 查看详情

ssm之spring

...烩,整合了现有的技术框架!为什么要学Spring技术是JavaEE开发必备技能,企业开发技术选型命中率>90%专业角度简化开发,降低企业级开发的复杂性框架整合,高效整合其他技术,提高企业级应用开发与运行效率优点spring是一... 查看详情

##走过路过不容错过之##javaee框架篇一spring

目录说一下你对Spring的理解?​​​​​​​Spring常用的注解简单说一下SpringMVC与Spring是如何整合的详细的说一下springaop的实现原理Spring中@Autowired和@Resource的区别?你给我说一下SpringBoot吧?SpringCloud的常用组件挨个介绍... 查看详情

二java框架之spring注解开发(代码片段)

文章目录1.IOC/DI注解开发1.1Component注解@Component@Controller@Service@Repository1.2纯注解开发模式1.3注解开发bean管理@Scope@PostConstruct@PreDestroy1.4注解开发依赖注入@Autowired@Qualifier@Value@PropertySource1.5第三方bean... 查看详情

javaee互联网轻量级框架整合开发—ssm框架(中文版带书签)原书代码

JavaEE互联网轻量级框架整合开发 第1部分入门和技术基础第1章认识SSM框架和Redis21.1Spring框架21.2MyBatis简介61.3SpringMVC简介111.4最流行的NoSQL——Redis121.5SSM+Redis结构框图及概述13第2章Java设计模式152.1Java反射技术152.2动态代理... 查看详情

javaweb开发之spring详解之——spring的入门以及ioc容器装配bean(xml和注解的方式)spring整合web开发整合junit4测试

Spring框架学习路线Spring的IOCSpring的AOP,AspectJSpring的事务管理,三大框架的整合Spring框架概述什么是Spring? Spring是分层的JavaSE/EEfull-stack(一站式)轻量级开源框架。所谓分层:SUN提供的EE的三层结构:web层、业务层、数据访问层... 查看详情

springboot整合与文件配置(代码片段)

哈喽~大家好,这篇看看Springboot整合与文件配置。🥇个人主页:个人主页      🥈系列专栏:【Java框架】 🥉与这篇相关的文章:       【JAVAEE框架】MyBatis与Spring的整合(上)【JAVAEE框... 查看详情

javaee框架——mybatis和spring整合

mybatis和spring的联合使用当前主流的框架已经不是ssh了,前台偏向于springMvc代替struts,后台的mybatis/ibatis的流行程度则超过了hibernate了,只有spring框架一直是流行框架里的中流砥柱。mybatis如何与spring交互呢?我为大家演... 查看详情

javaee框架——springmvc入门(注解url核心类详解文件上传和下载)和spring的整合(代码片段)

...。使用Spring可插入的MVC架构,从而在使用Spring进行WEB开发时,可以选择使用Spring的SpringMVC框架或集成其他MVC开发框架,如S 查看详情

《javaee互联网轻量级框架整合开发》开售,源码下载和纠错

各位:新书《JavaEE互联网轻量级框架整合开发——SSM框架(SpringMVC+Spring+MyBatis)和Redis实现》已经出版,欢迎大家购买,可以到下面地址购买:出版社天猫店京东自营当当自营刚刚上市不久,如果... 查看详情

springspring系列7之spring整合mvc框架

7、Spring整合MVC框架7.1、web环境中使用Spring7.2、整合MVC框架目标:使用Spring管理MVC的Action、Controller最佳实践参考:http://www.itnose.net/detail/6102205.htmlhttp://wenku.baidu.com/link?url=ABQ1RvCWEAVObPpqJKWudD-UPc4YyH1MQQlu11fpCe 查看详情