Spring


目录
  • 1.Spring 5简单介绍
  • 2.IOC(反转控制)
    • 1.什么是IOC
    • 2.IOC底层原理
    • 3.Bean管理操作的两种方式
      • 1--基于xml配置文件方式实现
        • (1)注入对象
        • (2)注入属性
          • 注入属性-外部bean
          • 注入属性-内部bean和级联赋值
          • 注入集合类型的属性
          • 将集合注入部分提取出来
      • IOC操作Bean
        • IOC操作Bean管理(FactoryBean)
        • IOC操作Bean管理(bean作用域)
        • IOC操作Bean管理(bean生命周期)
        • IOC操作Bean管理(自动装配)
        • IOC操作Bean管理(外部属性文件)
      • 2--基于Spring注解方式实现
        • 1、什么叫注解
        • 2、Spring针对Bean管理中创建对象提供注解
        • 3、基于Spring注解实现对象的创建
        • 4、基于注解的方式实现属性注入
        • 5、Spring中的@Bean注解
          • spring的注解分类
          • @bean注解概述
        • 6、完全注解开发
  • 3.AOP(面向切面编程)
    • 1、 什么是AOP
    • 2、AOP底层原理
      • (1)AOP底层使用动态代理
      • (2)AOP(JDK动态代理)
      • (3)AOP术语
      • (4)AOP操作准备
      • (5)AOP操作
        • 1、AspectJ注解方式(掌握)
        • 2、AspectJ配置文件方式(了解)
  • 4、数据库事务、JDBCTemplate
    • (1) 简介、测试
    • (2)JDBCTemplate操作数据库(增删查改)
    • (3)事务操作
      • 1.什么是事务?
      • 2.事务的特性(ACID)
      • 3.事务环境
      • 4.事务的操作
      • 5.XML声明式事务管理
        • 1.在spring配置文件中进行配置
        • 2.完全注解声明式
  • 5、Spring5框架的新功能
    • 1.增加功能
    • 2.核心特性
    • 3.WebFlux
      • (1)简单介绍
      • (2)响应式编程
      • (3)WebFlux 执行流程和核心API
      • (4)SpringWebflux(基于注解编程模型)
      • (5)SpringWebflux(基于函数式编程模型)

1.Spring 5简单介绍

1、spring是轻量级的开源的JavaEE框架

2.、Spring可以解决企业应用开发的复杂性

3、Spring有俩个核心部分:IOC和AOP

? (1)IOC:控制反转,把创建对象过程交给Spring进行管理

? (2)AOP:面向切面,不修改源代码进行功能增强

4、Spring特点

(1)方便解耦,简化开发

(2)AOP编程支持

(3)方便Junit测试

(4)方便和其他框架进行整合

(5)方便进行事务操作

(6)降低API开发难度

2.IOC(反转控制)

1.什么是IOC

(1)控制反转,把对象的创建和对象之间调用的过程,交给Spring进行管理

? (2)使用IOC目的:为了降低耦合度

? Spring 核心容器(Core)提供Spring框架的基本功能。核心容器的主要组件是BeanFactory,它是工厂模式的实现。BeanFactory使用控制反转(Ioc)模式将应用程序的配置和依赖性规范与实际的应用代码程序分开。Spring的声明式事务基于AOP实现,却并不需要程序开发者成为AOP专家,亦可轻易使用Spring的声明式事务管理。

2.IOC底层原理

