Spring -- Introduction (taking version 5.2 as an example)

Keywords: Java Spring

The notes of this article are compiled from the video https://www.bilibili.com/video/BV1Vf4y127N5

1. Overview of spring framework

(1) Spring is a lightweight open source Java EE framework, which can solve the complexity of enterprise application development.
(2) Spring has two core parts: IoC and Aop

IoCControl inversion, and leave the process of creating objects to Spring for management
AopAspect oriented, without modifying the source code for function enhancement

(3) Spring has the following features:
① Convenient decoupling and simplified development
② Aop programming support
③ Convenient program testing
④ Facilitate integration with other frameworks
⑤ Facilitate transaction operations
⑥ Reduce the difficulty of API development

2. Introduction to spring

(1) Download spring 5, address htt is ps://repo.spring.io/ui/native/release/org/springframework/spring/ , select version 5.26


(2) Create a common Java project in the IDEA and import the required jar package. It should be noted that the commons-logging-1.1.1.jar is not provided by Spring itself and needs to be downloaded separately

You also need to add these dependencies to your project

(3) Write code
Define the class User, and define the method add()

package com.atguigu.spring5;

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

Write the configuration file bean1.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--to configure User objects creating-->
    <bean id="user" class="com.atguigu.spring5.User"></bean>

</beans>

Writing test methods

package com.atguigu.spring5.TestDemo;

import com.atguigu.spring5.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestSpring5 {

    @Test
    public void testAdd(){
        //1. Load the spring configuration file
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        //2. Get the object created by the configuration, which reflects the IoC control inversion, that is, the object creation process is handed over to Spring for management
        User user = context.getBean("user", User.class);
        System.out.println(user);
        user.add();
    }

}

(4) Result output

3.IoC introduction

(1) IoC overview

IoC, its full English name is Inversion of Control, that is, control inversion. Spring manages the object creation and the calling process between objects, which can reduce the coupling. The above entry case is a simple implementation of IoC.

(2) IoC underlying principle

(2.1) the main technologies involved in the underlying principle of IoC include xml parsing, factory schema and reflection
(2.2) IoC process:
① Configure the created object in the xml configuration file

<bean id="user" class="com.atguigu.spring5.User"></bean>

② Create a factory class with service class and dao class (the IoC idea is based on the IoC container, and the underlying layer of the IoC container is the object factory)

class UserFact ory {
	public static UserDao getDao(){
		//xml parsing
		String classValue = class Attribute value;
		//Create objects by reflection
		Class clazz = Class.forName(classValue);
		//Return object
		return (UserDao)clazz.newInstance();
	}
}

(3) IoC interface

Spring provides two ways to implement IOC container (two interfaces):
① BeanFactory: the basic implementation of IOC container, which is the internal use interface of Spring. It is generally not provided for developers to use. The object will not be created when loading the configuration file, but will be created only after the object is obtained (used).
② ApplicationContext: the sub interface of BeanFactory interface, which provides more and more powerful functions and is generally used by developers. When the configuration file is loaded, the configuration file object will be created. In addition, the ApplicationContext interface has implementation classes:

4.IoC operation - Bean management

(1) Bean Management Overview

Bean management refers to two operations, namely, Spring creating objects and Spirng injecting attributes.
There are two ways to manage Bean operations, namely, based on xml configuration file and based on annotation.

(2) Bean management -- xml based configuration

① Creating objects based on xml

<!--
	(1)stay spring In the configuration file, use bean Tag. Add corresponding attributes in the tag to realize object creation
	(2)stay bean The tag has many attributes. Common attributes are introduced:
	* id Attribute: unique identification
	* class Properties: full classpath (package classpath)
	(3)When creating an object, the default is to execute the parameterless construction method to complete the object creation
-->
<bean id="user" class="com.atguigu.spring5.User"></bean>

② Attribute injection based on xml

Here we need to know a concept - DI (Dependency Injection), that is, Dependency Injection, that is, injection attributes.
The first injection method: use the set method for injection

//Create a class, define properties and corresponding set methods
public class Book {
	//Create attribute
	private String bname;
	private String bauthor;
	//Create the set method corresponding to the property
	public void setBname(String bname) {
		this.bname = bname;
	}
	public void setBauthor(String bauthor) {
		this.bauthor = bauthor;
	} 
	//Test set method injection
    public void testSet(){
        System.out.println("bname:"+bname);
        System.out.println("bauthor:"+bauthor);
    }
}
<!--stay spring Configuration file, configuration object creation, configuration attribute injection--> 
<bean id="book" class="com.atguigu.spring5.Book">
	 <!--
	 	use property Complete attribute injection
	 	name: Attribute name in class
		value: Values injected into attributes
	 -->
	<property name="bname" value="Journey to the West"></property>
	<property name="bauthor" value="Wu Chengen"></property>
</bean>
package com.atguigu.spring5.TestDemo;

import com.atguigu.spring5.Book;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

//test
public class TestSpring5 {
    @Test
    public void test(){
        //1. Load the spring configuration file
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        //2. Get the object created by configuration
        Book book = context.getBean("book", Book.class);
        System.out.println(book);
        book.testSet();
    }
}

The results are as follows:

The second injection method: injection with parameter structure

package com.atguigu.spring5;

public class Order{
    //attribute
    private String oname;
    private String address;
    //Parametric construction
    public Order(String oname,String address) {
        this.oname = oname;
        this.address = address;
    }
    
