Spring's first glimpse

Posted by azfar siddiqui on Wed, 01 Dec 2021 08:29:12 +0100

Learning materials: Spring official documentation
Spring is a lightweight framework for inversion of control (IOC) and aspect oriented programming (AOP).

1, IOC

When we write a simple program, we always need to new many objects, but if we want to write a large project, multiple classes are coupled with each other and the relationship is complex, which is not suitable for processing. At this time, someone thought of building a container, which is responsible for the generation, injection and assembly of all classes to decouple. This is the IOC container.

Generally speaking, it is to put the new instance process into the spring(IOC) container. When the project is initialized, the spring(IOC) container will first instantiate all classes to be used, and then inject this instance from the spring(IOC) container when it is needed. So how do you tell spring which classes to instantiate and how? Spring can get this information through xml or annotations.

2, XML injection

1.set injection

Requirements: parameter free construction and set method
Explanation: you can inject the corresponding properties by calling the set method. You can directly inject values (properties), bean references (refs) or some collections.
Example:

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="address" class="com.pojo.Address">
        <property name="address" value="xian"></property>
    </bean>

    <bean id="student" class="com.pojo.Student">
        <property name="name" value="hou"/>
        <property name="address" ref="address"/>

        <!--Array injection-->
        <property name="books">
            <array>
                <value>three countries</value>
                <value>Journey to the West</value>
                <value>Water Margin</value>
            </array>
        </property>

        <!--list-->
        <property name="hobbies">
            <list>
                <value>eat</value>
                <value>drink</value>
                <value>play</value>
            </list>
        </property>

        <property name="card">
            <map>
                <entry key="1" value="12"/>
                <entry key="2" value="23"/>
            </map>
        </property>

        <property name="game">
            <set>
                <value>wangzhe</value>
                <value>daota</value>
                <value>lol</value>
            </set>
        </property>

        <property name="wife">
            <null></null>
        </property>

        <!--properties-->
        <property name="infor">
            <props>
                <prop key="id">20200405</prop>
                <prop key="name">hdk</prop>
            </props>
        </property>
    </bean>

</beans>

Add: name can be added to the bean to set the alias (the separator can be comma, space or semicolon), or the alias can be set directly

<bean id="usert" class="com.hou.pojo.UsetT" name="u1,u2">
    <property name="name" value="kun"/>
</bean>

<alias name="user" alias="user2aaa"/>

2. Constructor injection

Requirement: there are one or more parameterized constructs
Explanation: it is to inject the corresponding attributes into spring through its constructor arg
Example:

<bean id="user" class="com.hou.pojo.User">
    <constructor-arg name="name" value="hou"></constructor-arg>
</bean>

3.p and c Injection

Requirements: p's namespace and set injection requirements; c's namespace and constructor injection requirements
Explanation: p injection is a simplified package for set injection, and c injection is a simplified package for constructor injection
You can directly assign values in the bean by means of "p: attribute name" or "c: attribute name",
Example:

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

    <!--p Namespace injection/set injection-->
    <bean id="use" class="com.pojo.User" p:name="dong" p:age="10">
    </bean>

    <!--c Namespace/constructor -->
    <bean id="use2" class="com.pojo.User" c:name="kun" c:age="19" scope="prototype"></bean>
</beans>

Supplement: scope scope
scope is an attribute in the bean, which can specify whether to use singleton mode or prototype mode, or session, request, application and websocket in the web
A singleton is to use only one instance. A prototype is to create a new instance every time it is injected. The default is a singleton
It can also be implemented by annotating @ scope

3, Automatic assembly

Simplify the configuration of a complex class.
You can use the autowire attribute of the bean to assemble in the form of byName or byType.
However, it will be easier to assemble with annotations. Only annotation automatic assembly is introduced here.
@Autowired annotation will be injected according to the type first. If there are multiple satisfied types, it will be injected according to the name

Note assembly conditions:
jdk1.5+
spring2.5+
context:
xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
Enable attribute annotation support: Context: annotation config/
Spring AOP package
@Autowired comments