? (1)xml解析、工厂模式、反射

](javascript:void(0)??

class Yanggb {
    @Bean
    public YanggbDao createYanggbDaoBean(){
        return new YanggbDao();
    }
}

[](javascript:void(0)??

在上面的例子中,createYanggbDaoBean方法就会产生一个YanggbDao对象,并将这个对象交给Spring管理(放到ioc容器中)。到这里很容易就能明白,@bean注解是使用在方法上的注解,它会明确地告诉被注解的方法去产生一个bean对象并交给spring容器管理。简单点说就是,@bean注解放在方法上,让方法去产生一个bean交给spring容器。

因为@bean注解是使用在方法上的,因此使用@bean注解的另一个好处就是能够动态获取一个bean对象,且能够根据环境不同得到不同的bean对象。

另外,@bean注解和xml配置中的bean标签的作用是一模一样的。

6、完全注解开发

? (1)创建配置类,代替xml配置文件

 //注解类   
@Configuration
@ComponentScan(basePackages = {"com.Spring5_demo3"})
public class config {

}


  //测试
    @Test
    public void test()
    {
        ApplicationContext context = new AnnotationConfigApplicationContext (Config.class);
        UserService userService = context.getBean ("userService", UserService.class);
        userService.show ();
    }

3.AOP(面向切面编程)

1、 什么是AOP

? (1)面向切面编程,利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

? (2)通俗来说AOP,就是不通过修改源代码,来增加功能。

? image-20211030212945812

2、AOP底层原理

(1)AOP底层使用动态代理

? ①有接口的情况,使用JDK动态代理

image-20211031092853518

? ②没有接口的情况,使用CGLIB动态代理

image-20211031093954570

(2)AOP(JDK动态代理)

? ①调用newProxyInstance(ClassLoader loader,类<?> [] interfaces,InvocationHandler h)方法

? 方法有三个参数 :

? 1-类加载器、2-增强方法所在的类,这个类实现的接口,支持多个接口

? 3-实现这个接口InvocationHandler,创建代理对象,写增强的方法

package com.Spring5_demo4.AOP_Proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;

public class JDKProxy {
    public static void main(String[] args) {
        //创建接口实现类代理对象
        Class[] interfaces = {UserDao.class};
        UserDaoimpl userDao = new UserDaoimpl ();
        UserDao dao = (UserDao)Proxy.newProxyInstance (JDKProxy.class.getClassLoader (), interfaces, new UserDaoProxy (userDao));
        int addres = dao.add (1, 2);
        System.out.println (addres);
    }

}
class UserDaoProxy implements InvocationHandler{
    //把创建的是谁的代理对象,就将谁传递过来 这里创建的是UserDao的代理对象
    private Object obj;
    public UserDaoProxy(Object object)
    {
        this.obj = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //方法之前进行处理
        System.out.println ("在方法之前执行--"+method.getName ()+"传递的参数:"+ Arrays.toString (args));
        //被增强的方法执行
        Object res = method.invoke (obj, args); //执行add后返回一个结果
        //方法之后
        System.out.println ("方法之后执行---"+obj);
        return res;
    }
}

(3)AOP术语

? 1、连接点

image-20211031153758654

? 2、切入点

? 实际被真正增强的方法,称为切入点;

? 3、通知(增强)

? ①实际增强的逻辑部分称为通知(增强)

? ②通知有五种类型

? 1.前置通知 2.后置通知 3.环绕通知 4.异常通知 5.最终通知

? 4、切面

? 将通知应用到切入点的过程;

(4)AOP操作准备

? 1、Spring 框架一般基于AspectJ实现AOP操作

? AspectJ不是Spring的组成部分,而是独立的AOP框架,一般把AspectJ和Spring框架整合使用,进行AOP操作

? 2、基于AspectJ实现AOP操作

? ①基于xml配置文件方式实现

? ②基于Spring注解方式实现(常用)

? 3、在项目中引入AOP依赖

? 4、切入点表达式

? ①切入点表示式的作用:可以知道对哪个类的哪个方法进行增强

? ②语法结构:execution([权限修饰符] [返回类型] [类全路径] [方法名称] [参数列表])

? 包 . Student .*表示对Student类中的所有方法进行增强

? 包 . * . *表示对包中的所有类的所有方法进行增强

(5)AOP操作

1、AspectJ注解方式(掌握)

? ①编写增强类和被增强类

? 在增强类中,创建方法,让不同方法代表不同通知类型

? ②进行通知的配置

? 1.在Spring配置文件中,开启注解扫描

<?xml version="1.0" encoding="UTF-8"?>


    
    

? 2.使用注解创建User和UserProxy对象

? 3.在增强类上面添加注解@Aspect

? 4.在Spring配置文件中开启生成代理对象

? ③配置不同类型的通知

? 在增强类的里面,在作为通知方法上面添加通知类型注解,使用切入点表达式来配置

package com.Spring5_AOP_annotation.bean;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
 * 增强类
 */
@Component
@Aspect //表示生成代理对象
public class UserProxy {
    /**
     * 前置通知
     * @Before注解就表示前置通知
     */
    @Before (value = "execution(* com.Spring5_AOP_annotation.bean.User.add(..))")
    public void before()
    {
        System.out.println ("before------");
    }

    /**
     * 最终通知 无论有没有异常都会执行
     */
    @After (value = "execution(* com.Spring5_AOP_annotation.bean.User.add(..))")
    public void after()
    {
        System.out.println ("after--------");
    }

    /**
     * 后置通知/返回通知 有异常不执行
     */
    @AfterReturning (value = "execution(* com.Spring5_AOP_annotation.bean.User.add(..))")
    public void afterReturning()
    {
        System.out.println ("AfterReturning--------");
    }

    /**
     * 异常通知
     */
    @AfterThrowing(value = "execution(* com.Spring5_AOP_annotation.bean.User.add(..))")
    public void afterThrowing()
    {
        System.out.println ("AfterThrowing--------");
    }

    /**
     * 环绕通知
     */
    @Around (value = "execution(* com.Spring5_AOP_annotation.bean.User.add(..))")
    public void Around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println ("环绕之前......");

        //被增强的方法执行
        proceedingJoinPoint.proceed ();

        System.out.println ("环绕之后.......");
    }
}

? 5.对公共切入点进行抽取

    @Around (value = "pointdemo()")
    public void Around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println ("环绕之前......");

        //被增强的方法执行
        proceedingJoinPoint.proceed ();

        System.out.println ("环绕之后.......");
    }
    //相同切入点抽取
    @Pointcut(value = "execution(* com.Spring5_AOP_annotation.bean.User.add(..))")
    public void pointdemo()
    {

    }