    public void testconstructorArg(){
        System.out.println("oname:"+oname);
        System.out.println("address:"+address);
    }
}
<!--Injection attribute with parameter construction-->
<bean id="order" class="com.atguigu.spring5.Order">
    <constructor-arg name="oname" value="computer"></constructor-arg>
    <constructor-arg name="address" value="China"></constructor-arg>
</bean>
package com.atguigu.spring5.TestDemo;

import com.atguigu.spring5.Order;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

//test
public class TestSpring5 {
    @Test
    public void testAdd(){
        //1. Load the spring configuration file
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        //2. Get the object created by configuration
        Order order = context.getBean("order", Order.class);
        System.out.println(order);
        order.testconstructorArg();
    }
}

The results are as follows:

The third injection method: p namespace injection (a simplification of the first method)
Add a p namespace to the configuration file

<!--Perform attribute injection in bean Operate inside the label--> 
<bean id="book" class="com.atguigu.spring5.Book" p:bname="Journey to the West" p:bauthor="Wu Chengen"></bean>

③ Inject null values and values containing special symbols based on xml

<!--(1)null value--> 
<property name="address">
	<null/>
</property>
<!--
	(2)The attribute value contains special symbols. The processing method is as follows:
 	Escape special symbols, such as using &lt; or &gt; hold<>Escape 
 	Write content with special symbols to CDATA
-->
<property name="address">
	<value><![CDATA[<<Hangzhou>>]]></value>
</property>

④ Injecting external bean s based on xml

package com.atguigu.spring5.dao;

public interface UserDao {
    void update();
}
package com.atguigu.spring5.dao;

public class UserDaoImpl implements UserDao {
    @Override
    public void update() {
        System.out.println("dao update...");
    }
}
package com.atguigu.spring5.service;

import com.atguigu.spring5.dao.UserDao;

public class UserService {
    //Create UserDao type attribute and generate set method
    private UserDao userDao;
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    public void add() {
        System.out.println("service add...............");
        userDao.update();
    }
}
<!--establish service and dao object-->
<bean id="userService" class="com.atguigu.spring5.service.UserService">
	<!--
		injection userDao object
		name Attribute: the name of the attribute in the class
		ref Properties: Creating userDao object bean label id value
	-->
    <property name="userDao" ref="userDaoImpl"></property>
</bean>
<bean id="userDaoImpl" class="com.atguigu.spring5.dao.UserDaoImpl"></bean>

⑤ Injecting internal bean s based on xml

package com.atguigu.spring5.bean;

public class Dept {
    private String dname;
    public void setDname(String dname) {
        this.dname = dname;
    }
}
package com.atguigu.spring5.bean;

public class Emp {
    private String ename;
    private String gender;
    //Employees belong to a department and are represented in object form
    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;
    }
    
    @Override
    public String toString() {
        return "Emp{" +
                "ename='" + ename + '\'' +
                ", gender='" + gender + '\'' +
                ", dept=" + dept +
                '}';
    }
}
<bean id="emp" class="com.atguigu.spring5.bean.Emp">
	<!--Set two common properties-->
	<property name="ename" value="lucy"></property>
	<property name="gender" value="female"></property>
	<!--Set object type properties-->
	<property name="dept">
	    <bean id="dept" class="com.atguigu.spring5.bean.Dept">
	        <property name="dname" value="Sales Department"></property>
	    </bean>
	</property>
</bean>

⑥ Cascade assignment based on xml

The first way to write:

<!--Cascade assignment--> 
<bean id="emp" class="com.atguigu.spring5.bean.Emp">
	<!--Set two common properties-->
	<property name="ename" value="lucy"></property>
	<property name="gender" value="female"></property>
	<!--Cascade assignment-->
	<property name="dept" ref="dept"></property>
</bean> 
<bean id="dept" class="com.atguigu.spring5.bean.Dept">
	<property name="dname" value="Sales Department"></property>
</bean>

The second way to write:

//Add the getDept() method in Emp.java
public Dept getDept() {
	return dept;
}
<bean id="emp" class="com.atguigu.spring5.bean.Emp">
	<!--Set two common properties-->
	<property name="ename" value="lucy"></property>
	<property name="gender" value="female"></property>
	<!--Cascade assignment-->
	<property name="dept" ref="dept"></property>
	<property name="dept.dname" value="Technology Department"></property>
</bean> 
<bean id="dept" class="com.atguigu.spring5.bean.Dept">
	<property name="dname" value="Finance Department"></property>
</bean>

⑦ Injecting collection attributes based on xml

package com.atguigu.spring5.collectiontype;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class Stu {
    
    //1 array type properties
    private String[] courses;
    //2 list collection type attribute
    private List<String> list;
    //3 map collection type attribute
    private Map<String,String> maps;
    //4 set set type attribute
    private Set<String> sets;
    //5. Multiple courses learned by students
    private List<Course> courseList;
    
    public void setCourseList(List<Course> courseList) {
        this.courseList = courseList;
    }
    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;
    }
    
    public void testCollection(){
        System.out.println(Arrays.toString(courses));
        System.out.println(list);
        System.out.println(maps);
        System.out.println(sets);
        System.out.println(courseList);
    }
}
<!--1 Collection type attribute injection-->
<bean id="stu" class="com.atguigu.spring5.collectiontype.Stu">
    <!--Array type attribute injection-->
    <property name="courses">
        <array>
            <value>java curriculum</value>
            <value>Database course</value>
        </array>
    </property>
    <!--list Type attribute injection-->
    <property name="list">
        <list>
            <value>Zhang San</value>
            <value>Li Si</value>
        </list>
    </property>
    <!--map Type attribute injection-->
    <property name="maps">
        <map>
            <entry key="JAVA" value="java"></entry>
            <entry key="PHP" value="php"></entry>
        </map>
    </property>
    <!--set Type attribute injection-->
    <property name="sets">
        <set>
            <value>MySQL</value>
            <value>Redis</value>
        </set>
    </property>
    	<!--injection list Collection type, value is object--> 
    	<property name="courseList">
		<list>
			<ref bean="course1"></ref>
			<ref bean="course2"></ref>
		</list>
	</property>
