Spring Getting Started Instructions

Objective introduction

  • Spring framework overview
  • IOC container
    • IOC underlying principles
    • IOC interface (BeanFactory)
    • IOC operation bean management (based on xml)
    • IOC operation bean management (based on annotations)
  • Aop
  • JdbcTemplate
  • transaction management
  • Spring5 new features

1. Introduction to the framework

1 Overview

  • Spring is a lightweight open source JavaEE framework
  • Spring can solve the complexity of enterprise application development
  • Spring has two core parts: IOC and Aop
    • IOC: Inversion of control, handing over the object creation process to Spring for management
    • Aop: Aspect-oriented, function enhancement without modifying the source code
  • Spring features
    • Convenient decoupling and simplified development
    • Aop programming support
    • Facilitate program testing
    • Easy to integrate with other frameworks
    • Convenient for business operations
    • Reduce API development difficulty

2. Spring entry case

1. Download spring

(1) Use the latest stable version of Spring 5.2.6

Insert image description here

(2) Download address

Insert image description here
Insert image description here

2. Open the idea tool and create a normal Java project

Insert image description here

Insert image description here

Insert image description here

3. Import Spring5 related jar packages

Insert image description here

Insert image description here

Insert image description here
4. Create a common class and create a common method in this class

public class User {
    
    
    public void add() {
    
    
        System.out.println("add.......");
    }
}

5. Create a Spring configuration file and configure the created objects in the configuration file.

Spring configuration file uses xml format

Insert image description here

<?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">
	
	<!--配置 User 对象创建--> 	
	<bean id="user" class="com.atguigu.spring5.User"></bean>
</beans>

6. Write test code

@Test
public void testAdd() {
    
    
    //1.加载spring配置文件
    ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
    //2.获取配置创建对象
    User user = context.getBean("user", User.class);
    System.out.println(user);
    user.add();
}

7. Operation results

Insert image description here

2.IOC

1. IOC concepts and principles

(1) What is IOC

  • Inversion of control, leaving the object creation and calling process between objects to Spring for management
  • Purpose of using IOC: to reduce coupling
  • The introductory case is IOC implementation

(2) The underlying principles of IOC

  • xml parsing, factory pattern, reflection

(3) Draw pictures to explain the underlying principles of IOC

Insert image description here

Insert image description here

Insert image description here

2. BeanFactory interface

(1) The IOC idea is based on the IOC container. The bottom layer of the IOC container is the object factory.

(2) Spring provides two ways to implement IOC containers: (two interfaces)

  • BeanFactory: The basic implementation of the IOC container. It is the internal usage interface of Spring and is not provided for developers to use - (the object will not be created when loading the configuration file, and the object will be created after the object is obtained (used))
  • ApplicationContext: A sub-interface of the BeanFactory interface, providing more and more powerful functions, generally used by developers----(the configuration file object will be created when the configuration file is loaded)

(3) The ApplicationContext interface has an implementation class---- (shortcut key Ctrl+h)

Insert image description here

FileSystemXmlApplicationContext represents reading files from the server storage drive letter path

ClassPathXmlApplicationContext represents reading files from the project src hierarchy directory path

3. IOC operation bean management (concept)

(1) What is Bean management

  • Bean management refers to two operations: Spring creates objects and Spirng injects properties.

(2) There are two methods for Bean management operations

  • Implemented based on xml configuration file
  • Implemented based on annotations

4. IOC operation bean management (based on xml)

Ⅰ. Based on xml method

(1) Create objects based on xml

<!--配置User对象创建-->
<bean id="user" class="com.atguigu.spring5.User"></bean>

说明:
- 在 spring 配置文件中,使用 bean 标签,标签里面添加对应属性,就可以实现对象创建
- 在 bean 标签有很多属性,介绍常用的属性
  - id 属性:唯一标识
  - class 属性:类全路径(包类路径)
- 创建对象时候,默认也是执行无参数构造方法完成对象创建

(2) Inject attributes based on xml

  • DI: dependency injection, which is to inject properties

(3) The first injection method: use the set method to inject

① Create a class, define attributes and corresponding set methods

/**
* 演示使用 set 方法进行注入属性
*/
public class Book {
    
    
	//创建属性
	private String bname;
	private String bauthor;
	//创建属性对应的 set 方法
	public void setBname(String bname) {
    
    
		this.bname = bname;
	}
	public void setBauthor(String bauthor) {
    
    
		this.bauthor = bauthor;
	} 
}

② Create configuration object in spring configuration file and inject configuration properties

<!-- set 方法注入属性--> 
<bean id="book" class="com.atguigu.spring5.Book">
	<!--使用 property 完成属性注入 name:类里面属性名称 value:向属性注入的值-->
	<property name="bname" value="易筋经"></property>
	<property name="bauthor" value="达摩老祖"></property>
</bean>

③ test case

@Test
public void bookTest(){
    
    
    //1.加载配置文件
    ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
    //2.获取配置文件创建对象
    Book book = context.getBean("book", Book.class);
    //类中加入toString()方法
    System.out.println(book);
}

(4) The second injection method: Injection using parameterized constructs

① Create a class, define attributes, and create attributes corresponding to parameter construction methods

/**
* 使用有参数构造注入
*/
public class Orders {
    
    
	//属性
	private String oname;
	private String address;
	//有参数构造
	public Orders(String oname,String address) {
    
    
		this.oname = oname;
		this.address = address;
	} 
}

② Configure in spring configuration file

<!--有参数构造注入属性--> 
<bean id="orders" class="com.atguigu.spring5.Orders">
	<constructor-arg name="oname" value="电脑"></constructor-arg>
	<constructor-arg name="address" value="China"></constructor-arg>
</bean>

③ test case

@Test
public void ordersTest(){
    
    
    //1.加载配置文件
    ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
    //2.获取配置文件创建对象
    Orders orders = context.getBean("orders", Orders.class);
    //类中加入toString()方法
    System.out.println(orders);
}

(5) p namespace injection (understanding)

Using p namespace injection can simplify the xml-based configuration method

  • The first step is to add the p namespace in the configuration file

Insert image description here

注意:xmlns:p="http://www.springframework.org/schema/p"

  • The second step is to perform attribute injection and operate in the bean tag.
<!--本次p名称注入使用的 无参构造创建对象  set 方法注入属性--> 
<bean id="book" class="com.atguigu.spring5.Book" p:bname="九阳神功" p:bauthor="无名氏"></bean>
Ⅱ. XML injection of other types of attributes

(1) Literal

① null value

<!--null 值--> 
<property name="address">
	<null/>
</property>

② The attribute value contains special symbols

<!--属性值包含特殊符号
 	1 把<>进行转义 &lt; &gt;
 	2 把带特殊符号内容写到 <![CDATA[~]]>中
-->

<constructor-arg name="oname">
    <value>&lt;&gt;</value>
</constructor-arg>
<property name="address">
	<value><![CDATA[<<南京>>]]></value>
</property>

注意:字面量或者特殊属性,根据set注入或者有参构造注入都是可以的

(2) Inject properties - external bean

① Create two classes, service class and dao class

② Call the method in dao in service

③ Configure in spring configuration file

//创建两个包 service 、dao
//在service包中创建UserService
public class UserService {
    
    
    //创建UserDao类型属性,生成set方法
    private UserDao userDao;
    public void setUserDao(UserDao userDao) {
    
    
        this.userDao = userDao;
    }
    public void add(){
    
    
        System.out.println("userService add.................");
        userDao.update();
    }
}

//在dao包中创建UserDao
public interface UserDao {
    
    
    void update();
}

//在dao包中创建UserDaoImpl
public class UserDaoImpl implements UserDao {
    
    
    @Override
    public void update() {
    
    
        System.out.println("UserDaoImpl update.................");
    }
}	
<!-- bean.xml 使用set方法注入 -->
<!-- service 和 dao 对象创建--> 
<bean id="userService" class="com.atguigu.spring5.service.UserService">
	<!--注入 userDao 对象
 	name 属性:类里面属性名称
 	ref 属性:创建 userDao 对象 bean 标签 id 值
 	-->
	<property name="userDao" ref="userDaoImpl"></property>
</bean> 
<bean id="userDaoImpl" class="com.atguigu.spring5.dao.UserDaoImpl"></bean>
@Test
public void serviceTest(){
    
    
    //1.加载配置文件
    ApplicationContext context = new ClassPathXmlApplicationContext("bean3.xml");
    //2.获取配置文件创建对象
    UserService userService = context.getBean("userService", UserService.class);
    UserDaoImpl userDaoImpl = context.getBean("userDaoImpl", UserDaoImpl.class);
    System.out.println(userService);
    System.out.println(userDaoImpl);
    userService.add();
}

(3) Injection properties - internal beans