example:

<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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

    <context:annotation-config/>

    <bean id="cat111" class="com.pojo.Cat"/>
    <bean id="dog" class="com.pojo.Dog"/>

    <bean id="people" class="com.pojo.People">
    </bean>

</beans>
public class People {

    @Autowired
    private Cat cat;
    @Autowired
    @Qualifier(value = "dog")
    private Dog dog;
    private String name;

    @Override
    public String toString() {
        return "People{" +
                "cat=" + cat +
                ", dog=" + dog +
                ", name='" + name + '\'' +
                '}';
    }

    public Cat getCat() {
        return cat;
    }

    public void setCat(Cat cat) {
        this.cat = cat;
    }

    public Dog getDog() {
        return dog;
    }

    public void setDog(Dog dog) {
        this.dog = dog;
    }

    public String getName() {
        return name;
    }

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

Supplement:
@Nullable: represents that the object can be null and placed in front of the type
@Autowired(required=false): represents @ Nullable
@Qualifier(value = ""): when the @ Autowired environment is very complex, manually specify the instance name of the assembly for use with @ Autowired
@Resource:
① If both name and type are specified, the only matching bean will be found in the Spring context for assembly. If not, an exception will be thrown.
② If name is specified, the bean with matching name (id) will be found in the context for assembly. If it is not found, an exception will be thrown.
③ If the type is specified, find a similar matching unique bean from the context for assembly. If it cannot be found or multiple beans are found, an exception will be thrown.
④ If neither name nor type is specified, the assembly will be performed automatically by byName; If there is no match, it will fall back to an original type for matching. If it matches, it will be assembled automatically.
@The function of Resource is equivalent to @ Autowired, but @ Autowired is automatically injected according to byType.

4, Annotation development

Constraints:

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

    <context:annotation-config/>
    <!--Specify the packages to scan-->
    <context:component-scan base-package="com.pojo"/>

</beans>

After specifying the package to be scanned, you do not need to configure bean s in xml, but directly configure them with annotations in classes
Component @ component, Controller @ Controller can be used according to different requirements, DAO@Repository , Service @ Service, represents that this class is managed by Spring;
Use @ Value("") to assign a value to the property, which can be placed on the set method or property.

package com.pojo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

//Equivalent to < bean id = "user" class = "com. POJO. User" > < / bean >
@Component
@Scope("prototype")
public class User {

    @Value("dong")
    private String name;

    public String getName() {
        return name;
    }

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

XML and annotation comparison
– XML can be used in any scenario, with clear structure and easy maintenance
– annotations are not self provided classes and cannot be used. Development is simple and convenient

xml and annotation integrated development: Recommended Best Practices
– xml managed beans
– annotation completes attribute injection
– in the process of use, it is not necessary to scan. The scanning is for the annotation on the class

Supplement:
To configure Spring using JavaConfig, you can use a configuration class instead of xml configuration

Write a configuration class

package com.config;

import com.pojo.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration //This will also be managed by the spring container and registered in the container, because it is originally a @ Component
@ComponentScan("com.pojo")
@Import(Config2.class)
public class MyConfig {

