spring framework knowledge sorting

What is spring

Spring is a lightweight open source framework for layered Java SE/EE application full stack, with IoC (Inverse Of Control) and AOP (Aspect Oriented Programming) as the kernel.

Functions of spring

In short, spring is used to manage objects. The creation, initialization, destruction and interdependent configuration of objects are handed over to the spring container, which controls the life cycle of objects.

Advantages of spring

1) Convenient decoupling and simplified development
Through the IoC container provided by Spring, the dependencies between objects can be controlled by Spring to avoid excessive coupling caused by hard coding. Users do not have to write code for the very low-level requirements such as singleton pattern class and attribute file parsing, and can focus more on the upper-level applications.
2) AOP programming support
Through the AOP function of Spring, it is convenient for aspect oriented programming. Many functions that are not easy to be realized with traditional OOP can be easily realized through AOP.
3) Declarative transaction support
It can free us from the monotonous and boring transaction management code, and carry out transaction management flexibly in a declarative way, so as to improve the development efficiency and quality.
4) Facilitate program testing
Almost all testing work can be carried out in a container independent programming way. Testing is no longer an expensive operation, but a thing to do at will.
5) Convenient integration of various excellent frameworks
Spring supports various excellent frameworks (Struts, Hibernate, Hessian, Quartz, etc.).
6) Reduce the difficulty of using Java EE API
Spring has a thin encapsulation layer for Java EE APIs (such as JDBC, JavaMail, remote calls, etc.), which greatly reduces the difficulty of using these APIs.
7) Java source code is a classic learning example
Spring's source code design is exquisite, the structure is clear, and the ingenuity is unique. It everywhere reflects the master's flexible use of Java design patterns and his profound attainments in Java technology. Its source code is not intended to be an example of best practices in Java technology.

quick get start

  1. Import coordinates
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.jtyhnet</groupId>
    <artifactId>springReview1218</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>


    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>
  1. Write interface class and implementation class
//Interface class
package com.jtyhnet.dao;

public interface UserDao {
    void save();
}
//Implementation class
package com.jtyhnet.dao.impl;

import com.jtyhnet.dao.UserDao;

public class UserDaoImpl implements UserDao {
    @Override
    public void save() {
        System.out.println("spring test");
    }
}
  1. Create the spring core configuration file ApplicationContext XML to configure the implementation class in the 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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="userDao" class="com.jtyhnet.dao.impl.UserDaoImpl"/>

</beans>
  1. Use Spring's API to get Bean instances
import com.jtyhnet.dao.UserDao;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class springTest {

    @Test
    public void test1(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao userDao = (UserDao) applicationContext.getBean("userDao");
        userDao.save();
    }

}

Through in ApplicationContext Configure the corresponding class in the bean tag in XML, and use the getBean() method to obtain the object of this class for operation.

spring configuration file parsing

bean tag

Bean tag basic configuration

<bean id="userDao" class="com.jtyhnet.dao.impl.UserDaoImpl"/>

The configuration object is created by Spring.
By default, it calls the parameterless constructor in the class. If there is no parameterless constructor, it cannot be created successfully.
Basic properties:
id: the unique identifier of the Bean instance in the Spring container
class: the fully qualified name of the Bean
Scope: refers to the scope of the object. The values are as follows:

Value rangeexplain
singletonDefault, singleton
prototypeMultiple cases
requestIn the WEB project, Spring creates a Bean object and stores the object in the request field
sessionIn the WEB project, Spring creates a Bean object and stores the object in the session domain
global sessionIn the WEB project, the application is in the Portlet environment. If there is no Portlet environment, the globalSession is equivalent

The difference between singleton and prototype

Comparison contentsingletonprototype
Number of instantiations of Bean1Multiple
Bean instantiation timingWhen the Spring core file is loaded, instantiate the configured Bean instanceInstantiate the Bean when the getBean() method is called
Bean object creationWhen the application loads and creates the container, the object is createdWhen working with objects, create new object instances
Bean object runningAs long as the container is, the object remains aliveAs long as the object is in use, it is always alive
Bean object destructionWhen the application uninstalls and destroys the container, the object is destroyedWhen the object is not used for a long time, it is recycled by the Java garbage collector

Init method: Specifies the name of the initialization method in the class
Destroy method: Specifies the name of the destroy method in the class

There are three ways to instantiate a Bean

  1. Parameterless construction method instantiation
    It will create class objects according to the default parameterless constructor. If there is no default parameterless constructor in the bean, the creation will fail
<bean id="userDao" class="com.jtyhnet.dao.impl.UserDaoImpl"/>
  1. Factory static method instantiation
package com.jtyhnet.factory;

import com.jtyhnet.dao.UserDao;
import com.jtyhnet.dao.impl.UserDaoImpl;

public class StaticFactoryBean {
    public static UserDao createUserDao(){
        System.out.println("Static factory creation");
        return new UserDaoImpl();
    }
}
<bean id="userDao" class="com.jtyhnet.factory.StaticFactoryBean" factory-method="createUserDao"/>
  1. Factory instance method instantiation
package com.jtyhnet.factory;

import com.jtyhnet.dao.UserDao;
import com.jtyhnet.dao.impl.UserDaoImpl;

public class DynamicFactoryBean {

    public UserDao createUserDao(){
        System.out.println("Factory instance method creation");
        return new UserDaoImpl();
    }

}
    <bean id="userDao" factory-bean="userDaoFactory" factory-method="createUserDao"/>
    <bean id="userDaoFactory" class="com.jtyhnet.factory.DynamicFactoryBean"/>

Dependency injection of Bean

Case:
service interface

package com.jtyhnet.service;

public interface UserService {
    void save();
}

service implements classes and calls dao's save method in the implementation class.

package com.jtyhnet.service.impl;

import com.jtyhnet.dao.UserDao;
import com.jtyhnet.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class UserServiceImpl implements UserService {
    @Override
    public void save() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao userDao = (UserDao) applicationContext.getBean("userDao");
        userDao.save();
    }
}

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

    <bean id="userDao" class="com.jtyhnet.dao.impl.UserDaoImpl"/>
    <bean id="userService" class="com.jtyhnet.service.impl.UserServiceImpl"/>

</beans>

Test

    public void test2(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = (UserService) applicationContext.getBean("userService");
        userService.save();

    }

In the above case, both UserService instance and UserDao instance exist in the Spring container. The current practice is to obtain UserService instance and UserDao instance outside the container, and then combine them in the program.
Since both UserService and UserDao are in the Spring container, and the final program directly uses UserService, you can set UserDao inside UserService in the Spring container.

Dependency injection concept of Bean