① One-to-many relationship: departments and employees. A department has multiple employees. An employee belongs to a department. The department is one and the employees are many.

② Represent a one-to-many relationship between entity classes, employees represent the departments they belong to, and use object type attributes to represent them.

//部门类
public class Dept {
    
    
	private String dname;
	public void setDname(String dname) {
    
    
		this.dname = dname;
 	} 
}
//员工类
public class Emp {
    
    
	private String ename;
	private String gender;
	//员工属于某一个部门,使用对象形式表示
	private Dept dept;
	public void setDept(Dept dept) {
    
    
		this.dept = dept;
	}
	public void setEname(String ename) {
    
    
		this.ename = ename;
	}
	public void setGender(String gender) {
    
    
		this.gender = gender;
 	}
}

③ Configure in spring configuration file

<!--内部 bean--> 
<bean id="emp" class="com.atguigu.spring5.bean.Emp">
	<!--设置两个普通属性-->
	<property name="ename" value="lucy"></property>
	<property name="gender" value=""></property>
	<!--设置对象类型属性-->
	<property name="dept">
		<bean id="dept" class="com.atguigu.spring5.bean.Dept">
			<property name="dname" value="安保部"></property>
		</bean>
 	</property>
</bean>
@Test
public void EmpTest(){
    
    
    //1.加载配置文件
    ApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");
    //2.获取配置文件创建对象
    Emp emp = context.getBean("emp", Emp.class);
    System.out.println(emp);
}

(4) Injection attributes - cascade assignment

① The first way of writing

<!--级联赋值--> 
<bean id="emp" class="com.atguigu.spring5.bean.Emp">
	<!--设置两个普通属性-->
	<property name="ename" value="lucy"></property>
	<property name="gender" value=""></property>
	<!--级联赋值第一种写法-->
	<property name="dept" ref="dept"></property>
</bean> 
<bean id="dept" class="com.atguigu.spring5.bean.Dept">
 	<property name="dname" value="财务部"></property>
</bean>
@Test
public void EmpTest(){
    
    
    //1.加载配置文件
    ApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");
    //2.获取配置文件创建对象
    Emp emp = context.getBean("emp", Emp.class);
    System.out.println(emp);
}

② The second way of writing

Insert image description here

<!--级联赋值--> 
<bean id="emp" class="com.atguigu.spring5.bean.Emp">
	<!--设置两个普通属性-->
	<property name="ename" value="lucy"></property>
	<property name="gender" value=""></property>
	<!--级联赋值第二种写法-->
	<property name="dept" ref="dept"></property>
	<property name="dept.dname" value="技术部"></property>
</bean> 
<bean id="dept" class="com.atguigu.spring5.bean.Dept"></bean>
//Emp
public class Emp {
    
    
    /**
     * 员工类
     */
    private String ename;
    private String gender;
    //员工属于某个部门,使用对象形式表示
    private Dept dept;
    public Dept getDept() {
    
    
        return dept;
    }
    public void setEname(String ename) {
    
    
        this.ename = ename;
    }
    public void setGender(String gender) {
    
    
        this.gender = gender;
    }
    public void setDept(Dept dept) {
    
    
        this.dept = dept;
    }
    @Override
    public String toString() {
    
    
        return "Emp{" +
                "ename='" + ename + '\'' +
                ", gender='" + gender + '\'' +
                ", dept=" + dept +
                '}';
    }
}

//Dept
public class Dept {
    
    
    /**
     * 部门类
     */
    private String dname;
    public Dept() {
    
    
    }
    public void setDname(String dname) {
    
    
        this.dname = dname;
    }
    @Override
    public String toString() {
    
    
        return "Dept{" +
                "dname='" + dname + '\'' +
                '}';
    }
}

//Test
@Test
public void EmpTest(){
    
    
    //1.加载配置文件
    ApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");
    //2.获取配置文件创建对象
    Emp emp = context.getBean("emp", Emp.class);
    System.out.println(emp);
}
Ⅲ. xml injection collection attributes
  • Inject array type properties

  • Inject List collection type properties

  • Inject Map collection type properties

① Create a class, define array, list, map, and set type attributes, and generate the corresponding set method

public class Stu {
    
    
     //1 数组类型属性
     private String[] courses;
     //2 list 集合类型属性
     private List<String> list;
     //3 map 集合类型属性
     private Map<String,String> maps;
     //4 set 集合类型属性
     private Set<String> sets;
     public void setSets(Set<String> sets) {
    
    
     	this.sets = sets;
     }
     public void setCourses(String[] courses) {
    
    
     	this.courses = courses;
     }
     public void setList(List<String> list) {
    
    
     	this.list = list;
     }
     public void setMaps(Map<String, String> maps) {
    
    
     	this.maps = maps;
     }
}

② Configure in spring configuration file

<!--1 集合类型属性注入--> 
<bean id="stu" class="com.atguigu.spring5.collectiontype.Stu">
	<!--数组类型属性注入-->
	<property name="courses">
        <array>
            <value>java 课程</value>
            <value>数据库课程</value>
        </array>
	</property>
    <!--list 类型属性注入-->
    <property name="list">
        <list>
            <value>张三</value>
            <value>小三</value>
        </list>
    </property>
    <!--map 类型属性注入-->
    <property name="maps">
        <map>
            <entry key="JAVA" value="java"></entry>
            <entry key="PHP" value="php"></entry>
        </map>
    </property>
    <!--set 类型属性注入-->
    <property name="sets">
        <set>
            <value>MySQL</value>
            <value>Redis</value>
        </set>
    </property>
</bean>
@Test
public void StuTest(){
    
    
    ApplicationContext context = new ClassPathXmlApplicationContext("bean5.xml");
    Stu stu = context.getBean("stu", Stu.class);
    System.out.println(stu);
}

(4) Set the object type value in the collection

//Course
public class Course {
    
    
    /**
     * 课程类
     */
    private String cname;
    public void setCname(String cname) {
    
    
        this.cname = cname;
    }
    @Override
    public String toString() {
    
    
        return "Course{" +
                "cname='" + cname + '\'' +
                '}';
    }
}

//Stu
public class Stu {
    
    
	/**
     *  创建类,定义数组、list、map、set 类型属性,生成对应 set 方法
     */
    //数组类型属性
    private String[] courses;
    //list集合类型属性
    private List<String> list;
    //map集合类型属性
    private Map<String,String> maps;
    //set集合类型属性
    private Set<String> sets;
    //学生所学多门课程
    private List<Course> courseList;
    public void setCourses(String[] courses) {
    
    
        this.courses = courses;
    }
    public void setList(List<String> list) {
    
    
        this.list = list;
    }
    public void setMaps(Map<String, String> maps) {
    
    
        this.maps = maps;
    }
    public void setSets(Set<String> sets) {
    
    
        this.sets = sets;
    }
    public void setCourseList(List<Course> courseList) {
    
    
        this.courseList = courseList;
    }
    @Override
    public String toString() {
    
    
        return "Stu{" +
                "courses=" + Arrays.toString(courses) +
                ", list=" + list +
                ", maps=" + maps +
                ", sets=" + sets +
                ", courseList=" + courseList +
                '}';
    }
}
<!-- 创建多个course对象 -->
<bean id="course1" class="com.company.spring5.Course">
    <property name="cname" value="Spring5 框架"/>
</bean>
<bean id="course2" class="com.company.spring5.Course">
    <property name="cname" value="MyBatis 框架"/>
</bean>
<bean id="stu" class="com.company.spring5.Stu">
    <property name="courseList">
        <list>
            <ref bean="course1"/>
            <ref bean="course2"/>
        </list>
    </property>
</bean>
@Test
public void StuTest(){
    
    
    ApplicationContext context = new ClassPathXmlApplicationContext("bean5.xml");
    Stu stu = context.getBean("stu", Stu.class);
    System.out.println(stu);
}

(5) Extract the injection part of the collection

① Introduce the namespace util in the spring configuration file

<?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:p="http://www.springframework.org/schema/p"
	xmlns:util="http://www.springframework.org/schema/util"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans.xsd
	http://www.springframework.org/schema/util 
	http://www.springframework.org/schema/util/spring-util.xsd">

② Use the util tag to complete the list collection injection and extraction

//Books
public class Books {
    
    
    private List<String> books;
    public void setBooks(List<String> books) {
    
    
        this.books = books;
    }
    @Override
    public String toString() {
    
    
        return "Books{" +
                "books=" + books +
                '}';
    }
}
//Test
@Test
public void booksTest(){
    
    
    ApplicationContext context = new ClassPathXmlApplicationContext("bean6.xml");
    Books books = context.getBean("books", Books.class);
    System.out.println(books);
}
<?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:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/util
       http://www.springframework.org/schema/util/spring-util.xsd">
    <!-- 提取list集合类型属性注入 -->
    <util:list id="bookList">
        <value>易筋经</value>
        <value>九阴真经</value>
        <value>九阳神功</value>
    </util:list>
    <!-- 提取list集合类型属性注入使用 -->
    <bean id="books" class="com.company.spring5.Books">
        <property name="books" ref="bookList"/>
    </bean>
