Ultra fine Spring learning notes

Introduction to Spring

Spring is an open source framework and a layered Java EE one-stop framework.

The so-called one-stop framework means that Spring has every layer of solutions developed by Java EE.

  • WEB layer: Spring MVC
  • Service layer: Spring Bean management, declarative transaction
  • DAO layer: Spring JDBC template, ORM template

advantage:

  • IOC: easy decoupling
  • AOP: program extension
  • lightweight framework
  • Facilitate integration with other frameworks

Spring usage

Introduction to the unzipped directory of Spring development package:

  • docs: Spring Development Specification and API
  • libs: Spring jar package and source code
  • Schema: constraints of spring configuration file

DataAccess is used for data access, WEB is used for page display, and the core container is the IOC part.

Control inversion (IOC)

Inversion of Control refers to reversing (handing over) the creation right of an object to Spring.

To use IOC, you need to import IOC related packages, that is, several packages in the core container in the figure above: beans, context, core and expression.

Implementation principle

Creating objects in traditional ways

UserDao userDao = new UserDao();	

If further interface oriented programming, polymorphism can be realized:

UserDao userDao = new UserDaoImpl();

The disadvantage of this method is the high coupling between the interface and the implementation class. When switching the underlying implementation class, the source code needs to be modified. The program design should meet the requirements of OCP Yuanzu and expand the program on the basis of not modifying the program source code as far as possible.

At this time, students who have learned design patterns may think of using factory patterns to decouple interfaces and their implementation classes. We use factory patterns:

class BeanFactory{
    public static UserDAO getUserDAO(){
        return new UserDAOImpl();
    }
}

Although there is no coupling between the interface and the implementation class, there is coupling between the interface and the factory.

Decoupling is realized by using factory + reflection + configuration file, which is also the bottom implementation of IOC of Spring framework.

//xml configuration file
//<bean id="userDAO" class="xxx.UserDAOImpl"></bean>
class BeanFactory{
    public static Object getBean(String id){
        //Parsing XML
        //reflex
        Class clazz=Class.forName();
        return clazz.newInstance();
    }
}

Comparison between IOC and traditional methods

How to obtain an object: Traditionally, an object is actively created through the new keyword.

In IOC mode, the life cycle of the object is managed by Spring, and the object is obtained directly from Spring. That is, control reversal -- handing over control from yourself to Spring

IOC XML development

The xsd-configuration.hmtl file is included in the docs file. The beans schema is defined.

<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"
    //Configure bean s here
    <bean id="userService" class="x.y.UserServiceImpl">
    </bean>
</beans>

Calling class:

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService)applicationContext.getBean("userService");
userService.save();

Bean tag configuration

Tell spring to create objects

To declare a bean is to tell spring to create an object of a class

id: the user-defined name of the object. It is a unique value and cannot contain special characters. spring finds the object by this name

Class: the fully qualified name of the class (it cannot be an interface, because spring is a reflection mechanism to create a class, and you must use a class)

spring completes someservice. Someservice = new someserviceimpl();

Spring puts the created objects into a map, and the spring framework has a map to store the objects

Springmap.put (value of ID, object);

For example: springMap.put("someService",new SomeServiceImpl());

A bean tag declares an object

life cycle

  • Init method: the method executed when the bean is initialized
  • Destroy method: the method executed when the bean is destroyed

Scope of action

Scope: the scope of a bean includes the following types. The first two are commonly used

  1. Singleton: created using singleton mode by default
  2. prototype: multiple cases
  3. Request: in a web project, spring creates a class and stores it in the request scope
  4. Session: in a web project, spring creates a class and stores it in the session scope
  5. Global session: in a web project, it must be used in the porlet environment

Spring factory class

  • BeanFactory: the factory class of the old version will generate an instance of the class only when the getBean() method is called.

  • ApplicationContext: when the configuration file is loaded, all Spring managed classes will be instantiated. There are two implementation classes:

    1. ClassPathXmlApplicationContext: load the configuration file under the classpath
    2. FileSystemXmlApplicationContext: load the configuration file under the disk

IOC and DI

DI refers to dependency injection. The premise is that there must be an IOC environment. When Spring manages this class, it injects the dependent properties of the class.

For example, in UserServiceImpl.java:

public class UserServiceImpl implements UserService{
  private String name;
  public void setName(String name){
    this.name=name;
  }
  public void save(){
    System.out.println("save "+name);
  }
}

In the configuration file:

<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="userService" class="spring.demo1.UserServiceImpl">
    <!--Configure dependent properties-->
    <property name="name" value="tony"/>
    </bean>
</beans>

Test code:

@Test
public void demo2(){
  //Create Spring Factory
  ApplicationContext applicationContext=
  new ClassPathXmlApplicationContext("applicationContext.xml");

  UserService userService=
  (UserService)applicationContext.getBean("userService");

  userService.save();
}

Operation results:

save tony

You can see that the properties configured in the configuration file have been successfully set when Spring manages this class. If you do not use dependency injection, you cannot use the interface. You can only use the implementation class to set it, because the attribute is not in the interface.

set injection of common type (simple type)

It is specified in Spring that the basic data type and String type of Java are simple types

Set injection (set injection): spring calls the set method of the class to complete attribute assignment in the set method

set injection of simple type:

<bean id="xx" class="xx">
    <property name="Attribute name" value="The value of this property"/>
    One property Only one property can be assigned a value
</bean>

Let's take the Student class as an example

In Student.java:

public class Student {
    private String name;
    private int age;

    private School school;

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

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

    public void setSchool(School school) {
        this.school = school;
    }

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

In the applicationContext.xml file:

<bean id="myStudent" class="com.jiawen.package1.Student">
    <property name="name" value="lisi"/>
    <property name="age" value="20"/>
</bean>

Test:

@Test
public void test01(){
    String config = "package1/applicationContext.xml";
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext(config);

    Student myStudent = (Student) applicationContext.getBean("myStudent");
    System.out.println(myStudent);
}

Operation results:

Student{name='lisi', age=20}

set injection of reference type

Set injection of reference type: spring calls the set method of the class

<bean id="xxx" class="xxxx">
    <property name="Attribute name" ref="bean of id(Object name)"/>
</bean>

Take schools and students as an example

In School.java:

public class School {
    private String name;
    private String address;

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