? 6.多个增强类对同一个方法进行增强,设置增强类优先级

? 1、在增强类上面添加注解@Order,数字类型值越小优先级越高

2、AspectJ配置文件方式(了解)

<?xml version="1.0" encoding="UTF-8"?>

    
        
        

    
        
        
        
        
            
        
    
    

4、数据库事务、JDBCTemplate

(1) 简介、测试

1.什么是JDBCTemplate

? Spring框架对JDBC进行封装,使用JDBCTemplate方便实现对数据库的操作

2.在springxml文件中配置数据库连接池,配置JDBCTemplate对象注入Datasource


    
    
        
        
        
        
    
    
    
    
    
        
    
        
        
   properties 文件
	driverClass=com.mysql.cj.jdbc.Driver
	url=jdbc:mysql://localhost:3306/test?&useSSL=false&serverTimezone=UTC
	userName=root
	password=wh.0410
        
     
  1. 测试类

        ApplicationContext context = new ClassPathXmlApplicationContext ("XML/Template/Te.xml");
            BookService bookService = context.getBean ("bookService", BookService.class);
            bookService.addBook (new Book ("1","三体","已售"));
    
    

(2)JDBCTemplate操作数据库(增删查改)

package com.Spring_JdbcTemplate.Dao;

import com.Spring_JdbcTemplate.entity.Book;

public interface BookDao {
    public void add(Book book);

    public void update(Book book);

    public void delete(String BookId);

}



package com.Spring_JdbcTemplate.Dao;


import com.Spring_JdbcTemplate.entity.Book;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

@Repository
public class BookDaoimpl implements BookDao{

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public void add(Book book) {
        String sql = "insert into t_book values (?,?,?)";
        int update = jdbcTemplate.update (sql, book.getBookId (), book.getBookName (), book.getUstatus ());
        System.out.println (update);
    }

    @Override
    public void update(Book book) {
        String sql = "update t_book set BookName = ?,ustatus = ? where BookId = ?";
        int update = jdbcTemplate.update (sql, book.getBookName (), book.getUstatus (), book.getBookId ());
        System.out.println (update);
    }

    @Override
    public void delete(String BookId) {
        String sql = "delete from t_book where BookId = ?";
        jdbcTemplate.update (sql,BookId);
    }
}


package com.Spring_JdbcTemplate.Service;

import com.Spring5_demo3.Dao.UserDao;
import com.Spring_JdbcTemplate.Dao.BookDao;
import com.Spring_JdbcTemplate.Dao.BookDaoimpl;
import com.Spring_JdbcTemplate.entity.Book;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class BookService {
    //注入dao
    @Autowired
    private BookDao bookDao;

    public void addBook(Book book)
    {
        bookDao.add(book);
    }
    public void updateBook(Book book)
    {
        bookDao.update(book);
    }
    public void DeleteBook(String BookId)
    {
        bookDao.delete(BookId);
    }

}

? 1.JdbcTemplate查询返回某个值

 /**
     * 查询返回某个值
     * @return
     */
    @Override
    public Integer selectCount() {
        String sql = "select count(*) from t_book";
        Integer count = jdbcTemplate.queryForObject (sql, Integer.class);
        return count;
    }

? 2.JdbcTemplate查询返回对象

/**
     * 返回对象
     * @param BookId
     * @return
     */
    @Override
    public Book queryOnebook(String BookId) {
        String sql = "select * from t_book where BookId = ?";
        Book book = jdbcTemplate.queryForObject (sql, new BeanPropertyRowMapper (Book.class), BookId);
        return book;
    }

? 3.JdbcTemplate查询返回集合