</beans>
Ⅳ、FactoryBean
  • Spring has two types of beans, one is a normal bean and the other is a factory bean (FactoryBean).
  • Ordinary beans: The bean type defined in the configuration file is the return type
  • Factory bean: The bean type defined in the configuration file can be different from the return type

The first step is to create a class and use this class as a factory bean to implement the FactoryBean interface.

The second step is to implement the methods in the interface and define the returned bean type in the implemented method.

public class MyBean implements FactoryBean<Course> {
    
    
     //定义返回 bean
     @Override
     public Course getObject() throws Exception {
    
    
         Course course = new Course();
         course.setCname("abc");
         return course;
     }
     @Override
     public Class<?> getObjectType() {
    
    
     	return null;
     }
     @Override
     public boolean isSingleton() {
    
    
     	return false;
 	} 
}
<bean id="myBean" class="com.atguigu.spring5.factorybean.MyBean">
</bean>
@Test
public void test3() {
    
    
    ApplicationContext context = new ClassPathXmlApplicationContext("bean3.xml");
    Course course = context.getBean("myBean", Course.class);
    System.out.println(course);
}
V. bean scope

(1) In Spring, set whether to create a bean instance as a single instance or multiple instances.

(2) In Spring, by default, a bean is a single instance object

public class Course {
    
    
    /**
     * 课程类
     */
    private String cname;
    public void setCname(String cname) {
    
    
        this.cname = cname;
    }
}

@Test
public void test4(){
    
    
    ApplicationContext context = new ClassPathXmlApplicationContext("bean6.xml");
    Course course1 = context.getBean("course", Course.class);
    Course course2 = context.getBean("course", Course.class);
    System.out.println(course1);
    System.out.println(course2);
}
<bean id="course" class="com.company.spring5.Course"/>

Insert image description here

(3) How to set up single instance or multiple instances?

① There is an attribute (scope) in the bean tag of the spring configuration file for setting single instance or multiple instances.

② scope attribute value

  • The default value of the first value is singleton, which means it is a single instance object.
  • The second value prototype indicates that it is a multi-instance object.
<!--提取list集合类型属性注入使用-->
<bean id="book" class="com.atguigu.spring5.collectiontype.Book" scope="prototype">
	<property name="list" ref="bookList"></property>
</bean>

Insert image description here

(4) The difference between singleton and prototype

  • The first singleton single instance, prototype multiple instances

  • When the second setting scope value is singleton, a single instance object will be created when loading the spring configuration file.

  • When the scope value is set to prototype, the object is not created when the spring configuration file is loaded, but the multi-instance object is created when the getBean method is called.

Ⅵ. Bean life cycle
  • life cycle

    • The process from object creation to object destruction
  • bean life cycle

    • Create bean instance through constructor (no parameter construction)
    • Set values ​​for bean properties and references to other beans (call the set method)
    • Call the bean initialization method (method that requires configuration initialization)
    • The bean is ready for use (the object is obtained)
    • When the container is closed, the bean's destruction method is called (the destruction method needs to be configured)
  • Demo bean life cycle

public class Orders {
    
    
    //无参数构造
    public Orders() {
    
    
    	System.out.println("第一步 执行无参数构造创建 bean 实例");
    }
    private String oname;
    public void setOname(String oname) {
    
    
        this.oname = oname;
        System.out.println("第二步 调用 set 方法设置属性值");
    }
    //创建执行的初始化的方法
    public void initMethod() {
    
    
    	System.out.println("第三步 执行初始化的方法");
    }
    //创建执行的销毁的方法
    public void destroyMethod() {
    
    
    	System.out.println("第五步 执行销毁的方法");
    } 
}
<bean id="orders" class="com.atguigu.spring5.bean.Orders" init-method="initMethod" destroy-method="destroyMethod">
	<property name="oname" value="手机"></property>
</bean>
@Test
public void testBean3() {
    
    
	// ApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");
	ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");
	Orders orders = context.getBean("orders", Orders.class);
	System.out.println("第四步 获取创建 bean 实例对象");
	System.out.println(orders);
	//手动让 bean 实例销毁
	context.close();
}

Insert image description here

  • Bean post-processor, there are seven steps in the bean life cycle

    1. Create bean instance through constructor (no parameter construction)
    2. Set values ​​for bean properties and references to other beans (call the set method)
    3. Pass the bean instance to the bean postprocessor method postProcessBeforeInitialization
    4. Call the bean initialization method (method that requires configuration initialization)
    5. Pass the bean instance to the method postProcessAfterInitialization of the bean postprocessor
    6. The bean is ready for use (the object is obtained)
    7. When the container is closed, the bean's destruction method is called (the destruction method needs to be configured)
  • Demonstration of adding post-processor effects

    • Create a class, implement the interface BeanPostProcessor, and create a post-processor
public class MyBeanPost implements BeanPostProcessor {
    
    
    @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) 
        throws BeansException {
    
    
        	System.out.println("在初始化之前执行的方法");
        return bean;
    }
    @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) 
        throws BeansException {
    
    
        	System.out.println("在初始化之后执行的方法");
        return bean;
    } 
}
<!--配置后置处理器--> 
<bean id="myBeanPost" class="com.atguigu.spring5.bean.MyBeanPost"></bean>

Insert image description here

Ⅶ. XML automatic assembly
  • What is autowiring

    • According to the specified assembly rules (property name or property type), spring automatically injects matching property values.
  • Demonstrate automatic assembly process

    ① Automatic injection based on attribute name

<!--实现自动装配
    bean 标签属性 autowire,配置自动装配
    autowire 属性常用两个值:
    byName 根据属性名称注入 ,注入值 bean 的 id 值和类属性名称一样
    byType 根据属性类型注入
    -->
<bean id="emp" class="com.atguigu.spring5.autowire.Emp" autowire="byName">
	<!--<property name="dept" ref="dept"></property>-->
</bean> 
<bean id="dept" class="com.atguigu.spring5.autowire.Dept"></bean>

② Automatic injection according to attribute type

<!--实现自动装配
    bean 标签属性 autowire,配置自动装配
    autowire 属性常用两个值:
    byName 根据属性名称注入 ,注入值 bean 的 id 值和类属性名称一样
    byType 根据属性类型注入
    -->
<bean id="emp" class="com.atguigu.spring5.autowire.Emp" autowire="byType">
	<!--<property name="dept" ref="dept"></property>-->
</bean> 
<bean id="dept" class="com.atguigu.spring5.autowire.Dept"></bean>
//Emp1
public class Emp1 {
    
    
    private Dept1 dept1;
    public void setDept1(Dept1 dept1) {
    
    
        this.dept1 = dept1;
    }
    @Override
    public String toString() {
    
    
        return "Emp1{" +
                "dept1=" + dept1 +
                '}';
    }
}

//Dept1
public class Dept1 {
    
    
    @Override
    public String toString() {
    
    
        return "Dept1{}";
    }
}

//Test
@Test
public void test6(){
    
    
    ApplicationContext context = new ClassPathXmlApplicationContext("bean7.xml");
    Emp1 emp1 = context.getBean("emp1", Emp1.class);
    System.out.println(emp1);
}
<!-- 属性名称自动注入 -->
<bean id="emp1" class="com.company.autowire.Emp1" autowire="byName"/>
<bean id="dept1" class="com.company.autowire.Dept1"/>
<bean id="dept2" class="com.company.autowire.Dept1"/>
Ⅷ. External property files

(1) Directly configure database information

① Configure Druid connection pool

②Introducing the Druid connection pool dependent jar package

Insert image description here

<!--直接配置连接池--> 
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
    <property name="url" value="jdbc:mysql://localhost:3306/userDb"></property>
    <property name="username" value="root"></property>
    <property name="password" value="root"></property>
</bean>

(2) Introduce external property files to configure the database connection pool

① Create an external properties file, properties format file, write database information, file name: jdbc.properties

prop.driverClass=com.mysql.jdbc.Driver
prop.url=jdbc:mysql://localhost:3306/userDb
prop.userName=root
prop.password=root

② Introduce the external properties file into the spring configuration file

<!-- 引入 context 名称空间 -->
<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:p="http://www.springframework.org/schema/p" 
    xmlns:util="http://www.springframework.org/schema/util" 
    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/util 
    http://www.springframework.org/schema/util/spring-util.xsd 
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context.xsd">