Dependency Injection: it is the concrete implementation of the Spring framework core IOC.
When writing the program, the creation of objects is handed over to Spring through control inversion, but there can be no dependency in the code.
IOC decoupling only reduces their dependencies, but it will not eliminate them. For example, the business layer will still call the methods of the persistence layer.
After using Spring, Spring can maintain the dependency between the business layer and the persistence layer.
Simply put, it means waiting for the framework to transfer the persistence layer object to the business layer without getting it ourselves.

Dependency injection method of Bean
  1. set method
    The instance object of which class needs to be used is set into the target class as an attribute.
package com.jtyhnet.service.impl;
import com.jtyhnet.dao.UserDao;
import com.jtyhnet.service.UserService;

public class UserServiceImpl implements UserService {

    private UserDao userDao;

    public void setUserDao(UserDao userDao) {
    	System.out.println("set injection");
        this.userDao = userDao;
    }

    @Override
    public void save() {
        userDao.save();
    }
}

Configure in the spring core configuration file, and inject relevant properties with the property tag inside the bean tag

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

    <bean id="userDao" class="com.jtyhnet.dao.impl.UserDaoImpl"/>
    <bean id="userService" class="com.jtyhnet.service.impl.UserServiceImpl">
        <property name="userDao" ref="userDao"/>
    </bean>

</beans>

In addition to property tag injection, P namespace injection can also be used, but it is more convenient than the above set method injection, which is mainly reflected in the configuration file
First introduce the P namespace xmlns:p=“ http://www.springframework.org/schema/p ”, and then you can configure it on the bean tag

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

    <bean id="userDao" class="com.jtyhnet.dao.impl.UserDaoImpl"/>
    <bean id="userService" class="com.jtyhnet.service.impl.UserServiceImpl" p:userDao-ref="userDao"/>

</beans>
  1. Construction method

The instance object of which class needs to be used is used as the parameter of the construction method

package com.jtyhnet.service.impl;

import com.jtyhnet.dao.UserDao;
import com.jtyhnet.service.UserService;

public class UserServiceImpl implements UserService {

    private final UserDao userDao;

    public UserServiceImpl(UserDao userDao) {
        System.out.println("Construction method injection");
        this.userDao = userDao;
    }

    @Override
    public void save() {
        userDao.save();
    }
}

Use constructor Arg tag injection in the configuration file

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

    <bean id="userDao" class="com.jtyhnet.dao.impl.UserDaoImpl"/>
    <bean id="userService" class="com.jtyhnet.service.impl.UserServiceImpl">
        <constructor-arg name="userDao" ref="userDao"/>
    </bean>

</beans>

The data type on which the Bean depends

Three data types of injected data

  • Common data type
  • Reference data type
  • Collection data type

In the above case, the reference Bean is injected, that is, the reference data type

1) Common data type injection

package com.jtyhnet.dao.impl;

import com.jtyhnet.dao.UserDao;

public class UserDaoImpl implements UserDao {

    private int userId;
    private String userName;

    public void setUserId(int userId) {
        this.userId = userId;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    @Override
    public String toString() {
        return "UserDaoImpl{" +
                "userId=" + userId +
                ", userName='" + userName + '\'' +
                '}';
    }

    @Override
    public void save() {
        System.out.println("spring test");
    }

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

    <bean id="userDao" class="com.jtyhnet.dao.impl.UserDaoImpl">
        <property name="userId" value="1"/>
        <property name="userName" value="tom"/>
    </bean>

</beans>
    public void test1(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao userDao = (UserDao) applicationContext.getBean("userDao");
        System.out.println(userDao);
    }


1) Collection data type injection

  • Generic is a normal data type
package com.jtyhnet.dao.impl;

import com.jtyhnet.dao.UserDao;

import java.util.List;

public class UserDaoImpl implements UserDao {

    private List<String> stringList;

    public void setStringList(List<String> stringList) {
        this.stringList = stringList;
    }

    @Override
    public void save() {
        System.out.println("spring test");
        System.out.println(stringList);
    }
}
<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="userDao" class="com.jtyhnet.dao.impl.UserDaoImpl">
        <property name="stringList">
            <list>
                <value>zhangsan1</value>
                <value>zhangsan2</value>
                <value>zhangsan3</value>
            </list>
        </property>
    </bean>

</beans>
    public void test1(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao userDao = (UserDao) applicationContext.getBean("userDao");
        userDao.save();
    }

  • Generic is a reference type
    Use bean tag injection or ref tag reference inside the list tag
package com.jtyhnet.domain;

public class User {

    private String name;
    private int age;

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

package com.jtyhnet.dao.impl;

import com.jtyhnet.dao.UserDao;
import com.jtyhnet.domain.User;

import java.util.List;

public class UserDaoImpl implements UserDao {

    private List<User> userList;

    public void setUserList(List<User> userList) {
        this.userList = userList;
    }

    @Override
    public void save() {
        System.out.println("spring test");
        System.out.println(userList);
    }

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

    <bean id="userDao" class="com.jtyhnet.dao.impl.UserDaoImpl">
        <property name="userList">
            <list>
                <bean id="user1" class="com.jtyhnet.domain.User">
                    <property name="name" value="tom"/>
                    <property name="age" value="21"/>
                </bean>
                <bean id="user2" class="com.jtyhnet.domain.User">
                    <property name="name" value="abc"/>
                    <property name="age" value="23"/>
                </bean>
            </list>
        </property>
    </bean>

</beans>


Using ref references

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

    <bean id="user1" class="com.jtyhnet.domain.User">
        <property name="name" value="tom"/>
        <property name="age" value="22"/>
    </bean>
    <bean id="user2" class="com.jtyhnet.domain.User">
        <property name="name" value="abc"/>
        <property name="age" value="23"/>
    </bean>
    <bean id="userDao" class="com.jtyhnet.dao.impl.UserDaoImpl">
        <property name="userList">
            <list>
                <ref bean="user1"/>
                <ref bean="user2"/>
            </list>
        </property>
    </bean>

</beans>

  • Map type collection injection
package com.jtyhnet.dao.impl;

import com.jtyhnet.dao.UserDao;
import com.jtyhnet.domain.User;

import java.util.Map;

public class UserDaoImpl implements UserDao {

    private Map<String,User> userMap;

    public void setUserMap(Map<String, User> userMap) {
        this.userMap = userMap;
    }

    @Override
    public void save() {
        System.out.println("spring test");
        System.out.println(userMap);
    }

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

    <bean id="user1" class="com.jtyhnet.domain.User">
        <property name="name" value="tom"/>
        <property name="age" value="22"/>
    </bean>
    <bean id="user2" class="com.jtyhnet.domain.User">
        <property name="name" value="abc"/>
        <property name="age" value="23"/>
    </bean>
    <bean id="userDao" class="com.jtyhnet.dao.impl.UserDaoImpl">
        <property name="userMap">
            <map>
                <entry key="user1" value-ref="user1"/>
                <entry key="user2" value-ref="user2"/>
            </map>
        </property>
    </bean>

</beans>

Key and value value types can be injected directly, and reference types can be introduced through key ref value Ref