</bean>
<!--Create multiple course object--> 
<bean id="course1" class="com.atguigu.spring5.collectiontype.Course">
	<property name="cname" value="Spring5 frame"></property>
</bean> 
<bean id="course2" class="com.atguigu.spring5.collectiontype.Course">
	<property name="cname" value="MyBatis frame"></property>
</bean>

⑦ Extract the collection injection part based on xml

Preliminary preparation: introduce the namespace util into 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: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">
<!--extract list Collection type attribute injection-->

	<util:list id="bookList">
		<value>Journey to the West</value>
		<value>Water Margin</value>
	</util:list>
	<!--extract list Collection type attribute injection usage--> 
	<bean id="book" class="com.atguigu.spring5.collectiontype.Book">
		<property name="list" ref="bookList"></property>
	</bean>

</beans>

(3) Bean management - FactoryBean

Spring has two types of beans, a normal bean and a factory bean

Ordinary beanThe bean type defined in the configuration file is the return type
Factory beanThe bean type defined in the configuration file can be different from the return type
package com.atguigu.spring5.factorybean;

import com.atguigu.spring5.collectiontype.Course;
import org.springframework.beans.factory.FactoryBean;

//Inherit interface FactoryBean
public class MyBean implements FactoryBean<Course> {
    //Custom return 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>
package com.atguigu.spring5.TestDemo;

import com.atguigu.spring5.collectiontype.Course;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestSpring5 {
    @Test
    public void test(){
        //1. Load the spring configuration file
        ApplicationContext context = new ClassPathXmlApplicationContext("bean5.xml");
        //2. Get the object created by configuration
        //Defining bean types can be different from return types
        Course course = context.getBean("myBean", Course.class);
        System.out.println(course);
    }
}

(4) Bean management - bean scope

① In Spring, bean s are singleton objects by default

package com.atguigu.spring5.TestDemo;

import com.atguigu.spring5.Book;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestSpring5 {
    @Test
    public void test(){
        //1. Load the spring configuration file
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        //2. Get the object created by configuration
        Book book1 = context.getBean("book", Book.class);
        Book book2 = context.getBean("book", Book.class);
        //If the output result is the same, it indicates that the obtained bean is single instance
        System.out.println("book1:"+book1);
        System.out.println("book2:"+book2);
    }
}

The output results are as follows:

② In the Spring configuration file, the scope attribute in the bean tag is used to set single instance or multiple instances

scopemeaning
Singleton (default)Single instance, a single instance object is created when the spring configuration file is loaded
prototypeMulti instance: create a multi instance object when calling the getBean() method
requestPut the created bean into the request
sessionPut the created bean into the session

(5) Bean management - bean life cycle

① Bean life cycle: the process from object creation to object destruction.

② The life cycle of a Bean is generally divided into the following stages:
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) Call the initialization method of the bean (the method that needs configuration initialization)
4) The bean is ready to use (the object is obtained)
5) When the container is closed, call the bean destruction method (the method that needs to be configured for destruction)

package com.atguigu.spring5.bean;

public class LifeCycle {
    
    //Nonparametric construction
    public LifeCycle() {
        System.out.println("The first step is to create a parameterless construction bean example");
    }
    private String id;
    public void setId(String id) {
        this.id = id;
        System.out.println("Step 2 call set Method to set the property value");
    }
    //Method for creating and executing initialization
    public void initMethod() {
        System.out.println("Step 3: execute initialization method");
    }
    //Method for creating and executing destruction
    public void destroyMethod() {
        System.out.println("Step 5 method of destruction");
    }
}
<!--
	init-method:initialization bean Method to execute when
	destroy-method:Destroy bean Method to execute when
-->
<bean id="lifecycle" class="com.atguigu.spring5.bean.LifeCycle" init-method="initMethod" destroy-method="destroyMethod">
    <property name="id" value="1"></property>
</bean>
package com.atguigu.spring5.TestDemo;

import com.atguigu.spring5.bean.LifeCycle;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestSpring5 {

    @Test
    public void test(){
        //1. Load the spring configuration file
        ClassPathXmlApplicationContext context =
                new ClassPathXmlApplicationContext("bean5.xml");
        //2. Get the object created by configuration
        LifeCycle lifeCycle = context.getBean("lifecycle", LifeCycle.class);
        System.out.println("Step 4 get and create bean Instance object");
        System.out.println(lifeCycle);
        //Manually destroy bean instances
        context.close();
    }
}

The results are as follows:

③ If you consider the post processor of a bean, the complete bean life cycle has seven stages:
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 post processor's method postProcessBeforeInitialization
4) Call the initialization method of the bean (the method that needs configuration initialization)
5) Pass the bean instance to the bean post processor method postProcessAfterInitialization
6) The bean is ready to use (the object is obtained)
7) When the container is closed, call the bean destruction method (the method that needs to be configured for destruction)

If you want to achieve the post processor effect, you only need to create a class (such as MyBeanPost) to inherit the interface BeanPostProcessor, implement the postProcessBeforeInitialization() method and postProcessAfterInitialization() method, and configure the post processor, In addition, it can be seen that the execution of the two methods corresponds to the third and fourth of the above seven stages respectively.

<bean id="myBeanPost" class="com.atguigu.spring5.bean.MyBeanPost"></bean>

(6) Bean management -- xml Automatic Assembly

package com.atguigu.spring5.autowire;

public class Dept {
    @Override
    public String toString() {
        return "Dept{}";
    }
}
package com.atguigu.spring5.autowire;

public class Emp {
    private Dept dept;
    
    public void setDept(Dept dept) {
        this.dept = dept;
    }
    
    @Override
    public String toString() {
        return "Emp{" +
                "dept=" + dept +
                '}';
    }
    
    public void test(){
        System.out.println(dept);
    }
}
<!--Realize automatic assembly
     bean Label properties autowire,Configure auto assembly
     autowire Property has two common values:
     byName:Inject value according to attribute name bean of id The value is the same as the class attribute name
     byType:Injected according to the attribute type, but of the same type bean You cannot define more than one, otherwise an error will be reported
-->
<bean id="emp" class="com.atguigu.spring5.autowire.Emp" autowire="byName/byType">
    <!--<property name="dept" ref="dept"></property>-->
</bean>
<bean id="dept" class="com.atguigu.spring5.autowire.Dept"></bean>

(7) Bean management - external properties file

Take the configuration database information as an example. druid is selected as the connection pool. In addition, the druid connection pool dependent jar package needs to be introduced into the project. The version selected here is 1.1.9 (other appropriate versions can be selected)
① Configure database information directly

<!--Configure connection pool directly-->
<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="123456"></property>
</bean>

② Importing an external property file to configure the database connection pool
Create an external properties file (i.e. properties format file) and use it to save database information, which is named jdbc.properties here

prop.driverClass=com.mysql.jdbc.Driver
prop.url=jdbc:mysql:///user_db
prop.username=root
prop.password=123456

Then introduce the jdbc.properties file into the spring configuration file. It is worth noting that the context namespace needs to be introduced before this

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

    <!--Import external properties file-->
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <!--Configure connection pool-->
    <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>
    
</beans>

(8) Bean management -- Annotation Based

① Annotation overview

The specific knowledge of annotations can be found in this article Java Basics - annotations
1) Annotation is a code special tag, format: @ annotation name (attribute name = attribute value, attribute name = attribute value...)
2) Using annotations, annotations act on classes, methods and properties
3) The purpose of using annotations in Spring is to simplify xml configuration

② Spring provides annotations for Bean managed object creation

1) @ Component (common annotation)
2) @ Service (generally used in business logic layer or Service layer)
3) @ Controller (generally used for Web tier)
4) @ Repository (generally used for persistence layer or Dao layer)
Note: the above four annotations can be used to create bean instances

③ Object creation based on annotation

1) Introduce related dependencies spring-aop-5.2.6.RELEASE.jar
2) Turn on component 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"
       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">

    <!--
        Turn on component scanning (note that it needs to be added) context Namespace)
        1 If multiple packages are scanned, they are separated by commas
        2 base-package="com.atguigu": scanning com.atguigu Annotations of all classes under the package
    -->
    <context:component-scan base-package="com.atguigu"></context:component-scan>
</beans>

3) Create a class and add an object annotation on the class

package com.atguigu.spring5.service;

import org.springframework.stereotype.Component;
/*
    1.In the annotation, the value attribute value can be omitted
    2.If not, the default value is the lowercase initial of the class name, such as userservice -- > userservice
    3.@Component(value="userService")Equivalent to < bean id = "userservice" class = "com. Atguigu. Spring5. Service. Userservice" / >
    4.The annotation @ Component can also be written as any of @ Service, @ Controller and @ Repository
*/
@Component(value="userService")
public class UserService {
    public void add(){
        System.out.println("add...");
    }
}

4) Testing

package com.atguigu.spring5.TestDemo;

import com.atguigu.spring5.service.UserService;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestSpring5 {

    @Test
    public void test(){
        //1. Load the spring configuration file
        ClassPathXmlApplicationContext context =
                new ClassPathXmlApplicationContext("bean1.xml");
        //2. Get the object created by configuration
        UserService userService = context.getBean("userService", UserService.class);
        System.out.println(userService);
        userService.add();
    }
}

The results are as follows:

④ Turn on detailed configuration in component scanning

<!--
	Example 1:
	use-default-filters="false": Indicates that the default is not used now filter,Self configuration filter
	context:include-filter: Set what to scan
-->
<context:component-scan base-package="com.atguigu" use-default-filters="false">
	<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

<!--
	Example 2:
	base-package="com.atguigu": scanning com.atguigu Annotations of all classes under the package
 	context:exclude-filter: Set what is not scanned
-->
<context:component-scan base-package="com.atguigu">
	<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

⑤ Attribute injection based on annotation

1) @ Autowired: auto assemble according to attribute type
First create the service and dao objects, and add the creation object annotation in the service and dao classes
UserDao.java