③ Use tags in the spring configuration file to introduce external property files

<!--引入外部属性文件--> 
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--配置连接池--> 
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="driverClassName" value="${prop.driverClass}"></property>
    <property name="url" value="${prop.url}"></property>
    <property name="username" value="${prop.userName}"></property>
    <property name="password" value="${prop.password}"></property>
</bean>

5. IOC operation bean management (based on annotation method)

Ⅰ. What is annotation?
  • Annotations are special marks in code, format: @annotation name (attribute name=attribute value, attribute name=attribute value...)
  • Use annotations, which act on classes, methods, and attributes.
  • Purpose of using annotations: simplify xml configuration
Ⅱ. Spring provides annotations for objects created in Bean management.
  • @Component
  • @Service
  • @Controller
  • @Repository

注意:上面四个注解功能是一样的,都可以用来创建 bean 实例

Ⅲ. Implement object creation based on annotation

The first step is to introduce dependencies

Insert image description here

Step 2: Enable component scanning

<!--开启组件扫描
    1 如果扫描多个包,多个包使用逗号隔开
    2 扫描包上层目录
    -->
<context:component-scan base-package="com.atguigu"></context:component-scan>

The third step is to create a class and add the create object annotation to the class.

//在注解里面 value 属性值可以省略不写,
//默认值是类名称,首字母小写
//UserService -- userService
@Component(value = "userService") //<bean id="userService" class=".."/>
public class UserService {
    
    
    public void add() {
    
    
    	System.out.println("service add.......");
    } 
}
Ⅳ. Turn on detailed configuration of component scanning
<!--示例 1
    use-default-filters="false" 表示现在不使用默认 filter,自己配置 filter
    context:include-filter ,设置扫描哪些内容
	type="annotation"  表示根据注解扫描
    -->
<context:component-scan base-package="com.atguigu" use-default-filters="false">
	<context:include-filter type="annotation" 										expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!--注:表示只扫描所有带Controller类的注解-->
<!--示例 2
     下面配置扫描包所有内容
     context:exclude-filter: 设置哪些内容不进行扫描
	 type="annotation"  表示根据注解扫描
    -->
<context:component-scan base-package="com.atguigu">
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!--注:表示在com.atguigu包中扫描全部,但不扫描所有带Controller类的注解-->
Ⅴ. Implement attribute injection based on annotation
  • @Autowired: Autowiring based on property type

The first step is to create service and dao objects, and add object creation annotations to the service and dao classes.

The second step is to inject the dao object into the service, add the dao type attribute to the service class, and use annotations on the attribute.

//testService
@Service
public class TestService {
    
    
    //定义dao类型属性
    //不需要添加et方法,因为内部已经封装
    //添加注入属性注解
    //根据类型进行注入
    @Autowired
    private TestDao testDao;
    public void add(){
    
    
        System.out.println("testService add .........");
        testDao.add();
    }
}

//testDao接口
public interface TestDao {
    
    
    public void add();
}

//testDaoImpl
@Repository
public class TestDaoImpl implements TestDao {
    
    
    @Override
    public void add() {
    
    
        System.out.println("TestDao add  ........");
    }
}

//test
@Test
public void test7(){
    
    
    ApplicationContext context = new ClassPathXmlApplicationContext("bean10.xml");
    TestService testService = context.getBean("testService", TestService.class);
    testService.add();
}
<?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">
    <!-- 开启注解扫描 -->
    <context:component-scan base-package="com.company"/>
</beans>
  • @Qualifier: Inject based on name

The use of this @Qualifier annotation is used together with @Autowired above.

//定义 dao 类型属性
//不需要添加 set 方法
//添加注入属性注解
@Autowired //根据类型进行注入
@Qualifier(value = "testDaoImpl1") //根据名称进行注入
private TestDao testDao;
//注意:在使用 @Qualifier 是必须与 @Autowired 同时使用
  • @Resource: can be injected based on type, can be injected based on name
//@Resource //根据类型进行注入
@Resource(name = "testDaoImpl1") //根据名称进行注入
private TestDao testDao;

//注意: @Resource 与 @Autowired 相比,@Resource 为java包中的,而 @Autowired 为spring包中的,@Autowired为根据类型注入,@Resource既可以根据类型注入,也可以根据名称注入
  • @Value: Inject common type properties
@Value(value = "abc")
private String name;
Ⅵ. Complete annotation development
  • Create a configuration class to replace the xml configuration file
@Configuration //作为配置类,代理xml配置文件
@ComponentScan(basePackages = {
    
    "com.company"})
public class SpringConfig {
    
    
}
  • Write test class
@Test
public void test8(){
    
    
    //加载配置类
    ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
    TestService testService = context.getBean("testService", TestService.class);
    System.out.println(testService);
    testService.add();
}

3. AOP

1. What is AOP?

  • For aspect-oriented programming (aspect), AOP can be used to isolate various parts of the business logic, thereby reducing the coupling between the various parts of the business logic, improving the reusability of the program, and improving the efficiency of development.
  • Popular description: Add new functions to the main functions without modifying the source code.
  • Using the login example to illustrate AOP

Insert image description here

2. AOP (underlying principle)

The bottom layer of AOP uses dynamic proxy --> There are two situations of dynamic proxy

  • The first situation with an interface is to use JDK dynamic proxy.

Description: Create an interface implementation class proxy object and enhance the class method

Insert image description here

  • In the second case where there is no interface, use CGLIB dynamic generation

Description: Create a proxy object of the subclass and enhance the method of the class

Insert image description here

3. AOP (JDK dynamic proxy)

(1) Use JDK dynamic proxy and use the method in the Proxy class to create a proxy object

Insert image description here

Call newProxyInstance method

Insert image description here

The method has three parameters:

  • The first parameter, class loader
  • The second parameter is the class where the enhancement method is located. The interface implemented by this class supports multiple interfaces.
  • The third parameter, implement this interface InvocationHandler, create a proxy object, and write the enhanced part

(2) Write JDK dynamic proxy code

① Create interface and define methods

public interface UserDao {
    
    
    public int add(int a,int b);
    public String update(String id);
}

② Create interface implementation class and implementation method

public class UserDaoImpl implements UserDao {
    
    
    @Override
    public int add(int a, int b) {
    
    
    	return a+b;
    }
    @Override
    public String update(String id) {
    
    
    	return id;
    } 
}

③ Use the Proxy class to create an interface proxy object

public class JDKProxy {
    
    
    public static void main(String[] args) {
    
    
        //创建接口实现类代理对象
        Class[] interfaces = {
    
    UserDao.class};
        // Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new InvocationHandler() {
    
    
            // @Override
            // public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    
            	// return null;
            // }
        // });
    UserDaoImpl userDao = new UserDaoImpl();
    UserDao dao = (UserDao)Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao));
    int result = dao.add(1, 2);
    System.out.println("result:"+result);
    } 
}

//创建代理对象代码
class UserDaoProxy implements InvocationHandler {
    
    
    //1 把创建的是谁的代理对象,把谁传递过来
    //有参数构造传递
    private Object obj;
    public UserDaoProxy(Object obj) {
    
    
    	this.obj = obj;
	}
    //增强的逻辑
    @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);
        //方法之后
        System.out.println("方法之后执行...."+obj);
        return res;
    } 
}

4. AOP (terminology)

(1) Connection point

  • Which methods in a class can be enhanced are called connection points.

(2) Entry point

  • The methods that are actually truly enhanced are called entry points.

(3) Notification (enhanced)

  • The logical part of the actual enhancement is called the notification (enhancement).
  • There are many types of notifications:
    • Pre-notification
    • post notification
    • surround notification
    • Exception notification
    • final notice

(4) Section

  • Note: Aspects are actions
  • Apply notifications to pointcut procedures.

5. AOP operation (preparation)

(1) The Spring framework generally implements AOP operations based on AspectJ.

  • AspectJ is not a part of Spring and is an independent AOP framework. Generally, AspectJ and Spirng framework are used together to perform AOP operations.

(2) Implement AOP operations based on AspectJ

  • Implemented based on xml configuration file
  • Implemented based on annotation (use)

(3) Introduce AOP related dependencies into the project project

Insert image description here

(4) Pointcut expression

  • The role of pointcut expressions: knowing which method in which class to enhance
  • Grammatical structures: execution([权限修饰符] [返回类型] [类全路径] [方法名称]([参数列表]) )
举例 1:对 com.atguigu.dao.BookDao 类里面的 add 进行增强
execution(* com.atguigu.dao.BookDao.add(..))

举例 2:对 com.atguigu.dao.BookDao 类里面的所有的方法进行增强
execution(* com.atguigu.dao.BookDao.* (..))
    