  • Properties injection
package com.jtyhnet.dao.impl;

import com.jtyhnet.dao.UserDao;
import com.jtyhnet.domain.User;

import java.util.Map;
import java.util.Properties;

public class UserDaoImpl implements UserDao {

    private Properties properties;

    public void setProperties(Properties properties) {
        this.properties = properties;
    }

    @Override
    public void save() {
        System.out.println("spring test");
        System.out.println(properties);
    }

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

    <bean id="userDao" class="com.jtyhnet.dao.impl.UserDaoImpl">
        <property name="properties">
            <props>
                <prop key="username">root</prop>
                <prop key="password">root</prop>
            </props>
        </property>
    </bean>

</beans>

Introduce other configuration files (sub module development)

In actual development, there are many Spring configurations, which leads to the complexity and volume of Spring configuration. Therefore, some configurations can be disassembled into other configuration files, and loaded in the main Spring configuration file through the import tag.

<import resource="applicationContext-xxx.xml"/>

spring related API s

applicationContext: interface type, which represents the application context. Bean objects in the Spring container can be obtained through its instance

  • Implementation class of ApplicationContext
  1. ClassPathXmlApplicationContext
    It loads the configuration file from the root path of the class. This is recommended.
  2. FileSystemXmlApplicationContext
    It loads the configuration file from the disk path. The configuration file can be anywhere on the disk.
  3. AnnotationConfigApplicationContext
    When configuring container objects with annotations, you need to use this class to create a spring container. It is used to read annotations.
  • The getBean() method uses
<bean id="userDao" class="com.jtyhnet.dao.impl.UserDaoImpl"/>
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao1 = (UserDao) applicationContext.getBean("userDao");
UserDao userDao2 = applicationContext.getBean("userDao", UserDao.class);
UserDao userDao3 = applicationContext.getBean(UserDao.class);

In the Bean tag, id is the unique identifier in the spring container. getBean(id) can get the unique object, but it needs to be forced; Through getBean(id,class), no forced conversion is required; getBean(class) is only available when there is only one Bean of this class in the container. If there are multiple beans of the same type, it cannot be used.

spring configuration data source

Role of data source (connection pool)

• data sources (connection pools) are the key to improving program performance, such as
• instantiate the data source in advance and initialize some connection resources
• get from data source when using connection resources
• return the connected resources to the data source after use
Common data sources (connection pool): DBCP, C3P0, BoneCP, Druid, etc

Data source manual creation

Import coordinates

		<dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.1.2</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.10</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.26</version>
        </dependency>

Create C3P0 connection pool

    @Test
    public void testC3P0() throws PropertyVetoException, SQLException {
        ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
        comboPooledDataSource.setDriverClass("com.mysql.jdbc.Driver");
        comboPooledDataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
        comboPooledDataSource.setUser("root");
        comboPooledDataSource.setPassword("root");
        Connection connection = comboPooledDataSource.getConnection();
        System.out.println(connection);
    }


Create Druid connection pool

    @Test
    public void testDruid() throws SQLException {
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");
        druidDataSource.setUrl("jdbc:mysql://localhost:3306/test");
        druidDataSource.setUsername("root");
        druidDataSource.setPassword("root");
        DruidPooledConnection connection = druidDataSource.getConnection();
        System.out.println(connection);
    }


To reduce coupling, jdbc connection information is extracted into the configuration file jdbc properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=root
jdbc.password=root
@Test
public void testC3P02() throws Exception {
    ResourceBundle jdbc = ResourceBundle.getBundle("jdbc");
    ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
    comboPooledDataSource.setDriverClass(jdbc.getString("jdbc.driver"));
    comboPooledDataSource.setJdbcUrl(jdbc.getString("jdbc.url"));
    comboPooledDataSource.setUser(jdbc.getString("jdbc.username"));
    comboPooledDataSource.setPassword(jdbc.getString("jdbc.password"));
    Connection connection = comboPooledDataSource.getConnection();
    System.out.println(connection);
}

spring configuration data source

Analyzing the above two manually created connection pools, both are created using parameterless construction, and the set method injects configuration, so they can be created by spring.

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


    <bean id="c3P0DataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="com.mysql.jdbc.Driver"/>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"/>
        <property name="user" value="root"/>
        <property name="password" value="root"/>
    </bean>

    <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/test"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean>


</beans>
    @Test
    public void test3() throws SQLException {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        ComboPooledDataSource c3P0DataSource = applicationContext.getBean("c3P0DataSource", ComboPooledDataSource.class);
        Connection connection = c3P0DataSource.getConnection();
        System.out.println(connection);
        System.out.println("------------------------------------");
        DruidDataSource druidDataSource = applicationContext.getBean("druidDataSource", DruidDataSource.class);
        DruidPooledConnection connection1 = druidDataSource.getConnection();
        System.out.println(connection1);
    }


To facilitate decoupling, use ApplicationContext The values written in XML are extracted into JDBC. XML In the properties configuration file, use the context tag in ApplicationContext Introducing jdbc.xml into XML properties.

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=root
jdbc.password=root
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:property-placeholder location="jdbc.properties"/>

    <bean id="c3P0DataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driver}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

    <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

</beans>

spring annotation development

Spring is a light code and heavy configuration framework. The configuration is heavy and affects the development efficiency. Therefore, annotation development is a trend. Annotation instead of xml configuration file can simplify the configuration and improve the development efficiency.

spring original annotation

Spring's original annotations are mainly used to replace the configuration of < bean >

annotationexplain
@ComponentUsed on classes to instantiate beans
@ControllerUse to instantiate beans on web tier classes
@ServiceUsed on the service layer class to instantiate beans
@RepositoryUsed on dao layer classes to instantiate beans
@AutowiredUse on field for type dependent injection
@QualifierUsed in conjunction with @ Autowired for dependency injection by name
@ResourceEquivalent to @ Autowired+@Qualifier, injected by name
@ValueInject common attributes
@ScopeLabel the scope of the Bean
@PostConstructUse to label the method, which is the initialization method of the Bean
@PreDestroyUse to mark the method as the Bean's destruction method

When developing with annotations, you need to use the application context Component scanning is configured in XML to specify which package and beans under its sub packages need to be scanned in order to identify classes, fields and methods configured with annotations.

<?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-->
    <context:component-scan base-package="com.jtyhnet"/>
   
</beans>

Using @ component or @ Repository to identify UserDaoImpl requires Spring to instantiate it.

package com.jtyhnet.dao.impl;

import com.jtyhnet.dao.UserDao;
import org.springframework.stereotype.Repository;

@Repository("userDao")
public class UserDaoImpl implements UserDao {