    public void setAddress(String address) {
        this.address = address;
    }

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

In Student.java:

public class Student {
    private String name;
    private int age;

    private School school;

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

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

    public void setSchool(School school) {
        this.school = school;
    }

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

In applicationContext.xml:

<bean id="myStudent" class="com.jiawen.package2.Student">
        <property name="name" value="lisi"/>
        <property name="age" value="22"/>
        <property name="school" ref="mySchool"/>
    </bean>

<!--    statement school object-->
    <bean id="mySchool" class="com.jiawen.package2.School">
        <property name="name" value="bj"/>
        <property name="address" value="hdq"/>
     </bean>

Operation results:

Student{name='lisi', age=22, school=School{name='bj', address='hdq'}}

Structural injection

Construction injection: spring calls the parameterized construction method of the class, and assigns the attribute in the construction method while creating the object

Construct injection uses the < constructor Arg > tag

< constructor Arg > tag: a < constructor Arg > represents a parameter of the construction method

< constructor Arg > tag attribute:

Name: indicates the formal parameter name of the constructor

index: the position of the construction method parameter. The parameter positions from left to right are in the order of 0, 1, 2

Value: the formal parameter type of the constructor is a simple type. Use value

ref: the formal parameter type of the method is reference type. Use ref

Take schools and students as an example

In School.java:

public class School {
    private String name;
    private String address;

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

    public void setAddress(String address) {
        this.address = address;
    }

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

In Student.java:

public class Student {
    private String name;
    private int age;

    private School school;

    public Student() {
    }

    public Student(String name, int age, School school) {
        this.name = name;
        this.age = age;
        this.school = school;
    }

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

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

    public void setSchool(School school) {
        this.school = school;
    }

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

In applicationContext.xml:

<bean id="myStudent" class="com.jiawen.package3.Student">
    <constructor-arg name="name" value="zhangsan"/>
    <constructor-arg name="age" value="20"/>
    <constructor-arg name="school" ref="mySchool"/>
</bean>

<bean id="mySchool" class="com.jiawen.package3.School">
    <property name="name" value="bj"/>
    <property name="address" value="bjhd"/>
</bean>

Test:

@Test
public void test03(){
    String config = "package3/applicationContext.xml";
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext(config);
    Student myStudent = (Student) applicationContext.getBean("myStudent");
    System.out.println(myStudent);
}

Operation results:

Student{name='zhangsan', age=20, school=School{name='bj', address='bjhd'}}

Automatic injection of reference types

Automatic injection of reference types: the spring framework can assign values to reference types according to certain rules
Usage rules: byName, byType

byName (injected by name)

byName: the attribute name of the reference type in the Java class is the same as the id name in the spring container (configuration file), and the data type is the same
For bean s in such containers, spring can assign values to reference types
Syntax:

<bean id="xx" class="xx" autowire="byName">
	Simple type attribute assignment
</bean>

Take schools and students as an example

In School.java:

public class School {
    private String name;
    private String address;

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

    public void setAddress(String address) {
        this.address = address;
    }

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

In Student.java:

public class Student {
    private String name;
    private int age;

    private School school;

    public Student() {
    }

    public Student(String name, int age, School school) {
        this.name = name;
        this.age = age;
        this.school = school;
    }

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

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

    public void setSchool(School school) {
        this.school = school;
    }

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

In applicationContext.xml:

<bean id="myStudent" class="com.jiawen.package4.Student" autowire="byName">
    <property name="name" value="lisi"/>
    <property name="age" value="22"/>
</bean>

<bean id="school" class="com.jiawen.package4.School" autowire="byName">
    <property name="name" value="bj"/>
    <property name="address" value="bjhd"/>
</bean>

Test:

@Test
public void test04(){
    String config = "package4/applicationContext.xml";
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext(config);
    Student myStudent = (Student) applicationContext.getBean("myStudent");
    System.out.println(myStudent);
}

Operation results:

Student{name='lisi', age=22, school=School{name='bj', address='bjhd'}}

byType (injected by type)

byType (injection by type): the data type of the reference type in the Java class and the class attribute of < bean > in the spring container (configuration file) are homologous
Beans can be assigned to reference types

Homology means one kind:

  1. The data type of reference type in Java class is the same as that of < bean >
  2. The data type of reference type in Java class and the value of < bean > class are the relationship between parent and child classes
  3. The data type of reference type and the class value of < bean > in Java class are the basis of interface and implementation class relationship

Syntax:

<bean id="xx" class="xx" autowire="byType">
	Simple type attribute assignment
</bean>

Take schools and students as an example

In School.java:

public class School {
    private String name;
    private String address;

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

    public void setAddress(String address) {
        this.address = address;
    }

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

In Student.java:

public class Student {
    private String name;
    private int age;

    private School school;

    public Student() {
    }

    public Student(String name, int age, School school) {
        this.name = name;
        this.age = age;
        this.school = school;
    }

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

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

    public void setSchool(School school) {
        this.school = school;
    }

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

In applicationContext.xml:

<bean id="myStudent" class="com.jiawen.package5.Student" autowire="byType">
        <property name="name" value="lisi"/>
        <property name="age" value="22"/>
</bean>

<bean id="mySchool" class="com.jiawen.package5.School">
        <property name="name" value="bj"/>
        <property name="address" value="bjhd"/>
</bean>

In order to better understand the concept of "homology", we introduce the subclass PrimarySchool of school and let the Student's school member point to the object of PrimarySchool

In PrimarySchool:

public class PrimarySchool extends School{

}

In applicationContext.xml:

<bean id="myStudent" class="com.jiawen.package5.Student" autowire="byType">
    <property name="name" value="lisi"/>
    <property name="age" value="22"/>
</bean>
<bean id="primarySchool" class="com.jiawen.package5.PrimarySchool">
	<property name="name" value="bjxx"/>
	<property name="address" value="bjdx"/>
</bean>

Test:

@Test
public void test05(){
    String config = "package5/applicationContext.xml";
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext(config);
    Student myStudent = (Student) applicationContext.getBean("myStudent");
    System.out.println(myStudent);
}

Operation results:

Student{name='lisi', age=22, school=School{name='bjxx', address='bjdx'}}

Property injection for p namespace

First, you need to introduce p namespaces:

<beans xmlns="http://www.springframework.org/schema/beans"
    //Introducing p namespaces
    xmlns:p="http://www.springframework.org/schema/p"
    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"
</beans>

If it is a normal attribute:

<bean id="car" class="demo.Car" p:name="bmv" p:price="123"></bean>

If it is a reference type:

<bean id="employee" class="demo.Employee"
	p:name="xiaoming" p:car-ref:"car">
</bean>

SpEL(Spring Expression Language) attribute injection (spring version 3. X or above)

<bean id="car" class="demo.Car">
    <property name="name" value="#{'xiaoming'}">
    <property name="car" ref="#{car}">
</bean>

Collection type attribute injection

<bean id="car" class="demo.Car">
    <property name="namelist">
        <list>
            <value>qirui</value>
            <value>baoma</value>
            <value>benchi</value>
        </list>
    </property>
</bean>

Multi module development settings