举例 3:对 com.atguigu.dao 包里面所有类,类里面所有方法进行增强
execution(* com.atguigu.dao.*.* (..))

6. AOP operation (AspectJ annotation)

(1) Create a class and define methods in the class

public class User {
    
    
    public void add() {
    
    
    	System.out.println("add.......");
    } 
}

(2) Create an enhancement class (write enhancement logic)

//在增强类里面,创建方法,让不同方法代表不同通知类型
//增强的类
public class UserProxy {
    
    
    public void before() {
    
    //前置通知
    	System.out.println("before......");
    } 
}

(3) Configure notifications

  • In the spring configuration file, enable annotation scanning
<?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" 
    xmlns:aop="http://www.springframework.org/schema/aop" 
    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 
    http://www.springframework.org/schema/aop 
    http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 开启注解扫描 -->
<context:component-scan base-package="com.atguigu.spring5.aopanno"></context:component-scan>
  • Create User and UserProxy objects using annotations

Insert image description here

  • Add the @Aspect annotation on the enhancement class
//增强的类
@Component
@Aspect //生成代理对象
public class UserProxy {
    
    
  • Enable generation of proxy objects in the spring configuration file
<!-- 开启 Aspect 生成代理对象--> 
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

(4) Configure different types of notifications

  • In the enhanced class, add the notification type annotation as the notification method, and use the pointcut expression configuration
//增强的类
@Component
@Aspect //生成代理对象
public class UserProxy {
    
    
    //前置通知
    //@Before 注解表示作为前置通知
    @Before(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
    public void before() {
    
    
    	System.out.println("before.........");
    }
    //后置通知(返回通知)
    @AfterReturning(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
    public void afterReturning() {
    
    
    	System.out.println("afterReturning.........");
    }
    //最终通知
    @After(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
    public void after() {
    
    
    	System.out.println("after.........");
    }
    //异常通知
    @AfterThrowing(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
    public void afterThrowing() {
    
    
    	System.out.println("afterThrowing.........");
    }
    //环绕通知
    @Around(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
    
    
        System.out.println("环绕之前.........");
        //被增强的方法执行
        proceedingJoinPoint.proceed();
        System.out.println("环绕之后.........");
    } 
}

(5) Same entry point extraction

//相同切入点抽取
@Pointcut(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
public void pointdemo() {
    
    
}
//前置通知
//@Before 注解表示作为前置通知
@Before(value = "pointdemo()")
public void before() {
    
    
	System.out.println("before.........");
}

(6) If there are multiple enhancement classes that enhance the same method, set the priority of the enhancement class.

//在增强类上面添加注解 @Order(数字类型值),数字类型值越小优先级越高
@Component
@Aspect
@Order(1)
public class PersonProxy

(7) Completely developed using annotations

//创建配置类,不需要创建 xml 配置文件 
@Configuration
@ComponentScan(basePackages = {
    
    "com.atguigu"})
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class ConfigAop {
    
    
}

7. AOP operation (AspectJ configuration file)

(1) Create two classes, the enhanced class and the enhanced class, and create methods

(2) Create two class objects in the spring configuration file

<!--创建对象--> 
<bean id="book" class="com.atguigu.spring5.aopxml.Book"></bean> 
<bean id="bookProxy" class="com.atguigu.spring5.aopxml.BookProxy"></bean>

(3) Configure the entry point in the spring configuration file

<!--配置 aop 增强--> 
<aop:config>
    <!--切入点-->
    <aop:pointcut id="p" expression="execution(* com.atguigu.spring5.aopxml.Book.buy(..))"/>
    <!--配置切面-->
    <aop:aspect ref="bookProxy">
        <!--增强作用在具体的方法上-->
        <aop:before method="before" pointcut-ref="p"/>
    </aop:aspect>
</aop:config>

4. JdbcTemplate

1. Concept and preparation

(1) What is JdbcTemplate

  • The Spring framework encapsulates JDBC and uses JdbcTemplate to facilitate database operations.

(2) Preparation work

①Introduce relevant jar packages

Insert image description here

② Configure the database connection pool in the spring configuration file

<!-- 数据库连接池 --> 
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
	<property name="url" value="jdbc:mysql:///user_db" />
	<property name="username" value="root" />
	<property name="password" value="root" />
	<property name="driverClassName" value="com.mysql.jdbc.Driver" />
</bean>

③ Configure JdbcTemplate object and inject DataSource

<!-- JdbcTemplate 对象 --> 
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
	<!--注入 dataSource-->
	<property name="dataSource" ref="dataSource"></property>
</bean>

④ Create service class, create dao class, and inject jdbcTemplate object into dao

Configuration file

<!-- 组件扫描 --> 
<context:component-scan base-package="com.atguigu"></context:component-scan>

Service

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

Dao

@Repository
public class BookDaoImpl implements BookDao {
    
    
	//注入 JdbcTemplate
	@Autowired
	private JdbcTemplate jdbcTemplate; 
}

2. Add

(1) Create entity classes corresponding to the database

public class User {
    
    
    private String userId;
    private String username;
    private String ustatus;
    
    get/set....
}

(2) Write service and dao

① Perform database addition operation in dao

② Call the update method in the JdbcTemplate object to implement the adding operation

Insert image description here

  • There are two parameters
  • The first parameter: sql statement
  • The second parameter: variable parameter, set the sql statement value
@Repository
public class BookDaoImpl implements BookDao {
    
    
    //注入 JdbcTemplate
    @Autowired
    private JdbcTemplate jdbcTemplate;
    //添加的方法
    @Override
    public void add(Book book) {
    
    
        //1 创建 sql 语句
        String sql = "insert into t_book values(?,?,?)";
        //2 调用方法实现
        Object[] args = {
    
    book.getUserId(), book.getUsername(), book.getUstatus()};
        int update = jdbcTemplate.update(sql,args);
        System.out.println(update);
    } 
}

(3) Test category

@Test
public void testJdbcTemplate() {
    
    
    ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
    BookService bookService = context.getBean("bookService", BookService.class);
    Book book = new Book();
    book.setUserId("1");
    book.setUsername("java");
    book.setUstatus("a");
    bookService.addBook(book);
}

Insert image description here

3. Modify and delete

(1) Modification

@Override
public void updateBook(Book book) {
    
    
    String sql = "update t_book set username=?,ustatus=? where user_id=?";
    Object[] args = {
    
    book.getUsername(), book.getUstatus(),book.getUserId()};
    int update = jdbcTemplate.update(sql, args);
    System.out.println(update);
}

(2) Delete

@Override
public void delete(String id) {
    
    
    String sql = "delete from t_book where user_id=?";
    int update = jdbcTemplate.update(sql, id);
    System.out.println(update);
}

4. Query returns a certain value

① Query how many records there are in the table and return a certain value

② Use JdbcTemplate to implement query and return a certain value code

Insert image description here

  • There are two parameters
  • The first parameter: sql statement
  • Second parameter: return type Class
//查询表记录数
@Override
public int selectCount() {
    
    
    String sql = "select count(*) from t_book";
    Integer count = jdbcTemplate.queryForObject(sql, Integer.class);
    return count;
}

5. Query return object

① Scenario: Query book details

② JdbcTemplate implements query return objects

Insert image description here

  • There are three parameters
  • The first parameter: sql statement
  • The second parameter: RowMapper is an interface. To return different types of data, use the classes implemented in this interface to complete data encapsulation.
  • The third parameter: sql statement value
//查询返回对象
@Override
public Book findBookInfo(String id) {
    
    
    String sql = "select * from t_book where user_id=?";
    //调用方法
    Book book = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<Book>(Book.class), id);
    return book;
}

6. Query returns collection

① Scenario: Query book list pagination...

② Call the JdbcTemplate method to implement the query and return the collection

Insert image description here

  • There are three parameters
  • The first parameter: sql statement
  • The second parameter: RowMapper is an interface. To return different types of data, use the classes implemented in this interface to complete data encapsulation.
  • The third parameter: sql statement value
//查询返回集合
@Override
public List<Book> findAllBook() {
    
    
    String sql = "select * from t_book";
    //调用方法
    List<Book> bookList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<Book>(Book.class));
    return bookList;
}

7. Batch operation

(1) Batch operation: multiple records in the operation table

① JdbcTemplate implements batch addition operations

Insert image description here

  • There are two parameters
  • The first parameter: sql statement
  • Second parameter: List collection, add multiple record data
//批量添加
@Override
public void batchAddBook(List<Object[]> batchArgs) {
    
    
    String sql = "insert into t_book values(?,?,?)";
    int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);
    System.out.println(Arrays.toString(ints));
}

//批量添加测试
List<Object[]> batchArgs = new ArrayList<>();
Object[] o1 = {
    
    "3","java","a"};
Object[] o2 = {
    
    "4","c++","b"};
Object[] o3 = {
    
    "5","MySQL","c"};
batchArgs.add(o1);
batchArgs.add(o2);
batchArgs.add(o3);
//调用批量添加
bookService.batchAdd(batchArgs);

② JdbcTemplate implements batch modification operations

//批量修改
@Override
public void batchUpdateBook(List<Object[]> batchArgs) {
    
    
    String sql = "update t_book set username=?,ustatus=? where user_id=?";
    int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);
    System.out.println(Arrays.toString(ints));
}

//批量修改
List<Object[]> batchArgs = new ArrayList<>();
Object[] o1 = {
    
    "java0909","a3","3"};
Object[] o2 = {
    
    "c++1010","b4","4"};
Object[] o3 = {
    
    "MySQL1111","c5","5"};
batchArgs.add(o1);
batchArgs.add(o2);
batchArgs.add(o3);
//调用方法实现批量修改
bookService.batchUpdate(batchArgs);

③ JdbcTemplate implements batch deletion operations

//批量删除
@Override
public void batchDeleteBook(List<Object[]> batchArgs) {
    
    
    String sql = "delete from t_book where user_id=?";
    int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);
    System.out.println(Arrays.toString(ints));
}

//批量删除
List<Object[]> batchArgs = new ArrayList<>();
Object[] o1 = {
    
    "3"};
Object[] o2 = {
    
    "4"};
batchArgs.add(o1);
batchArgs.add(o2);
//调用方法实现批量删除
bookService.batchDelete(batchArgs);

5. Transaction operations

1. Business concept

(1) What is a transaction?

① Transaction is the most basic unit of database operation. Logically, a group of operations will either succeed. If one fails, all operations will fail.

② Typical scenario: bank transfer