    @Bean
    public User getUser(){
        return new User();
    }

}

Change loading xml context to loading config context

import com.config.MyConfig;
import com.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Mytest {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
        User user = (User) context.getBean("getUser");
        System.out.println(user);
    }
}

5, AOP

Aspect oriented programming is a technology to realize the unified maintenance of program functions through precompiled mode and runtime dynamic agent. AOP is the continuation of OOP, a hot spot in software development, an important content in Spring framework, and a derivative paradigm of functional programming. AOP can isolate each part of business logic, reduce the coupling between each part of business logic, improve the reusability of program, and improve the efficiency of development.

AOP can add new functions through dynamic agents without changing the original code.

There are two mainstream dynamic proxy methods: java Native and cglib

java's native dynamic proxy needs to implement the interface, and cglib doesn't

Before springboot 2.0, the dynamic proxy of Java JDK is used by default. After 2.0, cglib is used by default. You can modify the default configuration through manual configuration.

The dynamic Proxy of JDK needs to know two classes: InvocationHandler and Proxy

1.InvocationHandler & Proxy

InvocationHandler: call handler

Each proxy instance has an associated invocation handler. When a method is called on a proxy instance, the method call is encoded and dispatched to the invoke method it calls.

Looking at the Client in the example, calling proxy.rent() is equivalent to reflecting the information of the rent method as the method parameter and calling the invoke method in the proxy class.

Object invoke(Object proxy, method, Object[] args);
//Parameters
//Proxy - the proxy instance that calls the method
//Method - the method corresponds to the instance that invokes the interface method on the proxy instance. The declared class of the method object will be the interface declared by the method, which can be the super interface of the proxy interface of the proxy class inheriting the method.
//args - array of objects containing method calls that pass the parameter values of the proxy instance, or null if the interface method has no parameters. The parameters of the primitive type are contained in an instance of the appropriate primitive wrapper class, such as java.lang.Integer or java.lang.Boolean.

Proxy provides static methods to create dynamic proxy classes and instances. It is also a superclass of all dynamic proxies created by these methods.

Write a proxy class to inherit InvocationHandler and override the invoke method,
Write a getProxy method and obtain the proxy instance through the proxy's newProxyInstance static method

package com;

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

//This class will be used to automatically generate proxy classes
public class ProxyInvocation implements InvocationHandler {

    //Proxy interface
    private Rent rent;

    public void setRent(Rent rent) {
        this.rent = rent;
    }

    //Generate proxy class
    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),rent.getClass().getInterfaces()
        ,this);
    }

    //Process the proxy instance and return the result
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        seeHouse();
        Object result = method.invoke(rent, args);
        fare();
        return result;
    }

    public void seeHouse(){
        System.out.println("see house");
    }

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

package com;

public class Client {

    public static void main(String[] args) {
        //Real role
        Host host = new Host();

        //delegable role
        ProxyInvocation proxyInvocation = new ProxyInvocation();

        //Handle the interface object we want to call by calling the program processing role
        proxyInvocation.setRent(host);

        Rent proxy = (Rent) proxyInvocation.getProxy();  //The proxy here is generated dynamically

        proxy.rent();

    }

}

2. AOP in spring

The most widely used aspectJ is here

Provide declarative transactions; Allows you to customize the cut plane

The following nouns need to be understood:

Crosscutting concerns: methods or functions that span multiple modules of an application. That is, the part that has nothing to do with our business logic, but we need to focus on is crosscutting concerns. Such as log, security, cache, transaction and so on
ASPECT: a special object whose crosscutting concerns are modularized. That is, it is a class.
Advice: work that must be completed in all aspects. That is, it is a method in a class.
Target: the notified object.
Proxy: an object created after notification is applied to the target object.
PointCut: the definition of the "place" where the aspect notification is executed.
Join point: the execution point that matches the pointcut
Tangent function (execution): (< modifier mode >? < return type mode > < method name mode > (< parameter mode >) < exception mode >?)

There are five types of Advice available:
1. Advance notification inherits MethodBeforeAdvice @Before
2. The post notification inherits afterreturningadvice (with return value) or inherits afteradvice (without return value) to override after Returning or after method @ After @AfterReturning
3. Surround notification @ Around
4. Exception throw notification @ AfterThrowing
5. Introduction notice (new method added in class)

Dependency:

<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
   <groupId>org.aspectj</groupId>
   <artifactId>aspectjweaver</artifactId>
   <version>1.9.4</version>
</dependency>

Like IOC, it can be implemented using configuration files or annotations

Method 1: configuration file

public class Log implements MethodBeforeAdvice {