/**
     * 查询返回集合
     * @return
     */
    public List queryBookList()
    {
        String sql = "select * from t_book";
        List books = jdbcTemplate.query (sql, new BeanPropertyRowMapper (Book.class));
        return books;
    }
	4.JdbcTemplate批量操作(批量添加修改删除)

image-20211103151827930

? 参数一:sql语句 参数二:List集合,添加多条记录

 /**
     * 批量添加
     * @param batchArgs
     */
    public void batchAdd(List batchArgs)
    {
        String sql = "insert into t_book values(?,?,?)";
        int[] batchUpdate = jdbcTemplate.batchUpdate (sql, batchArgs);
        System.out.println (Arrays.toString (batchUpdate));
    }

    /**
     * 批量修改
     * @param batchArgs
     */
    public void batchUpdate(List batchArgs)
    {
        String sql = "update t_book set BookName=?,ustatus=? where BookId = ?";
        int[] batchUpdate = jdbcTemplate.batchUpdate (sql, batchArgs);
        System.out.println (Arrays.toString (batchUpdate));
    }

    /**
     * 批量删除
     * @param batchArgs
     */
    public void batchDelete(List batchArgs)
    {
        String sql = "delete from t_book where BookId = ?";
        int[] batchUpdate = jdbcTemplate.batchUpdate (sql, batchArgs);
        System.out.println (Arrays.toString (batchUpdate));
    }

(3)事务操作

1.什么是事务?

? 事务是数据库操作的最基本单元,逻辑上一组操作,要莫都成功要么都失败。

2.事务的特性(ACID)

? 原子性

? 一致性

? 隔离性

? 持久性

3.事务环境

? 数据库事务环境image-20211103161217985

4.事务的操作

? 1-注意:事务一般添加到JavaEE三层结构的Service层上

? 2-在Spring进行事务管理操作

? 有两种方式 :编程式事务管理和声明式事务管理

? 开发中一般用声明式事务管理

? 3-声明式事务管理

? ①基于注解方式

? ②基于xml配置文件方式

? 4.在Spring进行声明式事务管理,底层使用AOP

? 5.在Spring事务管理API

? (1) 提供了一个接口,代表事务管理器。这个接口针对不同的框架提供了不同的实现类

? 0-修改xml文件

<?xml version="1.0" encoding="UTF-8"?>

? (2)-创建事务管理器


    


? (3)-开始事务注解

    

? (4)-在service类上面(或者service类里面的方法上面添加事务注解)

? ①@Transactional,这个注解添加到类的上面,也可以添加方法上面

? ②如果把这个注解添加类的上面,这个类里面的所有方法都添加事务

? ③如果把这个注解添加方法上面,位这个方法 添加事务

? (5)事务注解中的参数

image-20211103210443430

? 1-propagation :事务传播行为

? 多事务方法直接进行调用,这个过程中事务时如何进行管理的

? 事务方法:对数据库表数据进行变化的操作

? image-20211103211634666

? 2-Ioslation:事务隔离级别

? ·1 事务有特性称为隔离性,多事务操作之间不会产生影响,不考虑隔离将会 产生很多问题

? ·2 有三个读的问题 脏读、不可重复读、虚(幻)读

	![image-20211104174052000](C:\Users\未来可期\AppData\Roaming\Typora\typora-user-images\image-20211104174052000.png)

																				脏读

image-20211104174608491

? 不可重复读

虚读:一个未提及的事务读取到了已提交事务中添加的数据

通过事务的隔离级别可以解决上述问题:

? image-20211104175110262

? Mysql默认隔离级别为REPEATABLE READ

? 3-timeout:超过时间

? 事务需要在一定的时间内进行提交,如果不提交就进行回滚

? 默认值是- 1,设置时间以秒为单位进行计算

? 4-readOnly:是否只读

? 默认值为false,表示可以查询,可以进行添加修改删除操作

? 如果设为true就只能查询

? 5-rollbackFor:回滚

5.XML声明式事务管理

1.在spring配置文件中进行配置

? ①配置事务管理器

? ②配置通知

? ③配置切入点和切面


    
    
    
        
    

    
    
        
    
    
    
        
        
            
            
        
    
    
    
        
        
        
       
    

2.完全注解声明式

? ①创建配置类,使用配置类代替xml配置文件

package com.Spring_JdbcTemplate.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;