  1. When loading a configuration file, multiple configuration files are loaded
  2. Multiple configuration files are introduced into one configuration file

Take schools and students as an example

In School.java:

public class School {
    private String name;
    private String address;

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

    public void setAddress(String address) {
        this.address = address;
    }

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

In Student.java:

public class Student {
    private String name;
    private int age;

    private School school;

    public Student() {
    }

    public Student(String name, int age, School school) {
        this.name = name;
        this.age = age;
        this.school = school;
    }

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

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

    public void setSchool(School school) {
        this.school = school;
    }

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

In spring-school.xml:

<bean id="mySchool" class="com.jiawen.package6.School">
    <property name="name" value="bj"/>
    <property name="address" value="bjhd"/>
</bean>

In spring-student.xml:

<bean id="myStudent" class="com.jiawen.package6.Student" autowire="byType">
    <property name="name" value="lisi"/>
    <property name="age" value="22"/>
</bean>

In spring-total.xml:

<import resource="classpath:package6/spring-school.xml"/>
<import resource="classpath:package6/spring-student.xml"/>

Test:

@Test
public void test06(){
    String config = "package6/spring-total.xml";
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext(config);
    Student myStudent = (Student) applicationContext.getBean("myStudent");
    System.out.println(myStudent);
}

Operation results:

Student{name='lisi', age=22, school=School{name='bj', address='bjhd'}}

Spring total represents the main configuration file: the file containing other configuration files

The main configuration file generally does not define objects

Syntax: < import resource = "path to other configuration files" / >

Keyword: "classpath:": indicates the classpath (the directory where the class file is located). To specify the location of other files in the spring configuration file, you need to use classpath to tell spring where to load and read files

In the configuration file containing the relationship, wildcard (*: indicates any character can be used

IOC annotation development

  1. Introducing jar packages: in addition to the above four packages, you also need to introduce aop packages.

  2. Create applicationContext.xml and use annotation development to introduce context constraints (XSD configuration. HTML)

    <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"
            <!-- bean definitions here -->
    </beans>
    
  3. Component scanning: when developing with IOC annotations, you need to configure component scanning, that is, which classes under the package use IOC annotations.

    Declare a component scan, and a component is a Java object

    Base package: Specifies the package name of the annotation in your project

    Working mode of component scan: spring will scan and traverse the package specified by base package, all classes in the package and sub packages, find the annotations in the class, create objects according to the annotation function, or assign values to attributes

    <context:component-scan base-package="demo1">
    

    Three ways to specify multiple packages

    The first way: use multiple component scanners to specify different packages

    The second method: use the separator (; or,) to split multiple package names

    The third way: specify the parent package

  4. Add annotation on class

  5. Use annotations to set the value of a property

    //It is equivalent to configuring a < bean > whose id is UserDao and the corresponding class is this class
    @Component("UserDao")
    public class UserDAOImpl implements UserDAO {
    
    	@Override
    	public void save() {
    		// TODO Auto-generated method stub
    		System.out.println("save");
    	} 
    }
    

Annotation details

1.Component

Component annotation is used to modify a class and hand it over to Spring for management.

There are three derived annotations with similar functions, which are also used to modify classes.

  • @Controller: decorated web layer class
  • @Service: decorate the service layer class
  • @Repository: decorate dao layer class

2. Attribute injection

  • Common properties use @ Value to set the Value of the property
  • The object attribute uses @ Autowired. This annotation is injected according to the type. If you want to inject attributes by bean name or id, @ Autowired and @ Qualifier should be used together
  • In actual development, @ Resource(name = "") is used to complete attribute injection according to the name of the object

3. Other notes

  • @PostConstruct is equivalent to init method, which is used to initialize the annotation of the function
  • @PreDestroy is equivalent to destroy method, which is used to destroy the annotation of the function
  • @The annotation of the Scope scope is usually the default singleton, and there are multiple @ Scope("prototype")

Comparison of IOC's XML and annotation development

  • Applicable scenario: XML is applicable to any scenario; Annotations are only suitable for self written classes, not self provided classes. Annotations cannot be added.
  • You can use XML to manage bean s and use annotations for attribute injection

@Component: creating objects

@Component: creates an object, which is equivalent to the label of < bean >

Properties:

Value is the name of the object, that is, the id value of the bean

The value of value is unique, and the created object is one in the whole spring container

Location: above the class

@Component(value = "myStudent") is equivalent to < bean id = "mystudent" class = "com. Jiawen. Package1. Student" / >

The functions of spring and @ Component are the same. The annotations for creating objects include:

  1. @Repository (used on the persistence layer class): it imitates the implementation class of dao to create dao objects, which can access the database
  2. @Service (used above the business layer class): put it on the implementation class of servvice and create a service object. The service object is used for business processing and can have transaction and other functions
  3. @Controller (used on the controller): it is placed on the controller (processor) to create a controller object. The controller object can receive the parameters submitted by the user and display the processing results of the request

The syntax of the above three annotations is the same as @ Component, which can create objects, but these three annotations have additional functions

Take Student as an example

In Student.java

@Component(value = "myStudent")
public class Student {
    private String name;
    private String age;

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

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

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

Test:

@org.junit.Test
public void test01(){
    String config = "applicationContext.xml";
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext(config);
    Student student = (Student) applicationContext.getBean("myStudent");
    System.out.println(student);
}

Operation results:

Student{name='null', age='null'}

@Value: property assignment of simple type

@value: attribute assignment of simple type

Attribute: value is of type String and represents the attribute value of simple type

Location:

  1. The set method is not required for attribute definitions. It is recommended
  2. Above the set method

Take Student as an example

In Student.java

@Component(value = "myStudent")
public class Student {
    @Value(value = "lisi")
    private String name;
    @Value(value = "20")
    private String age;

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

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

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

Test:

@org.junit.Test
public void test02(){
    String config = "applicationContext.xml";
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext(config);
    Student student = (Student) applicationContext.getBean("myStudent");
    System.out.println(student);
}

Operation results:

Student{name='lisi', age='20'}

@Autowire: byType auto injection of reference type

@Autowired: the annotation provided by the spring framework to realize the assignment of reference types.

@Autowired: byType auto injection is used by default

Location:

  1. The set method is not required for attribute definitions. It is recommended
  2. Above the set method

Properties:

required is a Boolean type. The default value is true

required=true: indicates that the reference type assignment fails, the program reports an error, and the execution is terminated

required=false: reference type. If the assignment fails, the program will execute normally, and the reference type is null

Take schools and students as an example

In School.java:

@Component("mySchool")
public class School {
    @Value("bjdx")
    private String name;
    @Value("bjhd")
    private String address;

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

    public void setAddress(String address) {
        this.address = address;
    }

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

In Student.java:

@Component(value = "myStudent")
public class Student {
    @Value(value = "lisi")
    private String name;
    @Value(value = "20")
    private String age;

    @Autowired
    private School school;

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

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

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

Test:

@org.junit.Test
public void test03(){
    String config = "applicationContext.xml";
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext(config);
    Student student = (Student) applicationContext.getBean("myStudent");
    System.out.println(student);
}

Operation results:

Student{name='lisi', age='20', school=School{name='bjdx', address='bjhd'}}

@Autowire+@Qualifier: ByNama auto injection of reference type

If you want to use byName, you need to:

  1. Add @ Autowired to the attribute
  2. Add @ Qualifier (value = "bean id") to the attribute: it means that the bean with the specified name is used to complete the assignment

Take schools and students as an example

In School.java:

@Component("mySchool")
public class School {
    @Value("bjdx")
    private String name;
    @Value("bjhd")
    private String address;

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

    public void setAddress(String address) {
        this.address = address;
    }

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

In Student.java:

@Component(value = "myStudent")
public class Student {
    @Value(value = "lisi")
    private String name;
    @Value(value = "20")
    private String age;

    @Autowired
    @Qualifier(value = "mySchool")
    private School school;

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

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

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

Test:

@org.junit.Test
public void test04(){
    String config = "applicationContext.xml";
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext(config);
    Student student = (Student) applicationContext.getBean("myStudent");
    System.out.println(student);
}

@Resource: reference type assignment (from JDK)

@Resource: an annotation from the jdk. The spring framework provides functional support for this annotation, which can be used to assign values to reference types

It also uses the principle of automatic injection, supports byName and byType, and byName is the default

Location:

  1. The set method is not required for attribute definitions. It is recommended
  2. Above the set method

byName is the default. byName is automatically injected first. If byName assignment fails, byType is used again

Take schools and students as an example

In School.java:

@Component("mySchool")
public class School {
    @Value("bjdx")
    private String name;
    @Value("bjhd")
    private String address;

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

    public void setAddress(String address) {
        this.address = address;
    }

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

In Student.java:

@Component(value = "myStudent")
public class Student {
    @Value(value = "lisi")
    private String name;
    @Value(value = "20")
    private String age;

    @Resource(name = "mySchool")
    private School school;

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

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

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

AOP development

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. It is the continuation of OOP.

AOP can enhance the program. Without modifying the source code, it can perform permission verification, logging, performance monitoring, transaction control, etc.

In other words, functions are divided into two categories: core business functions and auxiliary enhancement functions. The two types of functions are developed independently of each other. For example, the login function is the core business function, and the log function is an auxiliary enhancement function. If necessary, the log and login are compiled together. The auxiliary function is called aspect. This selective and low coupling programming idea that combines aspect and core business functions is called aspect programming.

Underlying implementation

JDK agent

JDK dynamic proxy can only generate proxy for classes that implement interfaces.

Using JDK dynamic proxy:

In UserDao.java:

public interface UserDao {
    public void insert();
    public void delete();
    public void update();
    public void query();
}

Create the implementation class UserDaoImpl of UserDao

In UserDaoImpl:

public class UserDaoImpl implements UserDao{
    @Override
    public void insert() {
        System.out.println("insert");
    }

    @Override
    public void delete() {
        System.out.println("delete");
    }

    @Override
    public void update() {
        System.out.println("update");
    }

    @Override
    public void query() {
        System.out.println("query");
    }
}

JDK agent

In JDKProxy:

public class JDKProxy implements InvocationHandler {
    private UserDao userDao;

    public JDKProxy(UserDao userDao) {
        this.userDao = userDao;
    }

    public UserDao createProxy(){
        UserDao userDaoProxy = (UserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader(), userDao.getClass().getInterfaces(), this);
        return userDaoProxy;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if("update".equals(method.getName())){
            System.out.println("Permission verification");
            return method.invoke(userDao, args);
        }
        return method.invoke(userDao, args);
    }
}

Test procedure:

public static void main(String[] args) {
    UserDao userDao = new UserDaoImpl();
    UserDao proxy = new JDKProxy(userDao).createProxy();
    proxy.insert();
    proxy.delete();
    proxy.update();
    proxy.query();
}

Operation results:

insert
delete
 Permission verification
update
query

The update function is enhanced through dynamic proxies.

Cglib agent

Cglib dynamic proxy can generate proxy objects for classes that do not implement interfaces, and generate subclass objects.

Cglib cglib is a third-party open source code generation class library, which can dynamically add class properties and methods.

Different from the JDK agent above, Cglib is used as follows:

public class CglibProxy implements MethodInterceptor{
//Incoming enhanced object
    private UserDao customerDao;
    public CglibProxy(UserDao userDao){
        this.userDao=userDao;
    }
    
    public UserDao createProxy(){
        Enhancer enhancer=new Enhancer();
        enhancer.setSuperclass(userDao.getClass());
        enhancer.setCallback(this);
        UserDao proxy=(UserDao)enhancer.create();
        return proxy;
    }

    @Override
    public Object intercept(Object proxy, Method method, Object[] args
                            , MethodProxy methodProxy) throws Throwable {
        if("save".equals(method.getName())){
            System.out.println("enhance function");
            return methodProxy.invokeSuper(proxy, args);
        }
        return methodProxy.invokeSuper(proxy, args);
    }
}

If the interface class is implemented, JDK agent is used at the bottom. If it is not a class that implements the interface, the bottom layer uses Cglib proxy.

AOP development of Spring (XML mode of AspectJ)

AspectJ is an AOP framework. Spring introduces AspectJ and develops AOP based on AspectJ.

Related terms

  • Joinpoint: connection point, which can be intercepted. That is, the methods that can be enhanced are connection points.
  • Pointcut: pointcut, the real intercepted point, that is, the real enhanced method
  • Advice: notification, method level enhancement. Methods that enhance a method, such as permission verification for the save method, are called notifications.
  • Introduction: introduction, class level enhancement.
  • Target: target, enhanced object (class).
  • Weaving: weaving, the process of applying advice to target.
  • Proxy: proxy object, enhanced object.
  • Aspect: aspect, a combination of multiple notifications and multiple pointcuts.

usage method

  1. Import related packages

  2. Import profile

    <?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"> <!-- bean definitions here -->
    </beans>
    
  3. Write the target class and configure:

    public class ProductDaoImpl implements ProductDao {
        @Override
        public void save() {
            System.out.println("save");
        }
       
        @Override
        public void update() {
            System.out.println("update");
        }
      
        @Override
        public void find() {
            System.out.println("find");
        }
      
        @Override
        public void delete() {
            System.out.println("delete");
        }
    }
    
    <bean id="productDao" class="demo1.ProductDaoImpl"></bean>
    
  4. Write aspect classes, assuming that they are used for permission verification and configuration

    public class MyAspectXML {
        public void checkPri(){
            System.out.println("check auth");
        }
    }
    
    <bean id="myAspect" class="demo1.MyAspectXML"></bean>
    
  5. Enhance the target class through AOP configuration

    <aop:config>
    	<aop:pointcut expression="execution(* demo1.ProductDaoImpl.save(..))" id="pointcut1"/>
    	<aop:aspect ref="myAspect">
    		<aop:before method="chechPri" pointcut-ref="pointcut1"/>
    	</aop:aspect> 
    </aop:config>
    

Notification type

Before advice

Before the target method executes, the pointcut information can be obtained

<aop:before method="chechPri" pointcut-ref="pointcut1"/>		
public void checkPri(JoinPoint joinPoint){
	System.out.println("check auth "+joinPoint);
}

characteristic:

  1. Execute before target method
  2. The execution result of the target method will not be changed
  3. Does not affect the execution of the target method

Specify the parameter in the notification method: JoinPoint

JoinPoint: business method, which is the business method to add aspect function

The function is to obtain the information of method execution in the notification method, such as method name and method arguments. If you need method information in your aspect function, join point. The value of this JoinPoint parameter is given by the framework and must be the parameter of the first position

Method definition requirements:

  1. Public method public
  2. Method has no return value
  3. Method name customization
  4. Methods can have parameters or no parameters. If there are parameters, which are not user-defined, there are several parameter types that can be used

Post notification

After the target method executes the operation, the method return value can be obtained

<aop:after-returning method="writeLog" pointcut-ref="pointcut2" returning="result"/>
public void writeLog(Object result){
    System.out.println("writeLog "+result);
}

characteristic:

  1. Execute after target method
  2. The return value of the target method can be obtained, and different processing results can be made according to the return value
  3. You can modify the return value

Method definition requirements:

  1. Public method public
  2. Method has no return value
  3. Method name customization
  4. Method has parameters. It is recommended to use Object. The parameter name is user-defined

Around Advice

You can prevent the target method from executing before and after the target method executes

<aop:around method="around" pointcut-ref="pointcut3"/>
public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
    System.out.println("before");
    Object result=joinPoint.proceed();
    System.out.println("after");
    return result;
}
public Object myAround(ProceedingJoinPoint pjp) throws Throwable {
    String name = "";
    //Get the first parameter value
    Object[] args = pjp.getArgs();
    if(args!=null && args.length>1){
        Object arg = args[0];
        name = (String) arg;
    }
    //Implement surround notification
    Object result = null;
    System.out.println("Surround notification, before the target method, output time:"+new Date());
    //1. Target method call
    if("zhangsan".equals(name)){
        //If the conditions are met, call the target method
        result = pjp.proceed();  //method.invoke();  Object result = doFirst();
    }
    System.out.println("Surround the notification and commit the transaction after the target method");
    //2. Add functions before or after the target method
    if(result != null){
        result = "hello";
    }
    //Returns the execution result of the target method
    return result;
}

characteristic:

  1. It is the most powerful notification
  2. Functions can be added before and after the target method
  3. When the control target method is called and executed
  4. Modify the execution result of the original target method and affect the final call result

Definition mode of surrounding notification method:

  1. public
  2. There must be a return value. Object is recommended
  3. Method name customization
  4. Method consists of parameters, which are fixed ProceedingJoinPoint

Surround notification is equivalent to JDK dynamic proxy and InvocationHandler interface

Parameter: ProceedingJoinPoint is equivalent to Method in jdk dynamic proxy

Function: to execute the target method

Return value: is the execution result of the target method, which can be modified

Surround notification: do transactions frequently, start transactions before the target method, execute the target method, and submit transactions after the target method

Exception throw notification

Operation in case of program exception

<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut4" throwing="ex"/>
public void afterThrowing(Throwable ex){
	System.out.println("exception "+ex.getMessage());
}

characteristic:

  1. Executed when the target method throws an exception
  2. You can do an exception monitoring program to monitor whether there is an exception when the target method is executed. If there is an exception, you can send e-mail and SMS for notification

Definition format of exception notification method:

  1. public
  2. no return value
  3. Method name customization
  4. Method has an Exception parameter. If any, it is JoinPoint

Execution principle:

 	try{
        SomeServiceImpl.doSecond(..);
    } catch(Exception e){
        myAfterThrowing(e);
    }

Final notice

It is equivalent to a finally block, which will be executed regardless of whether there is an exception in the code

<aop:after method="finallyFunc" pointcut-ref="pointcut4"/>
public void finallyFunc(){
	System.out.println("finally");
}

Definition format of final notification method:

  1. public
  2. no return value
  3. Method name customization
  4. Method has no parameters. If it has parameters, it is JoinPoint

characteristic:

  1. Always execute
  2. Execute after target method

Spring pointcut expression

Based on the execution function

Syntax: [access modifier] method return value package name. Class name. Method name (parameter)

Any field can use * instead of any value

Spring's AOP is developed based on AspectJ annotations

Development steps

  1. Import jar package

  2. Set profile (Idea auto import):

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
    http://www.springframework.org/schema/tx 
    http://www.springframework.org/schema/tx/spring-tx.xsd">
    </beans>
    
  3. Write configuration target class

    <bean id="orderDao" class="demo1.OrderDao"></bean>
    
    public class OrderDao {
        public void save(){
            System.out.println("save order");
        }
        
        public void update(){
            System.out.println("update order");
        }
        
        public void delete(){
            System.out.println("delete order");
        }
      
        public void find(){
            System.out.println("find order");
        }
    }
    
  4. Turn on automatic proxy for aop annotations

    <aop:aspectj-autoproxy/>
    
  5. Write facet classes and configure

    @Aspect
    public class MyAspectAnno {
        @Before(value="execution(* demo1.OrderDao.save(..))")
        public void before(){
            System.out.println("before");
        }
    }
    
    <bean id="myAspect" class="demo1.MyAspectAnno">
    

    @Aspect: Annotation in aspectJ framework

    Function: indicates that the current class is a faceted class

    Aspect class: a class used to add functions to business methods. In this class, there are aspect function codes

    Location: above the class definition

Annotation notification type

@Before: advance notice

@Before(value = "execution(* *..SomeServiceImpl.do*(..))")
public void myBefore(JoinPoint joinPoint){
    //Gets the complete definition of the method
    System.out.println("Signature of method:"+joinPoint.getSignature());
    System.out.println("Name of method:"+joinPoint.getSignature().getName());
    //Gets the argument of the method
    Object[] objects = joinPoint.getArgs();
    for(Object obj:objects){
        System.out.println(obj);
    }
    //Is the function code to be executed
    System.out.println("Pre notification, aspect function "+new Date());
}

@Before: pre notification annotation

Attribute: value, is the pointcut expression, indicating the execution position of the function in the aspect

Location: above the method

characteristic:

  1. Execute before target method
  2. The execution result of the target method will not be changed
  3. Does not affect the execution of the target method

Specify the parameter in the notification method: JoinPoint

JoinPoint: business method, which is the business method to add aspect function

The function is to obtain the information of method execution in the notification method, such as method name and method arguments. If you need method information in your aspect function, join point. The value of this JoinPoint parameter is given by the framework and must be the parameter of the first position

Method definition requirements:

  1. Public method public
  2. Method has no return value
  3. Method name customization
  4. Methods can have parameters or no parameters. If there are parameters, which are not user-defined, there are several parameter types that can be used

@AfterReturning: Post notification

@AfterReturning(value = "execution(* *..SomeServiceImpl.doOther(..))",returning = "obj")
public void myAfterReturning(Object obj){
    //Object res: it is the return value of the target method after execution. The function processing of your aspect is performed according to the return value
    System.out.println("Post notification: executed after the target method, the returned value obtained:"+obj);
    if(obj.equals("abc")){

    } else{

    }

    //Modify the return value of the target method to see if it will affect the final method call result
    if(obj != null){
        obj = "hello";
    }
}

@After returning: Post notification

Properties:

  1. value, pointcut expression
  2. returning is a custom variable that represents the return value of the target method. The custom variable name must be the same as the formal parameter name of the notification method

Location: above the method definition

characteristic:

  1. Execute after target method
  2. The return value of the target method can be obtained, and different processing results can be made according to the return value
  3. You can modify the return value

Method definition requirements:

  1. Public method public
  2. Method has no return value
  3. Method name customization
  4. Method has parameters. It is recommended to use Object. The parameter name is user-defined

@Around: surround notification

@Around(value = "execution(* *..SomeServiceImpl.doFirst(..))")
public Object myAround(ProceedingJoinPoint pjp) throws Throwable {
    String name = "";
    //Get the first parameter value
    Object[] args = pjp.getArgs();
    if(args!=null && args.length>1){
        Object arg = args[0];
        name = (String) arg;
    }
    //Implement surround notification
    Object result = null;
    System.out.println("Surround notification, before the target method, output time:"+new Date());
    //1. Target method call
    if("zhangsan".equals(name)){
        //If the conditions are met, call the target method
        result = pjp.proceed();  //method.invoke();  Object result = doFirst();
    }
    System.out.println("Surround the notification and commit the transaction after the target method");
    //2. Add functions before or after the target method
    if(result != null){
        result = "hello";
    }
    //Returns the execution result of the target method
    return result;
}

@Around: surround notification

Properties:

value: pointcut expression

Location: above the method definition

characteristic:

  1. It is the most powerful notification
  2. Functions can be added before and after the target method
  3. When the control target method is called and executed
  4. Modify the execution result of the original target method and affect the final call result

Definition mode of surrounding notification method:

  1. public
  2. There must be a return value. Object is recommended
  3. Method name customization
  4. Method consists of parameters, which are fixed ProceedingJoinPoint

Surround notification is equivalent to JDK dynamic proxy and InvocationHandler interface

Parameter: ProceedingJoinPoint is equivalent to Method in jdk dynamic proxy

Function: to execute the target method

Return value: is the execution result of the target method, which can be modified

Surround notification: do transactions frequently, start transactions before the target method, execute the target method, and submit transactions after the target method

@AfterThrowing: throwing an exception

@AfterThrowing(value = "execution(* *..SomeServiceImpl.doSecond(..))",throwing = "exception")
public void myAfterThrowing(Exception exception){
    System.out.println("Exception notification, executed when an exception occurs in the method:"+exception.getMessage());
    //Send email and SMS to inform developers
}

@AfterThrowing: exception notification

Properties:

  1. value pointcut expression
  2. throwing is a custom variable that represents the exception object thrown by the target method. The variable name must be the same as the parameter name of the method

characteristic:

  1. Executed when the target method throws an exception
  2. You can do an exception monitoring program to monitor whether there is an exception when the target method is executed. If there is an exception, you can send e-mail and SMS for notification

Definition format of exception notification method:

  1. public
  2. no return value
  3. Method name customization
  4. Method has an Exception parameter. If any, it is JoinPoint

@After: final notification

@After(value = "execution(* *..SomeServiceImpl.doThird(..))")
public void myAfter(){
    System.out.println("Execute the final notification, which will always be executed");
    //Generally do resource cleanup
}

@After: final notification

Properties:

value pointcut expression

Location: above the method

Definition format of final notification method:

  1. public
  2. no return value
  3. Method name customization
  4. Method has no parameters. If it has parameters, it is JoinPoint

characteristic:

  1. Always execute
  2. Execute after target method

@PointCut: PointCut annotation

@Pointcut(value = "execution(* *..SomeServiceImpl.doThird(..))")
public void mypt(){

}
@After(value = "mypt()")
public void myAfter(){
    System.out.println("Execute the final notification, which will always be executed");
    //Generally do resource cleanup
}

@Before(value = "mypt()")
public void myBefore(){
    System.out.println("Execute pre notification");
}

@Pointcut: define and manage pointcuts. If multiple pointcut expressions in your project are repeated and can be reused, you can use @ pointcut

Properties:

value pointcut expression

Location: above the custom method

characteristic:

  • When @ Pointcut is defined on a method, the name of the method is the alias of the Pointcut expression.
  • In other notifications, the value attribute can use this method name instead of the pointcut expression

Spring JDCB template

Spring also provides a solution for the persistence layer, that is, ORM module and JDBC template.

For JDBC, org.springframework.jdbc.core.JdbcTemplate is provided as the template class.

Using JDBC templates

  1. Introduce jar package, database driver and jdbc related packages of Spring.

  2. Basic usage:

    public void demo1(){
        //Create connection pool
        DriverManagerDataSource dataSource=new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql:///spring4");
        dataSource.setUsername("root");
        dataSource.setPassword("123456");
        //Create JDBC template 
        JdbcTemplate jdbcTemplate=new JdbcTemplate(dataSource);
        jdbcTemplate.update("insert into account values (null,?,?)" , "xiaoming",1000d);
    }
    
  3. Leave the connection pool and template to Spring management

    • Profile:

      <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource;">
      <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
      <property name="url" value="jdbc:mysql:///spring4"></property>
      <property name="username" value="root"></property>
      <property name="password" value="123456"></property>
      </bean>
      
      <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate;"> 
      <property name="dataSource" ref="dataSource"></property>
      </bean>
      
    • Test documents:

      @RunWith(SpringJUnit4ClassRunner.class)
      @ContextConfiguration("classpath:applicationContext.xml")
      public class JdbcDemo2 {
      
          @Resource(name="jdbcTemplate")
          private JdbcTemplate jdbcTemplate;
          
          @Test
          public void demo2(){
              jdbcTemplate.update("insert into account values (null,?,?)" , "xiaolan",1000d);
          }
      }
      

Use open source database connection pool

  1. Configuration using DBCP:

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
    <property name="url" value="jdbc:mysql://192.168.66.128/spring4"></property>
    <property name="username" value="root"></property>
    <property name="password" value="123456"></property>
    
  2. Configuration using C3P0:

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
    <property name="jdbcUrl" value="jdbc:mysql://192.168.66.128/spring4"></property>
    <property name="user" value="root"></property>
    <property name="password" value="123456"></property>
    </bean>
    
  3. Import external properties file

    • First, create an external properties file

      jdbc.driverClass=com.mysql.jdbc.Driver
      jdbc.url=jdbc:mysql://192.168.66.128/spring4
      jdbc.username=root
      jdbc.password=123456
      
    • Then configure the properties file

      <context:property-placeholder location="classpath:jdbc.properties"/>
      <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
      <property name="driverClass" value="${jdbc.driverClass}"></property>
      <property name="jdbcUrl" value="${jdbc.url}"></property>
      <property name="user" value="${jdbc.username}"></property>
      <property name="password" value="${jdbc.password}"></property>
      </bean>
      

CRUD operation

Insert, update and delete statements operate with the template's update method.

public void demo(){
	jdbcTemplate.update("insert into account values (null,?,?)", "xiaoda",1000d);
	jdbcTemplate.update("update account set name=?,money=? where id=?", "xiaoda",1000d,2);
	jdbcTemplate.update("delete from account where id=?", 6);
}

Query operation:

public void demo3(){
	String name=jdbcTemplate.queryForObject("select name from account where id=?",String.class,5);
	long count=jdbcTemplate.queryForObject("select count(*) from account",Long.class);
}

Encapsulate the returned results into classes:

public void demo4(){
    Account account = jdbcTemplate.queryForObject("select * from account where id=?", new MyRowMapper(),5);
}

Of which:

class MyRowMapper implements RowMapper<Account>{
    @Override
    public Account mapRow(ResultSet rs, int rowNum) throws SQLException {
    	Account account=new Account();
    	account.setId(rs.getInt("id"));
    	account.setName(rs.getString("name"));
    	account.setMoney(rs.getDouble("money"));
    	return account;
    }
}

Transaction management in Spring

A transaction is a logical group of operations. The units that make up this group of operations either succeed or fail.

It has four characteristics:

  • Atomicity: transaction indivisibility
  • Consistency: data integrity is consistent before and after transaction execution
  • Isolation: the execution of one transaction should not be disturbed by other transactions
  • Persistence: once the transaction ends, the data is persisted to the database

If isolation is not considered, it will cause security problems:

  • Read questions:

    • Dirty read: one transaction reads uncommitted data from another transaction
    • Non repeatable reading: one transaction reads the update data submitted by another transaction, resulting in inconsistent query results multiple times in one transaction
    • Phantom reading: one transaction reads the insert data submitted by another transaction, resulting in inconsistent query results multiple times in one transaction
  • Write questions:

    • Missing updates

Solve read problem: set transaction isolation level

  • Read uncommitted: read uncommitted, unable to resolve any read issues
  • Read committed: the read has been committed, and the dirty read problem has been solved
  • Repeatable read: repeat read to solve the problems of dirty read and non repeatable read
  • Serializable: serialization to solve all read problems

Transaction Management API

  1. Platform transaction manager: platform transaction manager

    This is an interface with several different implementation classes. For example, the underlying layer of DataSourceTransactionManager uses JDBC to manage transactions; The underlying Hibernate transaction manager uses Hibernate to manage transactions.

  2. Transaction definition: transaction definition information is used to define transaction related information, such as isolation level, timeout information, propagation behavior, read-only, etc

  3. TransactionStatus: transaction status: an object used to record the status of transactions during transaction management.

Relationship between the above API s: when Spring performs transaction management, first, the platform transaction manager performs transaction management according to the transaction definition information. In the process of transaction management, various states are generated and these state information is recorded in the object of transaction state.

Propagation behavior of transactions

The propagation behavior of transactions mainly solves the problem of mutual call of business layer (Service) methods, that is, how to operate when there are different transactions in different businesses.

Spring provides seven transaction propagation behaviors, which are divided into three categories:

  • Ensure that multiple operations are in the same transaction

    • PROPAGATION_ Required: Method B calls method A. if there is a transaction in a, the transaction in a is used and the operation in B is included in the transaction; Otherwise, create a new transaction to include the operations in a and B. (default)
    • PROPAGATION_SUPPORTS: if there are transactions in A, use the transactions of A; Otherwise, do not use transactions
    • PROPAGATION_MANDATORY: if there are transactions in A, use the transactions of A; Otherwise, an exception is thrown
  • Ensure that multiple operations are not in the same transaction

    • PROPAGATION_REQUIRES_NEW: if there is A transaction in A, suspend it and create A new transaction, including only its own operations. Otherwise, create A new transaction that contains only its own operations.
    • PROPAGATION_NOT_SUPPORTED: if there are transactions in A, suspend and do not use transactions.
    • PROPAGATION_NEVER: if there is A transaction in A, an exception is thrown, that is, it cannot be run with A transaction.
  • Nested transaction

    • PROPAGATION_NESTED: if A has A transaction, execute it according to A's transaction. After execution, set A savepoint, and then execute B's operation. If an exception occurs, you can roll back to the original state or savepoint state.

example

Take the transfer as an example, the DAO layer classes of the business layer are as follows:

public interface AccountDao {
	public void outMoney(String from,Double money);
	public void inMoney(String to,Double money);
}
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao{
    @Override
    public void outMoney(String from, Double money) {
        this.getJdbcTemplate().update("update account set money = money - ? where name = ?",money,from);
    }
	
    @Override
    public void inMoney(String to, Double money) {
        this.getJdbcTemplate().update("update account set money = money + ? where name = ?",money,to);
    }
}
public interface AccountService {
    public void transfer(String from,String to,Double money);
}
public class AccountServiceImpl implements AccountService {
    private AccountDao accountDao;
    public void setAccountDao(AccountDao accountDao) {
      this.accountDao = accountDao;
    }

    @Override
    public void transfer(String from, String to, Double money) {
        accountDao.outMoney(from, money);
        accountDao.inMoney(to, money);
    }
}

Configure classes in xml:

<bean id="accountService" class="tx.demo.AccountServiceImpl">
	<property name="accountDao" ref="accountDao"/>
</bean>

<bean id="accountDao" class="tx.demo.AccountDaoImpl">
	<property name="dataSource" ref="dataSource"/>
</bean>

Transaction management 1: programming transaction management

  1. Configure platform transaction manager

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    	<property name="dataSource" ref="dataSource"></property>
    </bean>
    
  2. Configure transaction management template class

    <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
    	<property name="transactionManager" ref="transactionManager"></property>
    </bean>
    
  3. Inject transaction management template in business layer

    <bean id="accountService" class="tx.demo1.AccountServiceImpl">
    	<property name="accountDao" ref="accountDao"/>
    	<property name="transactionTemplate" ref="transactionTemplate"/>
    </bean>
    
  4. Coding for transaction management

    //In ServiceImpl class:
    private TransactionTemplate transactionTemplate;
    
    @Override
    public void transfer(String from, String to, Double money) {
      	transactionTemplate.execute(new TransactionCallbackWithoutResult() {
      		@Override
      		protected void doInTransactionWithoutResult(TransactionStatus arg0) {
        			accountDao.outMoney(from, money);
        			accountDao.inMoney(to, money);
      		}
        };
    }
    

Declarative transaction management (configuration implementation, based on AOP idea)

  1. Declarative transaction management based on XML

    • Configure transaction manager

      <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
      	<property name="dataSource" ref="dataSource"></property>
      </bean>
      
    • Configure transaction notifications

      <tx:advice id="txAdvice" transaction-manager="transactionManager">
      	<tx:attributes>
      		<tx:method name="transfer" propagation="REQUIRED"/>
      	</tx:attributes>
      </tx:advice>
      
    • Configuring aop transactions

      <aop:config>
      	<aop:pointcut expression="execution(* tx.demo2.AccountServiceImpl.*(..))" id="pointcut1"/>
      	<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"/>
      </aop:config>
      
  2. Annotation method

    • Configure the transaction manager, consistent with the above

    • Notes for opening transaction management:

      <tx:annotation-driven transaction-manager="transactionManager"/>
      
    • Add an annotation @ Transactional on the class that uses transactions

In this paper This blog post Based on
Author: supingemail
Original address: https://blog.csdn.net/supingemail/article/details/85988220

Tags: Java Spring

Posted on Sun, 28 Nov 2021 09:54:12 -0500 by Danicek