   //Method: the method of the target object to execute
   //objects: parameters of the called method
   //Object: target object
   @Override
   public void before(Method method, Object[] objects, Object o) throws Throwable {
       System.out.println( o.getClass().getName() + "of" + method.getName() + "Method was executed");
  }
}
public class AfterLog implements AfterReturningAdvice {
   //returnValue return value
   //Method called method
   //args parameter of the object of the called method
   //Target the called target object
   @Override
   public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
       System.out.println("Yes" + target.getClass().getName()
       +"of"+method.getName()+"method,"
       +"Return value:"+returnValue);
  }
}
<?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: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/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">

   <!--register bean-->
   <bean id="userService" class="com.kuang.service.UserServiceImpl"/>
   <bean id="log" class="com.kuang.log.Log"/>
   <bean id="afterLog" class="com.kuang.log.AfterLog"/>

   <!--aop Configuration of-->
   <aop:config>
       <!--breakthrough point expression:The expression matches the method to execute-->
       <aop:pointcut id="pointcut" expression="execution(* com.kuang.service.UserServiceImpl.*(..))"/>
       <!--Perform wrap; advice-ref Execution method . pointcut-ref breakthrough point-->
       <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
       <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
   </aop:config>

</beans>

You can also write advice into the configuration file, so that the slice class you define does not inherit five advice.

Step 1: write our own cut in class

public class DiyPointcut {

   public void before(){
       System.out.println("---------Before method execution---------");
  }
   public void after(){
       System.out.println("---------After method execution---------");
  }
   
}

To configure in spring

<!--The second way is to customize the implementation-->
<!--register bean-->
<bean id="diy" class="com.kuang.config.DiyPointcut"/>

<!--aop Configuration of-->
<aop:config>
   <!--The second way: use AOP Label Implementation of-->
   <aop:aspect ref="diy">
       <aop:pointcut id="diyPonitcut" expression="execution(* com.kuang.service.UserServiceImpl.*(..))"/>
       <aop:before pointcut-ref="diyPonitcut" method="before"/>
       <aop:after pointcut-ref="diyPonitcut" method="after"/>
   </aop:aspect>
</aop:config>

Test:

public class MyTest {
   @Test
   public void test(){
       ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
       UserService userService = (UserService) context.getBean("userService");
       userService.add();
  }
}

Method 2: annotation implementation

Detailed explanation of value in the note:

execution(* com.kuang.service.UserServiceImpl. * (...)) method execution Office

From left to right:

  1. execution(): expression body.

  2. The first * indicates the return type, and the * indicates all types.

  3. Package name: indicates the name of the package to be intercepted. The following two periods represent the current package and all sub packages of the current package, the methods of all classes under the com.sample.service.impl package and descendant package, and the * sign represents all classes.

  4. *(...): the last asterisk represents the method name, the * sign represents all methods, the following parentheses represent the method parameters, and the two periods represent any parameters.

Call method call

The difference from the above can be seen in this example

If the main method is intercepted with execution, line 11 will be intercepted

If you use call to intercept main, line 8 will be intercepted

Summary of common methods

Method execution: execution(MethodSignature)

Method call: call(MethodSignature)

Constructor execution: execution(ConstructorSignature)

Constructor call: call(ConstructorSignature)

Class initialization: staticinitialization(TypeSignature)

Property read operation: get(FieldSignature)

Attribute write operation: set(FieldSignature)

Exception handling execution: handler(TypeSignature)

Object initialization: initialization(ConstructorSignature)

Object pre initialization: preinitialization(ConstructorSignature)

Advice execution: adviceexecution()

Pointcut indicator

The pointcut indicator is used to indicate the purpose of the pointcut expression. At present, there is only one connection point, the execution method, in Spring AOP. The AspectJ pointcut indicators supported by Spring AOP are as follows:

Execution: the connection point used to match the method execution;

Within: used to match the method execution within the specified type;

this: the execution method used to match the current AOP proxy object type; Note the type matching of AOP proxy objects, which may include the introduction of interface type matching;

Target: the execution method used to match the current target object type; Note that the type matching of the target object does not include the type matching of the incoming interface;

args: used to match the currently executed method. The passed in parameter is the execution method of the specified type;