    @Override
    public void save() {
        System.out.println("spring anno test");
    }

}
    @Test
    public void test1(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDaoImpl userDao = applicationContext.getBean("userDao", UserDaoImpl.class);
        userDao.save();
    }


Using @ component or @ Service to identify UserServiceImpl requires Spring to instantiate it
Use @ Autowired or @ Autowired+@Qulifier or @ Resource to inject userDao

package com.jtyhnet.service.impl;

import com.jtyhnet.dao.UserDao;
import com.jtyhnet.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

@Service("userService")
public class UserServiceImpl implements UserService {

    /*@Autowired
    @Qualifier("userDao")*/
    @Resource(name = "userDao")
    private UserDao userDao;

    @Override
    public void save() {
        System.out.println("userService");
        userDao.save();
    }
}

    @Test
    public void test2(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserServiceImpl userService = applicationContext.getBean("userService", UserServiceImpl.class);
        userService.save();
    }


Use @ Value for string injection

package com.jtyhnet.dao.impl;

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

@Repository("userDao")
public class UserDaoImpl implements UserDao {

    @Value("Inject common data")
    private String str;

    @Value("${jdbc.driver}")
    private String driver;

    @Override
    public void save() {
        System.out.println(str);
        System.out.println(driver);
        System.out.println("spring anno test");
    }
}

    @Test
    public void test1(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDaoImpl userDao = applicationContext.getBean("userDao", UserDaoImpl.class);
        userDao.save();

    }


Use @ Scope to label the Scope of the Bean

package com.jtyhnet.dao.impl;

import com.jtyhnet.dao.UserDao;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Repository;

@Repository("userDao")
@Scope("singleton")
public class UserDaoImpl implements UserDao {

    @Value("Inject common data")
    private String str;

    @Value("${jdbc.driver}")
    private String driver;

    @Override
    public void save() {
        System.out.println(str);
        System.out.println(driver);
        System.out.println("spring anno test");
    }
}

Use the @ PostConstruct annotation initialization method and the @ PreDestroy annotation destruction method

    @PostConstruct
    public void init(){
        System.out.println("init");
    }

    @PreDestroy
    public void destroy(){
        System.out.println("destroy");
    }

spring new annotation

The above annotations cannot completely replace the xml configuration file. The configurations that need to be replaced by annotations are as follows:
Configuration of non custom beans: < Bean >
Load the configuration of the properties file: < context: Property placeholder >
Configuration of component scan: < context: component scan >
Import other files: < import >

annotationexplain
@ConfigurationUsed to specify that the current class is a Spring configuration class from which annotations will be loaded when creating a container
@ComponentScanUsed to specify the packages that Spring will scan when initializing the container. The function is the same as < context: component scan base package = "com.jtyhnet" / > in the xml configuration file of Spring
@BeanOn a method, annotations store the return value of the method in the Spring container
@PropertySourceFor loading Configuration in the properties file
@ImportUsed to import other configuration classes

spring annotation configuration data source

Use @ PropertySource to import the configuration file, @ Value to inject data, and use @ Bean to store it in the spring container on the method of obtaining the data source.

package com.jtyhnet.config;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;

import javax.sql.DataSource;
import java.beans.PropertyVetoException;

@PropertySource("classpath:jdbc.properties")
public class DataSourceConfiguration {

    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;

    @Bean("dataSource")
    public DataSource getDataSource() throws PropertyVetoException {
        ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
        comboPooledDataSource.setDriverClass(driver);
        comboPooledDataSource.setJdbcUrl(url);
        comboPooledDataSource.setUser(username);
        comboPooledDataSource.setPassword(password);
        return comboPooledDataSource;
    }
}

The spring annotation changes the xml configuration file to a configuration class

@Configuration tag this class as a configuration class
@ComponentScan configuring annotation scanning
@Import imports configuration classes of other configuration files and non custom objects (such as data source configuration classes)

package com.jtyhnet.config;

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

@Configuration
@ComponentScan("com.jtyhnet")
@Import(DataSourceConfiguration.class)
public class SpringConfiguration {
}

    @Test
    public void test3() throws SQLException {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfiguration.class);
        UserServiceImpl userService = applicationContext.getBean("userService", UserServiceImpl.class);
        userService.save();
        DataSource dataSource = applicationContext.getBean("dataSource", DataSource.class);
        Connection connection = dataSource.getConnection();
        System.out.println(connection);
    }

spring integration junit

step
① Import the coordinates of spring integration Junit
② Replace the original runtime with the @ Runwith annotation
③ Use @ ContextConfiguration to specify a profile or configuration class
④ Inject the object to be tested with @ Autowired
⑤ Create a test method to test

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.0.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
import com.jtyhnet.config.SpringConfiguration;
import com.jtyhnet.service.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
//Load spring core configuration file
//@ContextConfiguration(value = {"classpath:applicationContext.xml"})
//Load spring core configuration class
@ContextConfiguration(classes = {SpringConfiguration.class})
public class TestSpringJunit {

    @Autowired
    private UserService userService;

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

}

Aspect oriented programming AOP

AOP introduction of spring

AOP is the abbreviation of Aspect Oriented Programming, which means Aspect Oriented Programming. It 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.

  • The role and advantages of AOP
    Function: during the running of the program, enhance the function of the method without modifying the source code
    Advantages: reduce duplicate code, improve development efficiency, and easy to maintain

  • Underlying implementation of AOP
    In fact, the underlying layer of AOP is implemented through the dynamic proxy technology provided by Spring. During operation, Spring dynamically generates proxy objects through dynamic proxy technology. When the proxy object method is executed, it intervenes to enhance the function, and calls the method of the target object, so as to complete the function enhancement.

  • Common dynamic agent technology
    JDK agent: dynamic agent technology based on interface
    cglib proxy: dynamic proxy technology based on parent class

JDK dynamic agent

Interface class

package com.jtyhnet.JDKproxy;

public interface TargetInterface {
    public void method();
}

Implementation class

package com.jtyhnet.JDKproxy.impl;

import com.jtyhnet.JDKproxy.TargetInterface;

public class TargetInterfaceImpl implements TargetInterface {
    @Override
    public void method() {
        System.out.println("target running");
    }
}

Dynamic agent

package com.jtyhnet.JDKproxy;

import com.jtyhnet.JDKproxy.impl.TargetInterfaceImpl;

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

public class TargetProxy {

    public static void main(String[] args) {

        TargetInterfaceImpl target = new TargetInterfaceImpl();

        TargetInterface proxy = (TargetInterface) Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("Pre enhancement code");
                Object invoke = method.invoke(target, args);
                System.out.println("Post enhancement code");
                return invoke;
            }
        });