package com.atguigu.spring5.dao;

public interface UserDao {
    public void add();
}

UserDaoImpl.java

package com.atguigu.spring5.dao;

import org.springframework.stereotype.Repository;

@Repository(value = "userDaoImpl")
public class UserDaoImpl implements UserDao{
    @Override
    public void add() {
        System.out.println("dao add...");
    }
}

UserService.java

package com.atguigu.spring5.service;

import com.atguigu.spring5.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service(value="userService")
public class UserService {
  
    //Inject dao objects into the service, add dao type attributes to the service class, and use annotations on the attributes (there is no need to add set methods)
    @Autowired
    private UserDao userDao;
    
    public void add(){
        System.out.println("service add...");
        userDao.add();
    }
}

TestSpring5.java

package com.atguigu.spring5.TestDemo;

import com.atguigu.spring5.service.UserService;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestSpring5 {

    @Test
    public void test(){
        //1. Load the spring configuration file
        ClassPathXmlApplicationContext context =
                new ClassPathXmlApplicationContext("bean1.xml");
        //2. Get the object created by configuration
        UserService userService = context.getBean("userService", UserService.class);
        System.out.println(userService);
        userService.add();
    }
}

The results are as follows:

2) @ Qualifier: inject according to the name, which needs to be used with @ Autowired
UserService.java

package com.atguigu.spring5.service;

import com.atguigu.spring5.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

@Service(value="userService")
public class UserService {
    
    //When there are implementation objects of multiple interface classes, @ Autowired cannot accurately find which object needs to be injected, so @ Qualifier needs to inject according to the specific name
    @Autowired
    @Qualifier(value = "userDaoImpl")
    private UserDao userDao;
    
    public void add(){
        System.out.println("service add...");
        userDao.add();
    }
}

3) @ Resource: inject by type or name

//1. Injection according to type
//@Resource 
//2. Inject by name
@Resource(name = "userDaoImpl") 
private UserDao userDao;

Note: @ Resource is in javax.annotation.Resource
4) @ Value: inject common type attribute

@Value(value = "abc")
private String name;

⑥ Fully annotated development

1) Create a configuration class to replace the xml configuration file

package com.atguigu.spring5.config;

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

//@Configuration: as a configuration class, replace the xml configuration file
@Configuration
@ComponentScan(basePackages = {"com.atguigu"})
public class SpringConfig {
    
}

2) Rewrite test class

package com.atguigu.spring5.TestDemo;

import com.atguigu.spring5.config.SpringConfig;
import com.atguigu.spring5.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class TestSpring5 {

    @Test
    public void test(){
        //1. Load spring configuration class
        ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
        //2. Get the object created by configuration
        UserService userService = context.getBean("userService", UserService.class);
        System.out.println(userService);
        userService.add();
    }
}

5.AOP introduction

(1) AOP overview

AOP is the abbreviation of Aspect Oriented Programming, which means Aspect Oriented Programming. Using AOP, each part of business logic can be isolated, so as to reduce the coupling between each part of business logic, improve the reusability of programs, and improve the efficiency of development. It is commonly described as adding new functions to the main functions without modifying the source code.

(2) AOP underlying principle

The underlying layer of AOP uses dynamic agents. Generally speaking, there are two kinds of dynamic agents:
① If there is an interface, use JDK dynamic proxy, that is, create an interface to implement class proxy objects and enhance class methods
② Without interface, CGLIB dynamic proxy is used, that is, the proxy object of subclass is created to enhance the method of class

(3) JDK dynamic proxy implementation

① The class used by JDK dynamic proxy is java.lang.Proxy, and the related methods are

//Returns an instance of the proxy class of the specified interface that dispatches method calls to the specified call handler
static object newProxyInstance(ClassLoader loader,class<?>[] interfaces,InvocationHandler h)

The three parameters of the method are described as follows:

ClassLoader loaderClass loader
Class <? > [] interfacesEnhance the interface implemented by the class where the method is located (multiple interfaces are supported)
nvocationHandler hImplement this interface InvocationHandler, create proxy objects, and write enhanced parts

② Create interfaces and define methods

package com.atguigu.spring5;

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

③ Create interface implementation classes and implement methods

package com.atguigu.spring5;

public class UserDaoImpl implements UserDao{
    @Override
    public int add(int a, int b) {
        System.out.println("add Method is executed......");
        return a+b;
    }
    
    @Override
    public String update(String id) {
        return id;
    }
}

④ Creating interface Proxy objects using Proxy classes

package com.atguigu.spring5;

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) {
        //Create interface implementation class proxy object
        Class[] interfaces = {UserDao.class};
        //You can choose to use anonymous inner classes
//        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);
    }
}

//Create proxy object code
class UserDaoProxy implements InvocationHandler {
    
    //If the proxy object is created, pass it on
    //Parametric construction transfer
    private Object obj;
    public UserDaoProxy(Object obj) {
        this.obj = obj;
    }
    
    //Enhanced logic
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //Before method
        System.out.println("Method...."+method.getName()+" :Parameters passed..."+ Arrays.toString(args));
        
        //Enhanced method execution
        Object res = method.invoke(obj,args);
        
        //After method
        System.out.println("Method...."+obj);
        return res;
    }
}

⑤ Testing

(4) AOP operational terminology