@Within: used to match all methods within the specified * * * annotation * * * type;

@Target: the execution method used to match the current target object type, where the target object holds the specified * * * annotation * * *;

@args: used to match the currently executed method. The parameters passed in hold the execution of the specified * * * annotation * * *;

@Annotation: used to match the method with the specified * * * annotation * * * held by the current execution method;

package com.kuang.config;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class AnnotationPointcut {
   @Before("execution(* com.kuang.service.UserServiceImpl.*(..))")
   public void before(){
       System.out.println("---------Before method execution---------");
  }

   @After("execution(* com.kuang.service.UserServiceImpl.*(..))")
   public void after(){
       System.out.println("---------After method execution---------");
  }

   @Around("execution(* com.kuang.service.UserServiceImpl.*(..))")
   public void around(ProceedingJoinPoint jp) throws Throwable {
       System.out.println("Surround front");
       System.out.println("autograph:"+jp.getSignature());
       //Execute target method
       Object proceed = jp.proceed();
       System.out.println("After surround");
       System.out.println(proceed);
  }
}

Next: register the bean in the Spring configuration file and add a configuration that supports annotations

<!--The third way:Annotation implementation-->
<bean id="annotationPointcut" class="com.kuang.config.AnnotationPointcut"/>
<aop:aspectj-autoproxy/>

Supplementary focus

Unable to get bean from autowired in cut plane!!!
If you want to use the components in the spring container, you need to get the bean through beanfactory!!! For specific usage, refer to spring utils in ruoyi
Nor can you use applicationContext to get the bean, because it is also inside spring.

beanFactory can be obtained by implementing the interface beanfactoryprocessor;

applicationContext can be obtained by implementing the interface ApplicationContextAware;

/**
 * spring The utility class facilitates obtaining bean s in a non spring managed environment
 * 
 * @author ruoyi
 */
@Component
public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware 
{
    /** Spring Application context */
    private static ConfigurableListableBeanFactory beanFactory;

    private static ApplicationContext applicationContext;

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException 
    {
        SpringUtils.beanFactory = beanFactory;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException 
    {
        SpringUtils.applicationContext = applicationContext;
    }

    /**
     * Get object
     *
     * @param name
     * @return Object An instance of a bean registered with the given name
     * @throws org.springframework.beans.BeansException
     *
     */
    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) throws BeansException
    {
        return (T) beanFactory.getBean(name);
    }

    /**
     * Gets an object of type requiredType
     *
     * @param clz
     * @return
     * @throws org.springframework.beans.BeansException
     *
     */
    public static <T> T getBean(Class<T> clz) throws BeansException
    {
        T result = (T) beanFactory.getBean(clz);
        return result;
    }

    /**
     * Returns true if the BeanFactory contains a bean definition that matches the given name
     *
     * @param name
     * @return boolean
     */
    public static boolean containsBean(String name)
    {
        return beanFactory.containsBean(name);
    }

    /**
     * Determine whether the bean definition registered with the given name is a singleton or a prototype. If the bean definition corresponding to the given name is not found, an exception (NoSuchBeanDefinitionException) will be thrown
     *
     * @param name
     * @return boolean
     * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
     *
     */
    public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException
    {
        return beanFactory.isSingleton(name);
    }

    /**
     * @param name
     * @return Class Type of registered object
     * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
     *
     */
    public static Class<?> getType(String name) throws NoSuchBeanDefinitionException
    {
        return beanFactory.getType(name);
    }

    /**
     * If the given bean name has aliases in the bean definition, these aliases are returned
     *
     * @param name
     * @return
     * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
     *
     */
    public static String[] getAliases(String name) throws NoSuchBeanDefinitionException
    {
        return beanFactory.getAliases(name);
    }

    /**
     * Get aop proxy object
     * 
     * @param invoker
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T getAopProxy(T invoker)
    {
        return (T) AopContext.currentProxy();
    }

    /**
     * Gets the current environment configuration. null is returned if there is no configuration
     *
     * @return Current environment configuration
     */
    public static String[] getActiveProfiles()
    {
        return applicationContext.getEnvironment().getActiveProfiles();
    }

    /**
     * Obtain the current environment configuration. When there are multiple environment configurations, only the first one is obtained
     *
     * @return Current environment configuration
     */
    public static String getActiveProfile()
    {
        final String[] activeProfiles = getActiveProfiles();
        return StringUtils.isNotEmpty(activeProfiles) ? activeProfiles[0] : null;
    }
}