        proxy.method();
    }

}

cglib dynamic proxy

Entity class

package com.jtyhnet.cglibProxy;

public class Target {
    public void method(){
        System.out.println("cglib proxy");
    }
}

Dynamic agent

package com.jtyhnet.cglibProxy;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class CglibProxyTest {

    public static void main(String[] args) {
        //Create target object
        Target target = new Target();
        //Create intensifier
        Enhancer enhancer = new Enhancer();
        //Set parent class
        enhancer.setSuperclass(Target.class);
        //Set callback
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                System.out.println("Pre enhancement cglib");
                Object invoke = method.invoke(target, objects);
                System.out.println("Post enhancement cglib");
                return invoke;
            }
        });

        Target proxy = (Target) enhancer.create();

        proxy.method();
    }
}

The bottom layer of Spring's AOP implementation is to encapsulate the code of the above dynamic agent. After encapsulation, we only need to code the parts that need attention, and complete the method enhancement of the specified goal through configuration.
Common terms of AOP are as follows:

  • Target: the target object of the proxy
  • Proxy: after a class is enhanced by AOP weaving, a resulting proxy class is generated
  • Joinpoint s: the so-called join points refer to those intercepted points. In spring, these points refer to methods, because spring only supports method type join points
  • Pointcut: the so-called pointcut refers to the definition of which joinpoints we want to intercept
  • Advice (notification / enhancement): the so-called notification means that what needs to be done after intercepting the Joinpoint is notification
  • Aspect: a combination of pointcuts and notifications (Introductions)
  • Weaving: refers to the process of applying enhancements to the target object to create a new proxy object. spring uses dynamic proxy weaving, while AspectJ uses compile time weaving and class load time weaving

Clear matters for AOP development

  1. What needs to be written
  • Write core business code (target method of target class)
  • Write a facet class with notifications (enhancement methods) in it
  • In the configuration file, configure the weaving relationship, that is, which notifications are combined with which connection points
  1. Content of AOP technology implementation
    The Spring framework monitors the execution of pointcut methods. Once it is monitored that the pointcut method is running, the proxy mechanism is used to dynamically create the proxy object of the target object. According to the notification category, the corresponding function of the notification is woven into the corresponding position of the proxy object to complete the complete code logic operation.
  2. Which proxy method does the underlying AOP use
    In spring, the framework will decide which dynamic proxy method to adopt according to whether the target class implements the interface.

Key points of knowledge

  • aop: Aspect Oriented Programming
  • The underlying implementation of aop: dynamic agent based on JDK and dynamic agent based on Cglib
  • Key concepts of aop:
    Pointcut: enhanced method
    Advice: encapsulates ways to enhance business logic
    Aspect: pointcut + notification
    Weaving: the process of combining pointcuts with notifications
  • Clear items for development:
    Who is the pointcut (pointcut expression configuration)
    Who is notification (enhancement method in facet class)
    Weaving pointcuts and notifications into configuration

AOP development based on XML

quick get start

① Import AOP related coordinates
② Create target interface and target class (with internal tangent point)
③ Create facet class (with enhancement method inside)
④ Leave the object creation rights of the target class and the aspect class to spring
⑤ In ApplicationContext Configuring weaving relationships in XML
⑥ Test code

Coordinate import

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.13</version>
        </dependency>

Interface class

package com.jtyhnet.AOP;

public interface TargetInterface {
    void method();
}

Implementation class

package com.jtyhnet.AOP.impl;

import com.jtyhnet.AOP.TargetInterface;

public class Target implements TargetInterface {
    @Override
    public void method() {
        System.out.println("Target running");
    }
}

Enhanced method class

package com.jtyhnet.AOP;

public class MyAspect {

    //Pre enhancement method
    public void before(){
        System.out.println("Pre enhancement running");
    }

}

applicationContext.xml 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">

    <bean id="target" class="com.jtyhnet.AOP.impl.Target"/>

    <bean id="myAspect" class="com.jtyhnet.AOP.MyAspect"/>

    <aop:config>
        <aop:aspect ref="myAspect">
            <aop:before method="before" pointcut="execution(public void com.jtyhnet.AOP.impl.Target.method())"/>
        </aop:aspect>
    </aop:config>

</beans>

test

import com.jtyhnet.AOP.TargetInterface;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class AopTest {

    @Autowired
    private TargetInterface target;

    @Test
    public void test1(){
        target.method();
    }

}

Detailed explanation of XML configuration AOP

Writing of tangent point expression

Expression syntax:
execution([modifier] return value type package name. Class name. Method name (parameter))

  • The access modifier can be omitted
  • The returned value type, package name, class name and method name can be represented by an asterisk *
  • A point between the package name and the class name Represents the class under the current package, two points Represents the classes under the current package and its sub packages
  • The parameter list can use two points Represents any number and any type of parameter list