  • lucy transfers 100 yuan to mary
  • Lucy is 100 less, Mary is 100 more

(2) Four characteristics of transactions (ACID)

  • atomicity
  • consistency
  • Isolation
  • persistence

2. Build a transaction operating environment

Insert image description here
(1) Create a database table and add records

Insert image description here

(2) Create service, build dao, complete object creation and injection relationship

  • Service injects dao, injects JdbcTemplate in dao, injects DataSource in JdbcTemplate
@Service
public class UserService {
    
    
	//注入 dao
    @Autowired
    private UserDao userDao; 
}

@Repository
public class UserDaoImpl implements UserDao {
    
    
    @Autowired
    private JdbcTemplate jdbcTemplate; 
}

(3) Create two methods in dao: more money and less money methods, and create a method in service (transfer method)

@Repository
public class UserDaoImpl implements UserDao {
    
    
    @Autowired
    private JdbcTemplate jdbcTemplate;
    //lucy 转账 100 给 mary
    //少钱
    @Override
    public void reduceMoney() {
    
    
        String sql = "update t_account set money=money-? where username=?";
        jdbcTemplate.update(sql,100,"lucy");
    }
 	//多钱
    @Override
    public void addMoney() {
    
    
        String sql = "update t_account set money=money+? where username=?";
        jdbcTemplate.update(sql,100,"mary");
    } 
}

@Service
public class UserService {
    
    
    //注入 dao
    @Autowired
    private UserDao userDao;
    //转账的方法
    public void accountMoney() {
    
    
        //lucy 少 100
        userDao.reduceMoney();
        //mary 多 100
        userDao.addMoney();
    } 
}

(4) If the above code is executed normally, there will be no problem. However, if an exception occurs during the execution of the code, there will be a problem.

//转账的方法
public void accountMoney() {
    
    
	//lucy少100
    userDao.reduceMoney();
    //模拟异常
    int i = 10/0;
    //mary多100
    userDao.addMoney();
}

① How to solve the above problem? Use transactions to resolve

② Transaction operation process

//转账的方法
public void accountMoney() {
    
    
	try {
    
    
        //第一步 开启事务
        //第二步 进行业务操作
        //lucy少100
        userDao.reduceMoney();
        //模拟异常
        int i = 10/0;
        //mary多100
        userDao.addMoney();
        //第三步 没有发生异常,提交事务
    } catch(Exception e) {
    
    
        //第四步 出现异常,事务回滚
    }
}

3. Introduction to Spring transaction management

(1) Transactions are added to the Service layer (business logic layer) in the JavaEE three-tier structure

(2) Perform transaction management operations in Spring

  • There are two ways: programmatic transaction management and declarative transaction management (use)

(3) Declarative transaction management

  • Based on annotation method (use)
  • Based on xml configuration file method

(4) Declarative transaction management in Spring, using AOP principles at the bottom

(5) Spring transaction management API

  • Provides an interface representing the transaction manager. This interface provides different implementation classes for different frameworks.

Insert image description here

4. Annotation declarative transaction management

(1) Configure the transaction manager in the spring configuration file

<!--创建事务管理器--> 
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <!--注入数据源-->
    <property name="dataSource" ref="dataSource"></property>
</bean>

(2) In the spring configuration file, enable transaction annotations

① Introduce the namespace tx into the spring configuration file

<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" 
    xmlns:aop="http://www.springframework.org/schema/aop" 
    xmlns:tx="http://www.springframework.org/schema/tx" 
    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 
    http://www.springframework.org/schema/aop 
    http://www.springframework.org/schema/aop/spring-aop.xsd 
    http://www.springframework.org/schema/tx 
    http://www.springframework.org/schema/tx/spring-tx.xsd">

② Turn on transaction annotations

<!--开启事务注解--> 
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>

(3) Add transaction annotations on the service class (or on the methods in the service class)

  • @Transactional, this annotation is added to the class, and can also be added to the method.
  • If you add this annotation to a class, all methods in this class will add transactions.
  • If you add this annotation to the method, add a transaction for this method
@Service
@Transactional
public class UserService {
    
    

5. Declarative transaction management parameter configuration

(1) Add the annotation @Transactional to the service class. In this annotation, transaction-related parameters can be configured.

Insert image description here

(2) propagation: transaction propagation behavior

  • Multi-transaction methods are directly called. How are transactions managed during this process?

Insert image description here

Insert image description here

@Service
@Transactional(propagation = Propagation.REQUIRED)
public class UserService {
    
    

(3) ioslation: transaction isolation level

  • The characteristic of transactions is called isolation, which affects multiple transaction operations. Failure to consider isolation will cause many problems
  • There are three reading problems: dirty reading, non-repeatable reading, and virtual (phantom) reading.
  • Dirty read: One uncommitted transaction reads data from another uncommitted transaction

Insert image description here

(4) Non-repeatable read: An uncommitted transaction reads modified data from another committed transaction

Insert image description here

(5) Virtual reading: An uncommitted transaction reads data from another submitted transaction to add data

(6) Solution: Solve the read problem by setting the transaction isolation level

Insert image description here

@Service
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ)
public class UserService {
    
    

(7) timeout: timeout time

  • The transaction needs to be submitted within a certain period of time. If it is not submitted, it will be rolled back.
  • The default value is -1, which means there is no timeout, and the setting time is calculated in seconds.

(8) readOnly: whether it is read-only

  • Read: query operation, write: add, modify, delete operation
  • The default value of readOnly is false, which means it can be queried, and modification and deletion operations can be added.
  • Set the readOnly value to true. After setting it to true, you can only query

(9) rollbackFor: rollback

  • Set which exceptions occur for transaction rollback

(10) noRollbackFor: No rollback

  • Set which exceptions will not be rolled back

6. XML declarative transaction management

(1) Configure in the spring configuration file

  • The first step is to configure the transaction manager
  • Step 2: Configure notifications
  • Step 3: Configure entry points and aspects
<!--1 创建事务管理器--> 
<bean id="transactionManager" 
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <!--注入数据源-->
    <property name="dataSource" ref="dataSource"></property>
</bean>

<!--2 配置通知--> 
<tx:advice id="txadvice">
    <!--配置事务参数-->
    <tx:attributes>
        <!--指定哪种规则的方法上面添加事务-->
        <tx:method name="accountMoney" propagation="REQUIRED"/>
        <!--<tx:method name="account*"/>-->
    </tx:attributes>
</tx:advice>

<!--3 配置切入点和切面--> 
<aop:config>
    <!--配置切入点-->
    <aop:pointcut id="pt" expression="execution(* com.atguigu.spring5.service.UserService.*(..))"/>
    <!--配置切面-->
    <aop:advisor advice-ref="txadvice" pointcut-ref="pt"/>
</aop:config>

7. Fully annotated declarative transaction management

(1) Create a configuration class and use the configuration class to replace the xml configuration file

@Configuration //配置类
@ComponentScan(basePackages = "com.atguigu") //组件扫描
@EnableTransactionManagement //开启事务
public class TxConfig {
    
    
    //创建数据库连接池
    @Bean
    public DruidDataSource getDruidDataSource() {
    
    
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql:///user_db");
        dataSource.setUsername("root");
        dataSource.setPassword("root");
        return dataSource;
    }

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