@Configuration //配置类
@ComponentScan(basePackages = "com.Spring_JdbcTemplate") //组件扫描
@EnableTransactionManagement //开启事务
public class TxConfig {
    //创建数据库连接池
    @Bean
    public DruidDataSource getDruidDataSource()
    {
        DruidDataSource dataSource = new DruidDataSource ();
        dataSource.setDriverClassName ("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl ("jdbc:mysql://localhost:3306/test?&useSSL=false&serverTimezone=UTC");
        dataSource.setUsername ("root");
        dataSource.setPassword ("wh.0410");
        return dataSource;
    }

    @Bean
    public JdbcTemplate getJdbcTemplate(DataSource dataSource)
    {
        JdbcTemplate jdbcTemplate = new JdbcTemplate ();
        //到IOC容器中根据类型找到dataSource 并注入dataSource
        jdbcTemplate.setDataSource (dataSource);
        return jdbcTemplate;
    }

    //创建事务管理器duix
    @Bean
    public DataSourceTransactionManager getdataSourceTransactionManager(DataSource dataSource)
    {
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager ();
        //到IOC容器中根据类型找到dataSource 并注入dataSource
        dataSourceTransactionManager.setDataSource (dataSource);
        return dataSourceTransactionManager;
    }



}

? ②创建测试方法

 @Test
    public void accountMoneyAnno()
    {
        ApplicationContext context = new AnnotationConfigApplicationContext (TxConfig.class);
        UserService userService = context.getBean ("userService", UserService.class);
        userService.accountMoney ();
    }

5、Spring5框架的新功能

1.增加功能

image-20211105105238567

2.核心特性

? (1)@Nuallable注解可以使用在方法、属性、参数上面,表示方法返回可以为空,属性值可以为空

? 参数值可以为空

? (2)Spring5核心容器支持函数式风格GenericApplicationContext 创建对象

@Test
    public void  GenericApplicationContextTest()
    {
        //创建GenericApplicationContext对象
        GenericApplicationContext genericApplicationContext = new GenericApplicationContext ();
        //调用context方法对象注册
        genericApplicationContext.refresh ();

        genericApplicationContext.registerBean (Stu.class,()->new Stu ());

        //获取在Spring注册的对象
        Stu stu = (Stu) genericApplicationContext.getBean ("com.Spring_JdbcTemplate.Test.Stu");

        System.out.println (stu);
    }

(3)Spring5支持整合JUnit5

? 1-整合JUnit4

@RunWith (SpringJUnit4ClassRunner.class) //指定单元测试框架
@ContextConfiguration("classpath:XML/Template/Te2.xml") //加载配置文件
public class JTest4 {
    @Autowired
    private UserService userService;

    @Test
    public void test1()
    {
        userService.accountMoney ();
    }

}

? 2-整合JUnit5

@ExtendWith (SpringExtension.class)
@ContextConfiguration("classpath:XML/Template/Te2.xml")
public class JTest4 {
    @Autowired
    private UserService userService;

    @Test
    public void test1()
    {
        userService.accountMoney ();
    }

? 3-使用复合注解整合上述俩个注解

@SpringJUnitConfig(locations = "classpath:bean1.xml")
public class JTest5 {
 @Autowired
 private UserService userService;
 @Test
 public void test1() {
 userService.accountMoney();
 } }

3.WebFlux

image-20211105165804832

(1)简单介绍

? ①SpringWebFlux式Spring5新加的模块,用于web开发,与SpringMVC功能类似,WebFlux使用

当前一种比较流行的响应式编程出现的框架

? ②使用传统web框架,比如SpringMVC,这些基于Servlet容器,WebFlux是一种一部非阻塞的框架,异步非阻塞的框架再Servlet3.1以后才支持,核心是基于reactor的相关API实现

? ③异步非阻塞:

? 异步、同步:调用者发送请求,如果要等着对方回应后才能做其他事情则称为同步,若发送请求后可以不等待回应就去做其他事情称为异步(Ajax就是异步请求,局部改变动态页面)

? 阻塞、非阻塞:被调用者收到请求后,在做完请求任务后才给出反馈就是阻塞,若收到请求后马上就做出反馈就是非阻塞

? ④WebFlux的特点:

? 1-非阻塞式:可以在有限的资源下,提高系统的吞吐量和伸缩性(即在有限的 资源下处理更多的请求)

? 2-函数式编程:Spring框架基于java8,WebFlux使用java8函数时编程方式实现路由请求

? image-20211105191115266

(2)响应式编程

? 何为响应式编程是一种面向数据流和变化传播的编程范式,这意味着可以在编程语言中很方便的表达静态或动态的数据流,而相关的计算模型会自动将变化的值通过数据流进行传播

(3)WebFlux 执行流程和核心API

(4)SpringWebflux(基于注解编程模型)

(5)SpringWebflux(基于函数式编程模型)

	先看看springmvc boot 后再回头看5的新特性

尚硅谷Spring5框架教程(idea版)_哔哩哔哩_bilibili