Method method in target class: execution(public void com.jtyhnet.AOP.impl.Target.method())
All return value void methods in the target class: execution(void com.jtyhnet.AOP.impl.Target. * (.)
com. jtyhnet. All methods under AOP package: execution(* com.jtyhnet.AOP. *. * (.))
com. jtyhnet. All methods under the AOP package and its sub packages: execution(* com.jtyhnet.AOP. *. * (.))
All methods under the current project package and its sub packages: execution(* *. *. *. (.))

Type of notification
<aop:Notification type method="Method name in facet class" pointcut="Tangent expression"></aop:Notification type>
namelabelexplain
Before advice <aop:before>Used to configure pre notification. Specifies that the enhanced method is executed before the pointcut method
Post notification<aop:after-returning>Used to configure post notifications. Specifies that the enhanced method is executed after the pointcut method
Around Advice <aop:around>Used to configure surround notifications. Specifies that the enhanced method is executed before and after the pointcut method
Exception throw notification<aop:throwing>Used to configure exception throw notifications. Specifies that the enhanced method is executed when an exception occurs
Final notice<aop:after>Used to configure final notifications. The enhanced mode will be executed regardless of whether there are exceptions
Tangent expression extraction

When multiple enhanced pointcut expressions are the same, the pointcut expression can be extracted. In the enhancement, the pointcut ref attribute is used instead of the pointcut attribute to reference the extracted pointcut expression.

    <aop:config>
        <aop:aspect ref="myAspect">
            <aop:pointcut id="targetPointcut" expression="execution(public void com.jtyhnet.AOP.impl.Target.method())"/>
            <aop:before method="before" pointcut-ref="targetPointcut"/>
        </aop:aspect>
    </aop:config>
main points

aop weaving configuration

<aop:config>
	<aop:aspect ref="Section class">
		<aop:before method="Notification method name" pointcut="Tangent expression"></aop:before>
	</aop:aspect>
</aop:config>

Notification types: pre notification, post notification, surround notification, exception throw notification, and final notification
How to write tangent point expression:
execution([modifier] return value type package name. Class name. Method name (parameter))

Annotation based AOP development

quick get start

Annotation based aop development steps:
① Create target interface and target class (with internal tangent point)
② Create facet class (with enhancement method inside)
③ Leave the object creation rights of the target class and the aspect class to spring
④ Using annotations to configure weaving relationships in facet classes
⑤ Turn on the automatic agent for component scanning and AOP in the configuration file
⑥ Testing

Interface class

package com.jtyhnet.AOPanno.impl;

public interface TargetInterface {
    void method();
}

The implementation class @ Component is handed over to spring for management

package com.jtyhnet.AOPanno;

import com.jtyhnet.AOPanno.impl.TargetInterface;
import org.springframework.stereotype.Component;

@Component("target")
public class Target implements TargetInterface {
    @Override
    public void method() {
        System.out.println("Target running");
    }
}

Configure weaving in section class

package com.jtyhnet.AOPanno;

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

@Component("myAspect")
@Aspect
public class MyAspect {

    //Pre enhancement method
    @Before("execution(* com.jtyhnet.AOPanno.*.*(..))")
    public void before(){
        System.out.println("Pre enhancement running");
    }

}

Enable annotation scanning and AOP automatic agent in 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">

    <context:component-scan base-package="com.jtyhnet.AOPanno"/>
    <aop:aspectj-autoproxy/>

</beans>
import com.jtyhnet.AOPanno.impl.TargetInterface;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class AopTest {

    @Autowired
    private TargetInterface target;

    @Test
    public void test1(){
        target.method();
    }

}

Annotation configuration AOP details

Type of annotation notification

Configuration syntax of notification: @ notification annotation ("pointcut expression")

nameannotationexplain
Before advice @BeforeUsed to configure pre notification. Specifies that the enhanced method is executed before the pointcut method
Post notification@AfterReturningUsed to configure post notifications. Specifies that the enhanced method is executed after the pointcut method
Around Advice @AroundUsed to configure surround notifications. Specifies that the enhanced method is executed before and after the pointcut method
Exception throw notification@AfterThrowingUsed to configure exception throw notifications. Specifies that the enhanced method is executed when an exception occurs
Final notice@AfterUsed to configure final notifications. The enhanced mode will be executed regardless of whether there are exceptions
Extraction of tangent expression

Like configuring aop with xml, we can extract Pointcut expressions. The extraction method is to define a method in the cut plane, define the cut point expression on the method with the @ Pointcut annotation, and then refer to it in the enhanced annotation. The details are as follows:

package com.jtyhnet.AOPanno;

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

@Component("myAspect")
@Aspect
public class MyAspect {

    //Pre enhancement method
    @Before("MyAspect.myPoint()")
    public void before(){
        System.out.println("Pre enhancement running");
    }

    @Pointcut("execution(* com.jtyhnet.AOPanno.*.*(..))")
    public void myPoint(){}

}

Annotate aop development steps
① Dimension facet classes with @ Aspect
② Annotate notification method with @ notification annotation
③ Configure aop auto proxy in the configuration file < aop: AspectJ AutoProxy / >

Spring JdbcTemplate basic usage

JdbcTemplate overview

It is an object provided in the spring framework and a simple encapsulation of the original cumbersome Jdbc API object. The spring framework provides us with many operation template classes. For example: JdbcTemplate and HibernateTemplate for operating relational data, RedisTemplate for operating nosql database, JmsTemplate for operating message queue, etc.

JdbcTemplate development steps

① Import spring JDBC and spring TX coordinates
② Create database tables and entities
③ Create a JdbcTemplate object
④ Perform database operations

<!--Import spring of jdbc coordinate-->
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-jdbc</artifactId>
	<version>5.0.5.RELEASE</version>
</dependency>
<!--Import spring of tx coordinate-->
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-tx</artifactId>
	<version>5.0.5.RELEASE</version>
</dependency>
//1. Create data source object
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
dataSource.setUser("root");
dataSource.setPassword("root");
//2. Create a JdbcTemplate object
JdbcTemplate jdbcTemplate = new JdbcTemplate();
//3. Set data source to JdbcTemplate
jdbcTemplate.setDataSource(dataSource);
//4. Perform operation
jdbcTemplate.update("insert into account values(?,?)","tom",5000);

Spring configuration JdbcTemplate object

<!--data source DataSource-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
	<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
	<property name="jdbcUrl" value="jdbc:mysql:///test"></property>
	<property name="user" value="root"></property>
	<property name="password" value="root"></property>
</bean>
<!--JdbcTemplate-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
	<property name="dataSource" ref="dataSource"></property>
</bean>
@Test
public void testSpringJdbcTemplate() throws PropertyVetoException {
	ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
	JdbcTemplate jdbcTemplate = applicationContext.getBean(JdbcTemplate.class);
	//insert data
	jdbcTemplate.update("insert into account values(?,?)","lucy",5000);
	//Update data
	jdbcTemplate.update("update account set money=? where name=?",1000,"tom");
	//Query data and return result set
	List<Account> accounts = jdbcTemplate.query("select * from account", new BeanPropertyRowMapper<Account>(Account.class));
	for (Account account : accounts) {
	System.out.println(account.getName());
	}
	//Query a single object
	Account account = jdbcTemplate.queryForObject("select * from account where name=?", new BeanPropertyRowMapper<Account>(Account.class), "tom");
	System.out.println(account.getName());
}

Declarative transaction control

Programming transaction control related objects

  1. The PlatformTransactionManager interface is the transaction manager of spring, which provides our common methods of operating transactions.
methodexplain
TransactionStatus getTransaction(TransactionDefination defination)Gets the status information of the transaction
void commit(TransactionStatus status)Commit transaction
void rollback(TransactionStatus status)Rollback transaction

be careful:
PlatformTransactionManager is an interface type, and different Dao layer technologies have different implementation classes,
For example: when Dao layer technology is JDBC or mybatis: org springframework. jdbc. datasource. DataSourceTransactionManager
When Dao layer technology is Hibernate: org springframework. orm. hibernate5. HibernateTransactionManager

  1. TransactionDefinition is the transaction definition information object, which contains the following methods:
methodexplain
int getIsolationLevel()Gets the isolation level of the transaction
int getPropogationBehavior()Get propagation behavior of transaction
int getTimeout()Get timeout
boolean isReadOnly()Read only
  • Transaction isolation level

Setting the isolation level can solve the problems caused by transaction concurrency, such as dirty read, non repeatable read and virtual read.

levelexplain
ISOLATION_DEFAULTUse the default isolation level of the back-end database
ISOLATION_READ_UNCOMMITTEDAllow reading of uncommitted changes. It may cause dirty reading, unreal reading or non repeatable reading.
ISOLATION_READ_COMMITTEDThe read has been committed to ensure that the modified data of one transaction can be read by another transaction only after it is committed
ISOLATION_REPEATABLE_READIt can be read repeatedly to ensure that dirty reading does not occur. It can not be read repeatedly, but phantom reading will occur,
ISOLATION_SERIALIZABLETransactions are processed in sequence and completely obey the isolation level of ACID to ensure that dirty reads, unrepeatable reads and phantom reads do not occur.
  • Transaction propagation behavior

REQUIRED: if there is no transaction currently, create a new transaction. If there is already a transaction, join it. General selection (default)
SUPPORTS: SUPPORTS the current transaction. If there is no transaction, it will be executed in a non transactional manner (no transaction)
MANDATORY: use the current transaction. If there is no transaction, an exception will be thrown
REQUERS_NEW: create a new transaction. If it is currently in a transaction, suspend the current transaction.
NOT_SUPPORTED: perform operations in a non transactional manner. If there is a transaction, suspend the current transaction
NEVER: runs in a non transactional manner. If there is a transaction, an exception will be thrown
NESTED: if a transaction currently exists, it is executed within a NESTED transaction. If there is no current transaction, perform an operation similar to REQUIRED
Timeout: the default value is - 1. There is no timeout limit. If yes, set in seconds
Read only: it is recommended to set it as read-only when querying

  • The TransactionStatus interface provides the specific running status of transactions. The methods are described below.
methodexplain
boolean hasSavepoint()Store rollback points
boolean isCompleted()Is the transaction complete
boolean isNewTransaction()Is this a new transaction
boolean isRollbackOnly()Whether the transaction is rolled back

Declarative transaction control based on XML

Spring's declarative transaction, as its name implies, is to handle transactions in a declarative manner. The declaration here refers to the declaration in the configuration file, and the declarative transaction in the spring configuration file is used to replace the code transaction.

  • The role of declarative transactions
  1. Transaction management does not invade developed components. Specifically, the business logic object will not realize that it is in the process of transaction management. In fact, it should be the same, because transaction management is a system level service, not a part of business logic. If you want to change the transaction management plan, you only need to reconfigure it in the definition file
  2. When transaction management is not required, the transaction management service can be removed by modifying the setting file without changing the code and recompiling, which is extremely convenient for maintenance

The underlying layer of Spring declarative transaction control is AOP.

Declarative transaction control matters:
 who is the tangent point?
 who is the notice?
 configuration section?

Implementation of declarative transaction control

Transfer case:

Dependent coordinates

<dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.1.2</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.10</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.26</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.0.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.13</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.0.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>5.0.5.RELEASE</version>
        </dependency>

dao interface class

package com.jtyhnet.dao;

public interface UserDao {
    void in(String inMan,double money);
    void out(String outMan,double money);
}

dao implementation class

package com.jtyhnet.dao.impl;

import com.jtyhnet.dao.UserDao;
import org.springframework.jdbc.core.JdbcTemplate;

public class UserDaoImpl implements UserDao {


    private JdbcTemplate jdbcTemplate;

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    @Override
    public void in(String inMan, double money) {
        System.out.println(inMan+" to change into "+money);
        jdbcTemplate.update("update account set money=money+? where name = ?",money,inMan);
    }

    @Override
    public void out(String outMan, double money) {
        System.out.println(outMan+" Transfer out "+money);
        jdbcTemplate.update("update account set money=money-? where name = ?",money,outMan);
    }
}

service interface class

package com.jtyhnet.service;

public interface UserService {
    void transfer(String outMan,String inMan,Double money);
}

service implementation class

package com.jtyhnet.service.impl;

import com.jtyhnet.dao.UserDao;
import com.jtyhnet.service.UserService;

public class UserServiceImpl implements UserService {

    private UserDao userDao;

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public void transfer(String outMan,String inMan,Double money) {
        userDao.out(outMan,money);
        userDao.in(inMan,money);
    }
}

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

    <context:property-placeholder location="jdbc.properties"/>

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driver}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <bean id="userDao" class="com.jtyhnet.dao.impl.UserDaoImpl">
        <property name="jdbcTemplate" ref="jdbcTemplate"/>
    </bean>

    <bean id="userService" class="com.jtyhnet.service.impl.UserServiceImpl">
        <property name="userDao" ref="userDao"/>
    </bean>