    //创建事务管理器
    @Bean
    public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource) {
    
    
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
        transactionManager.setDataSource(dataSource);
        return transactionManager;
    } 
}

6. New features of Spring5 framework

1. Framework optimization

  • The code of the entire Spring5 framework is based on Java8 and is runtime compatible with JDK9. Many deprecated classes and methods have been deleted from the code base.

2. The Spring 5.0 framework comes with a universal log encapsulation

  • Spring5 has removed Log4jConfigListener, and the official recommendation is to use Log4j2
  • Spring5 framework integrates Log4j2

The first step is to introduce the jar package

Insert image description here

The second step is to create the log4j2.xml configuration file

<?xml version="1.0" encoding="UTF-8"?>
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--Configuration 后面的 status 用于设置 log4j2 自身内部的信息输出,可以不设置,当设置成 trace 时,可以看到 log4j2 内部各种详细输出--> 
<configuration status="INFO">
    <!--先定义所有的 appender-->
    <appenders>
        <!--输出日志信息到控制台-->
        <console name="Console" target="SYSTEM_OUT">
            <!--控制日志输出的格式-->
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </console>
    </appenders>
    <!--然后定义 logger,只有定义 logger 并引入的 appender,appender 才会生效-->
    <!--root:用于指定项目的根日志,如果没有单独指定 Logger,则会使用 root 作为默认的日志输出-->
    <loggers>
        <root level="info">
        	<appender-ref ref="Console"/>
        </root>
    </loggers>
</configuration>

3. Spring5 framework core container supports @Nullable annotation

① @Nullable annotation can be used on methods, properties, and parameters, indicating that the method return can be null, the attribute value can be null, and the parameter value can be null

② Annotations are used on methods, and the return value of the method can be empty.

@Nullable
String getId();

③ Annotations are used in method parameters, and method parameters can be empty.

Insert image description here

④ Annotations are used on attributes, and the attribute value can be empty.

Insert image description here

4. Spring5 core container supports functional style GenericApplicationContext

//函数式风格创建对象,交给 spring 进行管理
@Test
public void testGenericApplicationContext() {
    
    
    //1 创建 GenericApplicationContext 对象
    GenericApplicationContext context = new GenericApplicationContext();
    //2 调用 context 的方法对象注册
    context.refresh();
    context.registerBean("user1",User.class,() -> new User());
    //3 获取在 spring 注册的对象
    // User user = (User)context.getBean("com.atguigu.spring5.test.User");
    User user = (User)context.getBean("user1");
    System.out.println(user);
}

5. Spring5 supports integrating JUnit5

(1) Integrate JUnit4

The first step is to introduce Spring-related test dependencies

Insert image description here

The second step is to create a test class and use annotations to complete it.

@RunWith(SpringJUnit4ClassRunner.class) //单元测试框架
@ContextConfiguration("classpath:bean1.xml") //加载配置文件
public class JTest4 {
    
    
    @Autowired
    private UserService userService;
    @Test
    public void test1() {
    
    
    	userService.accountMoney();
    } 
}

(2) Spring5 integrates JUnit5

The first step is to introduce the jar package of JUnit5

Insert image description here

The second step is to create a test class and use annotations to complete it.

@ExtendWith(SpringExtension.class)
@ContextConfiguration("classpath:bean1.xml")
public class JTest5 {
    
    
    @Autowired
    private UserService userService;
    @Test
    public void test1() {
    
    
    	userService.accountMoney();
    } 
}

(3) Use a composite annotation to replace the above two annotations to complete the integration

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

7. Webflux

1. Introduction to Spring Webflux

(1) Spring5 adds a new module for web development. Its functions are similar to SpringMVC. Webflux uses a current framework that compares with the emergence of process-responsive programming.

Insert image description here

(2) Use traditional web frameworks, such as SpringMVC, which are based on Servlet containers. Webflux is an asynchronous non-blocking framework. The asynchronous non-blocking framework is only supported after Servlet3.1. The core is implemented based on the relevant API of Reactor.

(3) Explain what asynchronous non-blocking is

Asynchronous and synchronous / non-blocking and blocking

The above are all for different objects:

  • Asynchronous and synchronous are for the caller. The caller sends a request. If the caller waits for the other party to respond before doing other things, it is synchronous. If the caller sends the request and then does other things without waiting for the other party to respond, it is asynchronous.
  • Blocking and non-blocking are for the callee. After the callee receives the request, it will give feedback after completing the requested task. It is blocking. After receiving the request, it will give feedback immediately and then do things. It is non-blocking.

(4) Webflux features

  • The first non-blocking style: improve system throughput and scalability under limited resources, and implement responsive programming based on Reactor

  • Second functional programming: Spring5 framework is based on java8, Webflux uses Java8 functional programming to implement routing requests

(5) Compare SpringMVC

Insert image description here

  • Both the first and second frameworks can use annotations and both run in containers such as Tomet.
  • Second, SpringMVC uses imperative programming, and Webflux uses asynchronous reactive programming.

2. Reactive programming (Java implementation)

(1) What is reactive programming?

Reactive programming is a programming paradigm oriented toward data flow and change propagation. This means that static or dynamic data flows can be easily expressed in programming languages, and the associated computing model will automatically propagate changing values ​​through the data flow. Spreadsheet programs are an example of reactive programming. Cells can contain literal values ​​or formulas like "=B1+C1", and the value of the cell containing the formula will change based on the changes in the values ​​of other cells.

(2) Java8 and previous versions

The observer pattern provides two classes Observer and Observable

public class ObserverDemo extends Observable {
    
    
    public static void main(String[] args) {
    
    
        ObserverDemo observer = new ObserverDemo();
        //添加观察者
        observer.addObserver((o,arg)->{
    
    
            System.out.println("发生变化");
        });
        observer.addObserver((o,arg)->{
    
    
            System.out.println("手动被观察者通知,准备改变");
        });
        observer.setChanged(); //数据变化
        observer.notifyObservers(); //通知
    } 
}

3. Reactive programming (Reactor implementation)

(1) In reactive programming operations, Reactor meets the Reactive specification framework

(2) Reactor has two core classes, Mono and Flux. These two classes implement the interface Publisher and provide rich operators. The Flux object implements the publisher and returns N elements; the Mono object implements the publisher and returns 0 or 1 elements.

(3) Both Flux and Mono are publishers of data streams. Both Flux and Mono can send out three data signals: element value, error signal, completion signal. Both error signal and completion signal represent termination signals. The termination signal is used to tell The subscriber data flow ends. The error signal terminates the data flow and passes the error message to the subscriber.

Insert image description here

(4) Code demonstration Flux and Mono

The first step is to introduce dependencies

<dependency>
     <groupId>io.projectreactor</groupId>
     <artifactId>reactor-core</artifactId>
     <version>3.1.5.RELEASE</version>
</dependency>

Second step programming code

public static void main(String[] args) {
    
    
    //just 方法直接声明
    Flux.just(1,2,3,4);
    Mono.just(1);
    //其他的方法
    Integer[] array = {
    
    1,2,3,4};
    Flux.fromArray(array);

    List<Integer> list = Arrays.asList(array);
    Flux.fromIterable(list);
    Stream<Integer> stream = list.stream();
    Flux.fromStream(stream);
}

(5) Three signal characteristics

  • The error signal and completion signal are both termination signals and cannot coexist.
  • If no element value is sent, but an error or completion signal is sent directly, it indicates an empty data stream.
  • If there is no error signal and no completion signal, it means unlimited data flow.

(6) Calling just or other methods only declares the data flow. The data flow is not sent out. The data flow will only be triggered after subscribing. If you do not subscribe, nothing will happen.

//just方法直接声明
Flux.just(1,2,3,4).subscribe(System.out::print);
Mono.just(1).subscribe(System.out::print);

(7) Operator

Perform operations on the data flow one by one to become operators, such as factory assembly lines

  • The first map element is mapped to a new element

Insert image description here

  • The second flatMap element is mapped to the stream
  • Convert each element into a stream and merge the converted streams into a larger stream

Insert image description here

4. Spring Webflux execution process and core API

  • SpringWebflux is based on Reactor. The default container is Netty. Netty is a high-performance NIO framework, an asynchronous and non-blocking framework.

(1)Netty

  • BIO

Insert image description here