Operational terminologymeaning
Connection pointMethods that can be enhanced in the class
breakthrough pointMethods that are actually really enhanced
Notification (enhanced)Actual enhanced logical part
sectionIs an action that applies a notification to the pointcut process

Among them, there are many types of notifications, such as pre notification, post notification, surround notification, exception notification, final notification, etc.

(5) The basis of AOP specific operation

① AspectJ is not a part of Spring. It is independent of the AOP framework. Generally, AspectJ and Spirng framework are used together for AOP operation.
② There are two ways to implement AOP operation based on AspectJ: Based on xml configuration file and based on annotation (recommended).
③ Introduce AOP related dependencies into the project

④ Pointcut expression
1) Function: determine which method in which class is enhanced.
2) Syntax structure:
Execution (exception thrown by method modifier method return value method class matching method name (formal parameter table in method) method declaration)

1.The yellow font cannot be omitted, and wildcards are supported in each part“*" To match all.
2.The special part is the formal parameter table, which supports two kinds of wildcards:
	" * ": Represents an arbitrary type of parameter;
	". .": Represents zero or more parameters of any type;

3) Application examples:

Enhance add in the com.atguigu.dao.BookDao classexecution( * com.atguigu.dao.BookDao.add(...))
Enhance all methods in the com.atguigu.dao.BookDao classexecution( * com.atguigu.dao.BookDao.* (...))
Enhance all classes and methods in the com.atguigu.dao packageexecution( * com.atguigu.dao.. (...))

(6) AOP specific operation - AspectJ annotation

① Create a class and define methods in the class

package com.atguigu.spring5.aopanno;

import org.springframework.stereotype.Component;

@Component
public class User {
    
    public void add(){
        //Test exception notification
        //int a=1/0;
        System.out.println("add...");
    }
}

② Create enhanced classes and write enhanced logic

package com.atguigu.spring5.aopanno;

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

//Enhanced class
@Component
@Aspect   //Generate proxy object
@Order(1) //When there are multiple enhancement classes with the same method for enhancement, set the enhancement class priority, that is, add the annotation @ order (numeric type value) on the enhancement class. The smaller the numeric type value, the higher the priority
public class UserProxy {
	