</beans>

New account table for test

create table account(
id INT NOT NULL auto_increment,
name VARCHAR ( 255 ) ,
money decimal(20,2),
PRIMARY KEY ( id ) 
);
insert into account values (null,'zhangsan',5000);
insert into account values (null,'lisi',5000);


Test transfer function

import com.jtyhnet.service.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class TestSpringTx {

    @Autowired
    private UserService userService;

    @Test
    public void test1(){
        userService.transfer("zhangsan","lisi",100.0);
    }

}



Query database transfer succeeded

According to the logic of transaction control, the transfer out and transfer in should be within one transaction. If the transfer out and transfer in is abnormal, the whole transaction will fail and the money of the two users will not change.

package com.jtyhnet.service.impl;

import com.jtyhnet.dao.UserDao;
import com.jtyhnet.service.UserService;

public class UserServiceImpl implements UserService {

    private UserDao userDao;

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public void transfer(String outMan,String inMan,Double money) {
        userDao.out(outMan,money);
        int i = 1/0;
        userDao.in(inMan,money);
    }
}

Use int i = 1/0; Simulate abnormal test

It is found that although an error is reported, the transfer out operation is still completed and the transfer in fails. It is necessary to configure a transaction for the transfer out and transfer in.

1. Introduce tx namespace into XML
2. Configure the bean of the transactionManager and inject the dataSource into the dataSource
3.tx:advice configuration transaction enhancement,
Use < TX: attributes >
<tx:method name="*"/>
</tx:attributes>
Specify the method to enhance
4. To combine transaction control with business logic code, aop weaving is used to realize transaction enhancement

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

    <context:property-placeholder location="jdbc.properties"/>

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driver}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <bean id="userDao" class="com.jtyhnet.dao.impl.UserDaoImpl">
        <property name="jdbcTemplate" ref="jdbcTemplate"/>
    </bean>

    <bean id="userService" class="com.jtyhnet.service.impl.UserServiceImpl">
        <property name="userDao" ref="userDao"/>
    </bean>

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

    <!--Transaction enhanced configuration-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="*"/>
        </tx:attributes>
    </tx:advice>

    <!--Configure transactions AOP Weave in-->
    <aop:config>
        <aop:pointcut id="myPointcut" expression="execution(* com.jtyhnet.service.impl.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="myPointcut"/>
    </aop:config>


</beans>

Test again after restoring the data in the table


Achieve overall control

  • The difference between < AOP: aspect > and < AOP: advisor >
    < AOP: advisor > is mostly used for transaction management< AOP: aspect > is used for common aspects, such as logs
    < AOP: advisor > advice needs to be configured and injected< AOP: aspect > acts on specific bean s

  • Configuration of transaction parameters of pointcut method

    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="*"/>
        </tx:attributes>
    </tx:advice>

Where, < TX: method > represents the configuration of the transaction parameters of the pointcut method, for example:
<tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED" timeout="-1" read-only="false"/>
Name: tangent point method name
Isolation: isolation level of transaction
Propagation: propagation behavior of transactions
Timeout: timeout
Read only: read only