  • NIO

Insert image description here

(2) The execution process of SpringWebflux is similar to SpringMVC

SpringWebflux core controller DispatchHandler implements the interface WebHandler

The interface WebHandler has a method

public interface WebHandler {
    
    
    Mono<Void> handle(ServerWebExchange varl);
}

public Mono<Void> handle(ServerWebExchange exchange) {
    
      //放http请求响应请求
    return this.handlerMappings == null ? this.createNotFoundError() : Flux.fromIterable(this.handlerMappings{
    
    
        return mapping.getHandler(exchange);  //根据请求地址获取对应mapping
    }).next().switchIfEmpty(this.createNotFoundError()).faltMap((handler) -> {
    
    
        return this.invokeHandler(exchange, handler);  //调用具体业务方法
    }).flatMap((result) -> {
    
    
        return this.handleResult(exchange, result);  //处理结果返回
    });
}

(3) DispatcherHandler in SpringWebflux is responsible for request processing

  • HandlerMapping: request query to processing method
  • HandlerAdapter: really responsible for request processing
  • HandlerResultHandler: response result processing

(4) Spring Webflux implements functional programming, two interfaces: RouterFunction (routing processing) and HandlerFunction (processing function)

5. Spring Webflux (based on annotation programming model)

There are two ways to implement Spring Webflux: the annotation programming model and the functional programming model. The annotation programming model is similar to the previous SpringMVC. You only need to configure the relevant dependencies into the project. SpringBoot automatically configures the relevant running containers. Netty is used by default. server

The first step is to create a SpringBoot project and introduce Webflux dependencies

Insert image description here

<dependency>
	<groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

The second step is to configure the startup port number

Insert image description here

Step 3 Create packages and related classes

//实体类
public class User {
    
    
	private String name;
	private String gender;
	private Integer age;
    
    public User(String name, String gender, Integer age) {
    
    
        this.name = name;
        this.gender = gender;
        this.age = age;	
    }
}
//创建接口定义操作的方法
//用户操作接口
public interface UserService {
    
    
    //根据 id 查询用户
    Mono<User> getUserById(int id);
    //查询所有用户
    Flux<User> getAllUser();
    //添加用户
    Mono<Void> saveUserInfo(Mono<User> user);
}
//接口实现类
public class UserServiceImpl implements UserService {
    
    
    //创建 map 集合存储数据
    private final Map<Integer,User> users = new HashMap<>();
    public UserServiceImpl() {
    
    
        this.users.put(1,new User("lucy","nan",20));
        this.users.put(2,new User("mary","nv",30));
        this.users.put(3,new User("jack","nv",50));
    }
    //根据 id 查询
    @Override
    public Mono<User> getUserById(int id) {
    
    
    	return Mono.justOrEmpty(this.users.get(id));
    }
    //查询多个用户
    @Override
    public Flux<User> getAllUser() {
    
    
    	return Flux.fromIterable(this.users.values());
    }
    //添加用户
    @Override
    public Mono<Void> saveUserInfo(Mono<User> userMono) {
    
    
        return userMono.doOnNext(person -> {
    
    
        	//向 map 集合里面放值
            int id = users.size()+1;
            users.put(id,person);
        }).thenEmpty(Mono.empty());
    } 
}
//创建 controller
@RestController
public class UserController {
    
    
    //注入 service
    @Autowired
    private UserService userService;
    //id 查询
    @GetMapping("/user/{id}")
    public Mono<User> geetUserId(@PathVariable int id) {
    
    
    	return userService.getUserById(id);
    }
    //查询所有
    @GetMapping("/user")
    public Flux<User> getUsers() {
    
    
    	return userService.getAllUser();
    }
    //添加
    @PostMapping("/saveuser")
    public Mono<Void> saveUser(@RequestBody User user) {
    
    
        Mono<User> userMono = Mono.just(user);
        return userService.saveUserInfo(userMono);
    } 
}

illustrate

  • SpringMVC method implementation, synchronous blocking method, based on SpringMVC+Servlet+Tomcat
  • Implemented in SpringWebflux mode, asynchronous and non-blocking, based on SpringWebflux+Reactor+Netty

6. Spring Webflux (based on functional programming model)

(1) When operating using the functional programming model, you need to initialize the server yourself

(2) Based on the functional programming model, there are two core interfaces: RouterFunction (which implements the routing function and forwards requests to the corresponding handler) and HandlerFunction (which processes requests and generates responses). The core tasks define the implementation of the two functional interfaces. And start the required servers.

(3) Spring Webflux requests and responses are no longer ServletRequest and ServletResponse, but ServerRequest and ServerResponse

The first step is to copy the annotation programming model project and keep the entity and service contents.

The second step is to create Handler (specific implementation method)

public class UserHandler {
    
    
    private final UserService userService;
    public UserHandler(UserService userService) {
    
    
        this.userService = userService;
    }
    //根据 id 查询
    public Mono<ServerResponse> getUserById(ServerRequest request) {
    
    
        //获取 id 值
        int userId = Integer.valueOf(request.pathVariable("id"));
        //空值处理
        Mono<ServerResponse> notFound = ServerResponse.notFound().build();
        //调用 service 方法得到数据
        Mono<User> userMono = this.userService.getUserById(userId);
        //把 userMono 进行转换返回
        //使用 Reactor 操作符 flatMap
        return userMono.flatMap(person -> 
        ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(fromObject(person)))
        .switchIfEmpty(notFound);
    }
    //查询所有
    public Mono<ServerResponse> getAllUsers() {
    
    
        //调用 service 得到结果
        Flux<User> users = this.userService.getAllUser();
        return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(users,User.cl
        ass);
    }
    //添加
    public Mono<ServerResponse> saveUser(ServerRequest request) {
    
    
        //得到 user 对象
        Mono<User> userMono = request.bodyToMono(User.class);
        return ServerResponse.ok().build(this.userService.saveUserInfo(userMono));
    } 
}

The third step is to initialize the server and write the Router

/*
* 创建路由的方法
*/
//1 创建 Router 路由
public RouterFunction<ServerResponse> routingFunction() {
    
    
	//创建 hanler 对象
    UserService userService = new UserServiceImpl();
    UserHandler handler = new UserHandler(userService);
    //设置路由
    return RouterFunctions.route(
    GET("/users/{id}").and(accept(APPLICATION_JSON)),handler::getUserById).andRoute(GET("/users").and(accept(APPLICATION_JSON)),handler::getAllUsers);
}

/*
* 创建服务器完成适配
*/
//2 创建服务器完成适配
public void createReactorServer() {
    
    
    //路由和 handler 适配
    RouterFunction<ServerResponse> route = routingFunction();
    HttpHandler httpHandler = toHttpHandler(route);
    ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler);
    //创建服务器
    HttpServer httpServer = HttpServer.create();
    httpServer.handle(adapter).bindNow();
}

/*
* 最终调用
*/
public static void main(String[] args) throws Exception{
    
    
    Server server = new Server();
    server.createReactorServer();
    System.out.println("enter to exit");
    System.in.read();
}

(4) Call using WebClient

public class Client {
    
    
    public static void main(String[] args) {
    
    
        //调用服务器地址
        WebClient webClient = WebClient.create("http://127.0.0.1:5794");
        //根据 id 查询
        String id = "1";
        User userresult = webClient.get().uri("/users/{id}", id).accept(MediaType.APPLICATION_JSON).retrieve().bodyToMono(User.class).block();
        System.out.println(userresult.getName());
        //查询所有
        Flux<User> results = webClient.get().uri("/users").accept(MediaType.APPLICATION_JSON).retrieve().bodyToFlux(User.class);
        results.map(stu -> stu.getName()).buffer().doOnNext(System.out::println).blockFirst();
	} 
}

8. Course Summary

1. Overview of Spring Framework

  • A lightweight open source JavaEE framework, in order to solve enterprise complexity, consists of two core components: IOC and AOP
  • Spring5.2.6 version

2. IOC container

  • The underlying principles of IOC (factory, reflection, etc.)
  • IOC interface (BeanFactory)
  • IOC operation bean management (based on xml)
  • IOC operation bean management (based on annotations)

3、Aop

  • The underlying principle of AOP: dynamic proxy, with interface (JDK dynamic proxy), without interface (CGLIB dynamic proxy)
  • Terminology: pointcut, enhancement (notification), aspect
  • Implement AOP operations based on AspectJ

4、JdbcTemplate

  • Use JdbcTemplate to implement database curd operation
  • Use JdbcTemplate to implement database batch operations

5. Affairs management

  • transaction concept
  • Important concepts (propagation behavior and isolation levels)
  • Declarative transaction management based on annotations
  • Completely annotated approach to declarative transaction management

6. Spring5 new features

  • Integrated logging framework
  • @Nullable annotation
  • Functional registration object
  • Integrate JUnit5 unit testing framework
  • SpringWebflux uses

Guess you like

Origin blog.csdn.net/weixin_45888036/article/details/131437187
Recommended