	//Extract the same pointcut
	@Pointcut(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
		public void pointdemo() {
	}    

    //Pre notification, @ Before annotation indicates pre notification
    //@Before(value = "pointdemo()")
    @Before(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
    public void before() {
        System.out.println("before.........");
    }
    //Post notification (return notification)
    @AfterReturning(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
    public void afterReturning() {
        System.out.println("afterReturning.........");
    }
    //Final notice
    @After(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
    public void after() {
        System.out.println("after.........");
    }
    //Exception notification
    @AfterThrowing(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
    public void afterThrowing() {
        System.out.println("afterThrowing.........");
    }
    
    //Around Advice 
    @Around(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws
            Throwable {
        System.out.println("Before surround.........");
        //Enhanced method execution
        proceedingJoinPoint.proceed();
        System.out.println("After surround.........");
    }
}

③ Configure notifications

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

    <!--Enable annotation scanning-->
    <context:component-scan base-package="com.atguigu.spring5.aopanno"></context:component-scan>

    <!-- open Aspect Generate proxy object-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

</beans>

④ Testing

package com.atguigu.spring5.testaop;

import com.atguigu.spring5.aopanno.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestAop {
    
    @Test
    public void testaopanno(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        User user = context.getBean("user", User.class);
        user.add();
    }
}

The results are as follows:

(7) AOP specific operation - AspectJ configuration file

① Create two classes, enhanced class and enhanced class, and create methods

package com.atguigu.spring5.aopxml;

public class Book {
    
    public void buy(){
        System.out.println("buy...");
    }
}
package com.atguigu.spring5.aopxml;

public class BookProxy {
    
    public void before(){
        System.out.println("before...");
    }
}

② Create two class objects 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: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">

    <!--create object-->
    <bean id="book" class="com.atguigu.spring5.aopxml.Book"></bean>
    <bean id="bookProxy" class="com.atguigu.spring5.aopxml.BookProxy"></bean>

    <aop:config>
        <!--breakthrough point-->
        <aop:pointcut id="p" expression="execution(* com.atguigu.spring5.aopxml.Book.buy(..))"/>
        <!--Configure section-->
        <aop:aspect ref="bookProxy">
            <!--The enhancement effect is on the specific method-->
            <aop:before method="before" pointcut-ref="p"/>
        </aop:aspect>
    </aop:config>
</beans>

③ Testing

package com.atguigu.spring5.testaop;

import com.atguigu.spring5.aopxml.Book;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestAop {
    
    @Test
    public void testaopanno(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
        Book book = context.getBean("book", Book.class);
        book.buy();
    }
}

The results are as follows:

Note: if full annotation is used, you do not need to create an xml configuration file, just create a configuration class for configuration

package com.atguigu.spring5.config;

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

@Configuration
@ComponentScan(basePackages = {"com.atguigu"})
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class ConfigAop {
}

6.JdbcTemplate

(1) JdbcTemplate overview

JdbcTemplate is the encapsulation of JDBC by the Spring framework. It is convenient to operate the database by using JdbcTemplate

(2) Preliminary preparations for using JdbcTemplate

① Import related jar packages:

② Configure 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: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">

    <!-- Database connection pool -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
        <property name="url" value="jdbc:mysql://localhost:3306/user_db" />
        <property name="username" value="root" />
        <property name="password" value="123456" />
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    </bean>

    <!--to configure JdbcTemplate Objects, injection DataSource-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <!--use set Method injection dataSource-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!-- establish service Classes, creating dao Class, in dao injection jdbcTemplate object -->
    <!-- Component scan -->
    <context:component-scan base-package="com.atguigu"></context:component-scan>
</beans>

③ Create the required table in the database. The table name is t_user. The table structure is as follows:

④ Create entity class User
User.java

package com.atguigu.spring5.entity;

public class User {
    
    private String userId;
    private String username;
    private String ustatus;
    
    public String getUserId() {
        return userId;
    }
    
    public void setUserId(String userId) {
        this.userId = userId;
    }
    
    public String getUsername() {
        return username;
    }
    
    public void setUsername(String username) {
        this.username = username;
    }
    
    public String getUstatus() {
        return ustatus;
    }
    
    public void setUstatus(String ustatus) {
        this.ustatus = ustatus;
    }
    
    @Override
    public String toString() {
        return "User{" +
                "userId='" + userId + '\'' +
                ", username='" + username + '\'' +
                ", ustatus='" + ustatus + '\'' +
                '}';
    }
}

(3) JdbcTemplate operation database - add function

① Write code
UserDao.java

package com.atguigu.spring5.dao;

import com.atguigu.spring5.entity.User;

public interface UserDao {
    void add(User user);
}

UserDaoImpl.java

package com.atguigu.spring5.dao;

import com.atguigu.spring5.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

@Repository
public class UserDaoImpl implements UserDao{

    //Inject JdbcTemplate
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    @Override
    public void add(User user) {
        String sql = "insert into t_user values(?,?,?)";
        Object[] args = {user.getUserId(),user.getUsername(),user.getUstatus()};
        int update = jdbcTemplate.update(sql, args);
        System.out.println("update:"+update);
    }
}

UserService.java

package com.atguigu.spring5.service;

import com.atguigu.spring5.dao.UserDao;
import com.atguigu.spring5.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {
    
    //Injection dao
    @Autowired
    private UserDao userDao;
    
    //Add method
    public void addUser(User user){
        userDao.add(user);
    }
}

② Testing

package com.atguigu.spring5.test;

import com.atguigu.spring5.entity.User;
import com.atguigu.spring5.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestJdbcTemplate {
    
    @Test
    public void test1(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        UserService userService = context.getBean("userService",UserService.class);
        User user = new User();
        user.setUserId("1");
        user.setUsername("Tom");
        user.setUstatus("happy");
        userService.addUser(user);
    }
}

The results are as follows:

(4) JdbcTemplate operation database -- modification and deletion functions

① Modify function

@Override
public void update(User user) {
    String sql = "update t_user set username=?,ustatus=? where userid=?";
    Object[] args = {user.getUsername(),user.getUstatus(),user.getUserId()};
    int update = jdbcTemplate.update(sql, args);
    System.out.println("update:"+update);
}

② Delete function

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

(5) JdbcTemplate operation database - query function

① The query returns a value
The method used is: queryForObject (String sql, Class requiredType)

sqlsql statement of query
requiredTypeReturn type Class
@Override
public int selectCount() {
    String sql = "select count(*) from t_user";
    Integer count = jdbcTemplate.queryForObject(sql, Integer.class);
    return count;
}

② Query return object
The method used is: queryForObject(String sql, rowmapper, rowmapper, Object... args)

sqlsql statement of query
rowMapperRowMapper is an interface. For returning different types of data, use the implementation classes in this interface to complete data encapsulation
argssql statement value
@Override
public User findUserInfo(String id) {
    String sql = "select * from t_user where userid=?";
    //Call method
    User user = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<User>(User.class), id);
    return user;
}

③ Query return collection
The method used is: query (String sql, rowmapper, rowmapper, Object... args)

sqlsql statement of query
rowMapperRowMapper is an interface. For returning different types of data, use the implementation classes in this interface to complete data encapsulation
argssql statement value
@Override
public List<User> findAllUser() {
    String sql = "select * from t_user";
    List<User> userList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<User>(User.class));
    return userList;
}

(6) JdbcTemplate operation database - batch add operation

The method used is: batchUpdate(String sql, list < 0bject [> batchargs)

sqlsql statement
batchArgsList collection to add multiple record data
//Batch add
@Override
public void batchAddBook(List<Object[]> batchArgs) {
	String sql = "insert into t_user values(?,?,?)";
	int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);
	System.out.println(Arrays.toString(ints));
}
//Batch add test
List<Object[]> batchArgs = new ArrayList<>();
Object[] o1 = {"3","Tom","happy"};
Object[] o2 = {"4","Mike","sad"};
batchArgs.add(o1);
batchArgs.add(o2);
//Call batch add
bookService.batchAdd(batchArgs);

(7) JdbcTemplate operation database - batch modification

The method used is still: batchUpdate(String sql, list < 0bject [> batchargs)

//Batch modification
@Override
public void batchUpdateBook(List<Object[]> batchArgs) {
	String sql = "update t_user set username=?,ustatus=? where userid=?";
	int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);
	System.out.println(Arrays.toString(ints));
}
//Batch modification test
List<Object[]> batchArgs = new ArrayList<>();
Object[] o1 = {"Marry","sad","3"};
Object[] o2 = {"Tom","happy","4"};
batchArgs.add(o1);
batchArgs.add(o2);
//Call method to realize batch modification
bookService.batchUpdate(batchArgs);

(8) JdbcTemplate operation database - batch deletion

The method used is still: batchUpdate(String sql, list < 0bject [> batchargs)

//Batch delete
@Override
public void batchDeleteBook(List<Object[]> batchArgs) {
	String sql = "delete from t_user where userid=?";
	int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);
	System.out.println(Arrays.toString(ints));
}
//Batch delete
List<Object[]> batchArgs = new ArrayList<>();
Object[] o1 = {"3"};
Object[] o2 = {"4"};
batchArgs.add(o1);
batchArgs.add(o2);
//Call method to realize batch deletion
bookService.batchDelete(batchArgs);

7. Services

(1) Transaction overview

Transaction is a user-defined sequence of database operations. These operations are either all done or none done. It is an inseparable work unit

(2) ACID attribute of the transaction

AtomicityTransaction is the logical work unit of database. All operations included in transaction are either done or not done.
ConsistencyThe result of transaction execution must be to change the database from one consistency state to another. That is, the system changes from one correct state to another. For example, when A transfers from A to B, A transfers 50 yuan and transfers 100 yuan to B, the transaction will prompt that the balance is insufficient and roll back, which ensures the consistency of the banking system, because the balance cannot be negative.
IsolationThe execution of one transaction cannot be disturbed by other transactions. That is, the internal operations and data used by a transaction are isolated from other concurrent transactions, and the concurrent transactions cannot interfere with each other.
SustainabilityPersistence, also known as permanence, means that once a transaction is committed, its changes to the data in the database should be permanent. Other subsequent operations or faults should not have any impact on their execution results.

(3) Build a transaction operating environment

① Build environment
Create the required table named t_account. The table structure is:

The data in the table are:

UserDao.java

package com.atguigu.spring5.dao;

public interface UserDao {
    
    public void addMoney();
    public void reduceMoney();
}

UserDaoImpl.java

package com.atguigu.spring5.dao;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

@Repository
public class UserDaoImpl implements UserDao{

    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    //More money
    @Override
    public void addMoney() {
        String sql = "update t_account set money=money+? where username=?";
        jdbcTemplate.update(sql,100,"Marry");
    }
    
    //Lucy transferred 100 to Mary
    //Less money
    @Override
    public void reduceMoney() {
        String sql = "update t_account set money=money-? where username=?";
        jdbcTemplate.update(sql,100,"Lucy");
    }
}

UserService.java

package com.atguigu.spring5.service;

import com.atguigu.spring5.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {
    
    @Autowired
    private UserDao userDao;
    
    //transfer accounts
    public void accountMoney(){
        //Lucy is 100 less
        userDao.reduceMoney();
        
        //Artificial simulation anomaly
        //int n=1/0;
        
        //Mary more than 100
        userDao.addMoney();
    }
    
}

② Testing

package com.atguigu.spring5.test;

import com.atguigu.spring5.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestJdbcTemplate {
    
    @Test
    public void test1(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        UserService userService = context.getBean("userService",UserService.class);
        userService.accountMoney();
    }
}

The results are as follows:

(4) Transaction scenario import

If an exception occurs in the accountMoney() method of the above UserService class (division by zero can be added), the transfer may not succeed, that is, Lucy's account may be reduced by 100, but Mary's account does not increase by 100. This situation must be avoided obviously. Therefore, in order to solve similar problems, Transaction management in Spring needs to be introduced.

(5) Introduction to Spring transaction management

① Spring transactions are generally added to the Service layer (business logic layer) in the three-tier structure of Java EE.
② Spring generally has two methods for transaction management: programming transaction management and declarative transaction management (recommended). Declarative transaction management includes two methods: annotation based (recommended) and xml configuration file based.
③ In Spring's declarative transaction management, the underlying principle is AOP.
④ Spring Transaction Management API: provides an interface to represent the transaction manager. This interface provides different implementation classes for different frameworks

(6) Spring transaction management -- annotated declarative transaction management

① Configure the transaction manager in the spring configuration file (note that the transaction tx namespace also needs to be introduced)

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

    <!-- Database connection pool -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
        <property name="url" value="jdbc:mysql://localhost:3306/user_db" />
        <property name="username" value="root" />
        <property name="password" value="123456" />
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    </bean>

    <!--to configure JdbcTemplate Objects, injection DataSource-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <!--use set Method injection dataSource-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!-- establish service Classes, creating dao Class, in dao injection jdbcTemplate object -->
    <!-- Component scan -->
    <context:component-scan base-package="com.atguigu"></context:component-scan>


    <!--Create transaction manager-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--Injection data source-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--Open transaction annotation-->
    <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>

</beans>

② Add the transaction annotation @ Transactional on the service class (or on the related methods in the service class) and start the simulation exception

package com.atguigu.spring5.service;

import com.atguigu.spring5.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional   //Can be added to a class or method
public class UserService {
    
    @Autowired
    private UserDao userDao;
    
    //transfer accounts
    public void accountMoney(){
        //Lucy is 100 less
        userDao.reduceMoney();
        
        //Simulation anomaly
        int n=10/0;
        
        //Mary more than 100
        userDao.addMoney();
    }
}

③ When the test is performed again, the console will give an exception prompt of division by zero, but the data in the database is still correct and valid!

(7) Spring transaction management - transaction parameters (propagation behavior)

Posted by adslworld.net on Fri, 10 Sep 2021 17:22:40 -0700