Annotation based declarative transaction control

First change the case to annotation development, and then add transaction control after verifying that the transfer function is successful

The reference XML configuration is gradually changed to annotation

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

    <context:property-placeholder location="jdbc.properties"/>

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driver}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <bean id="userDao" class="com.jtyhnet.dao.impl.UserDaoImpl">
        <property name="jdbcTemplate" ref="jdbcTemplate"/>
    </bean>

    <bean id="userService" class="com.jtyhnet.service.impl.UserServiceImpl">
        <property name="userDao" ref="userDao"/>
    </bean>

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

    <!--Transaction enhanced configuration-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="*"/>
        </tx:attributes>
    </tx:advice>

    <!--Configure transactions AOP Weave in-->
    <aop:config>
        <aop:pointcut id="myPointcut" expression="execution(* com.jtyhnet.service.impl.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="myPointcut"/>
    </aop:config>


</beans>
  1. Annotation configuration dataSource
package com.jtyhnet.DataSource;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;

import javax.sql.DataSource;
import java.beans.PropertyVetoException;

@PropertySource("classpath:jdbc.properties")
public class C3P0DataSource {

    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;

    @Bean("dataSource")
    public DataSource getDataSource() throws PropertyVetoException {
        ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
        comboPooledDataSource.setDriverClass(driver);
        comboPooledDataSource.setJdbcUrl(url);
        comboPooledDataSource.setUser(username);
        comboPooledDataSource.setPassword(password);
        return comboPooledDataSource;
    }
}
  1. Annotation configuration JdbcTemplate
package com.jtyhnet.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.annotation.Resource;
import javax.sql.DataSource;

public class Day05JdbcTemplate {

    @Autowired
    private DataSource dataSource;

    @Bean("jdbcTemplate")
    public JdbcTemplate getJdbcTemplate(){
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.setDataSource(dataSource);
        return jdbcTemplate;
    }
}

  1. Configure spring core configuration classes
package com.jtyhnet.config;

import com.jtyhnet.DataSource.C3P0DataSource;
import com.jtyhnet.DataSource.Day05JdbcTemplate;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
@ComponentScan("com.jtyhnet")
@Import({C3P0DataSource.class, Day05JdbcTemplate.class})
public class SpringConfiguration {
}

Since neither DataSource nor JdbcTemplate is a custom class, use @ Import to Import

  1. Configure dao,service
package com.jtyhnet.dao;

public interface UserDao {
    void in(String inMan,double money);
    void out(String outMan,double money);
}

package com.jtyhnet.dao.impl;

import com.jtyhnet.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

@Repository("userDao")
public class UserDaoImpl implements UserDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public void in(String inMan, double money) {
        System.out.println("anno " + inMan+" to change into "+money);
        jdbcTemplate.update("update account set money=money+? where name = ?",money,inMan);
    }

    @Override
    public void out(String outMan, double money) {
        System.out.println("anno " + outMan+" Transfer out "+money);
        jdbcTemplate.update("update account set money=money-? where name = ?",money,outMan);
    }
}

package com.jtyhnet.service;

public interface UserService {
    void transfer(String outMan,String inMan,Double money);
}

package com.jtyhnet.service.impl;

import com.jtyhnet.dao.UserDao;
import com.jtyhnet.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service("userService")
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    @Override
    public void transfer(String outMan, String inMan, Double money) {
        userDao.out(outMan,money);
        userDao.in(inMan,money);
    }
}

  1. test
import com.jtyhnet.config.SpringConfiguration;
import com.jtyhnet.service.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfiguration.class)
public class SpringTest {

    @Autowired
    private UserService userService;

    @Test
    public void test1(){
        userService.transfer("zhangsan","lisi",100.0);
    }

}



Query database transfer succeeded

Add annotation to configure declarative transaction control:
① Use @ Transactional to modify classes or methods that need transaction control. The attributes available for annotation are the same as xml configuration methods, such as isolation level, propagation behavior, etc.
② If annotations are used on a class, all methods under the class are configured with the same set of annotation parameters.
③ In terms of methods, different methods can adopt different transaction parameter configurations.
④ Annotation driven to enable transaction in Xml configuration file < TX: annotation driven / >

package com.jtyhnet.service.impl;

import com.jtyhnet.dao.UserDao;
import com.jtyhnet.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service("userService")
@Transactional
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    //@Transactional(isolation = Isolation.READ_COMMITTED,propagation = Propagation.REQUIRED)
    @Override
    public void transfer(String outMan, String inMan, Double money) {
        userDao.out(outMan,money);
        int i = 1/0;
        userDao.in(inMan,money);
    }
}

xml configuration
< TX: annotation driven transaction manager = "transactionManager" / >, where transaction manager = "transactionManager" can be omitted. By default, < TX: annotation driven > will automatically use the transaction manager named transactionManager.

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

    <context:component-scan base-package="com.jtyhnet"/>

    <context:property-placeholder location="jdbc.properties"/>

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driver}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--Platform transaction manager-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    
	<!--Annotation driven transactions-->
    <tx:annotation-driven transaction-manager="transactionManager"/>

</beans>

test

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

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringTest {

    @Autowired
    private UserService userService;

    @Test
    public void test1(){
        userService.transfer("zhangsan","lisi",100.0);
    }

}



Query the database to confirm that both transfer out and transfer in failed, and the transaction was controlled

In order to make @ Transactional effective, the above annotation development still uses the xml configuration file, and the annotation transformation is not complete. After analysis, it is found that

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

In fact, it is also a configuration class. Therefore, you can refer to the data source configuration class and write a separate transaction manager configuration class. It is introduced in the spring core configuration class @ import, and use the @ EnableTransactionManagement tag instead of < TX: annotation driven / >

Transaction manager configuration class

package com.jtyhnet.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;

public class Day05TransactionManager {

    @Autowired
    private DataSource dataSource;

    @Bean("transactionManager")
    public DataSourceTransactionManager getDataSourceTransactionManager(){
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource);
        return dataSourceTransactionManager;
    }

}

spring core configuration class

package com.jtyhnet.config;

import com.jtyhnet.DataSource.C3P0DataSource;
import com.jtyhnet.DataSource.Day05JdbcTemplate;
import com.jtyhnet.DataSource.Day05TransactionManager;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@ComponentScan("com.jtyhnet")
@Import({C3P0DataSource.class, Day05JdbcTemplate.class, Day05TransactionManager.class})
@EnableTransactionManagement
public class SpringConfiguration {
}

test

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

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfiguration.class)
public class SpringTest {

    @Autowired
    private UserService userService;

    @Test
    public void test1(){
        userService.transfer("zhangsan","lisi",100.0);
    }

}



Transactions under control

Keywords: Java Spring Back-end

Added by jayR on Sat, 25 Dec 2021 10:08:55 +0200