6, SpringBoot integrates MyBatis

spring needs to configure dataSource and sqlSessionFactory in xml

But now we all use springboot. Let's talk directly about the yml common configurations of springboot ~

# MyBatis configuration
mybatis:
  # Search for the specified package alias
  typeAliasesPackage: com.example.**.domain
  # Configure mapper scanning and find all mapper.xml mapping files
  mapperLocations: classpath*:mapper/**/*Mapper.xml

typeAliasesPackage allows us to write only the class name of resultType in mapper without writing the complete path of com. *

Maperlocations are the mapper locations we need to scan. You can get mapper.xml from different places through wildcards

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.2.0</version>
</dependency>

7, SpringBoot configuration transaction

Reference blog: https://blog.csdn.net/wkl305268748/article/details/77619367

Introduction and use

In Spring, there are two ways to implement transactions: programmatic transaction management and declarative transaction management.
Programming transaction management: programming transaction management uses TransactionTemplate or directly uses the underlying platform transactionmanager. For programmatic transaction management, spring recommends using the TransactionTemplate.
Declarative transaction management: Based on AOP. Its essence is to intercept before and after the method, then create or join a transaction before the target method starts, and commit or roll back the transaction according to the execution after the target method is executed.
Declarative transaction management does not need intrusion code. Transaction operations can be carried out through @ Transactional, which is faster and simpler.

  1. Transaction operation is realized through @ Transactional.
  2. Spring's AOP, that is, declarative transaction management, is rolled back for unchecked exception by default. That is, transaction rollback is performed for the RuntimeException() Exception or its subclasses by default; checked exceptions, that is, exceptions that can be try{} caught, will not be rolled back. Therefore, for our custom exceptions, we can set them through rollbackFor
  3. If we need to catch exceptions and roll back at the same time, we can use TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); Perform a manual rollback operation.
  4. Use Object savePoint = TransactionAspectSupport.currentTransactionStatus().createSavepoint();
    Set the rollback point and use TransactionAspectSupport.currentTransactionStatus().rollbackToSavepoint(savePoint); Rollback to savePoint.

Annotation parameters

  • readOnly: this attribute is used to set whether the current transaction is read-only. If set to true, it means read-only; if false, it means read-write; the default value is false. For example: @ Transactional(readOnly=true)
  • rollbackFor: this attribute is used to set the array of exception classes that need to be rolled back. When an exception in the specified exception array is thrown in the method, the transaction is rolled back. For example: specify a single exception class: @ Transactional(rollbackFor=RuntimeException.class) specify multiple exception classes: @ Transactional(rollbackFor={RuntimeException.class, Exception.class})
  • rollbackForClassName this property is used to set the array of Exception class names that need to be rolled back. When an Exception in the array of specified Exception names is thrown in the method, the transaction will be rolled back. For example: specify a single Exception class name @ Transactional(rollbackForClassName = "RuntimeException") and specify multiple Exception class names: @ Transactional(rollbackForClassName = {"RuntimeException", "Exception"})
    noRollbackFor this property is used to set the exception class array that does not need to be rolled back. When the exception in the specified exception array is thrown in the method, transaction rollback will not be carried out. For example: specify a single exception class: @ Transactional(noRollbackFor=RuntimeException.class) specify multiple exception classes: @ Transactional(noRollbackFor={RuntimeException.class, Exception.class})
  • noRollbackForClassName this property is used to set the array of Exception class names that do not need to be rolled back. When an Exception in the array of specified Exception names is thrown in the method, transaction rollback will not be performed. For example: specify a single Exception class name: @ Transactional(noRollbackForClassName = "RuntimeException") specify multiple Exception class names: @ Transactional(noRollbackForClassName = {"RuntimeException", "Exception"})
  • Propagation this property is used to set the propagation behavior of the transaction. For example: @ Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)
  • Isolation this attribute is used to set the transaction isolation level of the underlying database. The transaction isolation level is used to deal with the concurrency of multiple transactions. Generally, the default isolation level of the database is used, which basically does not need to be set
  • Timeout this property is used to set the timeout seconds of the transaction. The default value is - 1, which means never timeout

Transaction properties

Transaction isolation level

Isolation level refers to the degree of isolation between several concurrent transactions. Five constants representing the isolation level are defined in the TransactionDefinition interface:

TransactionDefinition.ISOLATION_DEFAULT: This is the default value, indicating that the default isolation level of the underlying database is used. For most databases, this value is usually TransactionDefinition.ISOLATION_READ_COMMITTED.
TransactionDefinition.ISOLATION_READ_UNCOMMITTED: this isolation level indicates that one transaction can read data modified by another transaction but not yet committed. This level does not prevent dirty reads, non repeatable reads and phantom reads, so it is rarely used. For example, PostgreSQL does not actually have this level.
TransactionDefinition.ISOLATION_READ_COMMITTED: this isolation level indicates that one transaction can only read the committed data of another transaction. This level can prevent dirty reading, which is also the recommended value in most cases.
TransactionDefinition.ISOLATION_REPEATABLE_READ: this isolation level indicates that a transaction can repeatedly execute a query during the whole process, and the records returned each time are the same. This level prevents dirty reads and non repeatable reads.
TransactionDefinition.ISOLATION_SERIALIZABLE: all transactions are executed one by one, so that there is no interference between transactions. In other words, this level can prevent dirty reads, non repeatable reads and phantom reads. However, this will seriously affect the performance of the program. This level is not normally used.

Transaction propagation behavior

The so-called transaction propagation behavior means that if a transaction context already exists before starting the current transaction, there are several options to specify the execution behavior of a transactional method. The definition of TransactionDefinition includes the following constants representing propagation behavior:

TransactionDefinition.PROPAGATION_REQUIRED: if a transaction currently exists, join the transaction; If there is no current transaction, a new transaction is created. This is the default.
TransactionDefinition.PROPAGATION_REQUIRES_NEW: create a new transaction. If there is a current transaction, suspend the current transaction.
TransactionDefinition.PROPAGATION_SUPPORTS: if a transaction currently exists, join the transaction; If there are currently no transactions, continue to run in a non transactional manner.
TransactionDefinition.PROPAGATION_NOT_SUPPORTED: run in non transaction mode. If there is a transaction, suspend the current transaction.
TransactionDefinition.PROPAGATION_NEVER: runs in a non transactional manner. If there is a transaction, an exception will be thrown.
TransactionDefinition.PROPAGATION_MANDATORY: if a transaction currently exists, join the transaction; Throw an exception if there is no current transaction.
TransactionDefinition.PROPAGATION_NESTED: if a transaction currently exists, create a transaction to run as a nested transaction of the current transaction; If there is no transaction at present, this value is equivalent to transactiondefinition.promotion_ REQUIRED.

Transaction Timeout

The so-called transaction timeout refers to the maximum time allowed for the execution of a transaction. If the time limit is exceeded but the transaction has not been completed, the transaction will be rolled back automatically. In the transaction definition, the timeout time is represented by the value of int, and its unit is seconds.
The default setting is the timeout value of the underlying transaction system. If the underlying database transaction system does not set the timeout value, it is none and there is no timeout limit.

Transaction read-only attribute

Read only transactions are used when the customer code is read-only but does not modify the data. Read only transactions are used for optimization in specific scenarios, such as when Hibernate is used.
The default is read-write transactions.

Topics: Java Spring Algorithm