spring learning notes

Posted by shibiny on Wed, 15 Dec 2021 15:55:03 +0100

1. Spring overview

1.1 INTRODUCTION

  • Spring: spring -- > brings spring to the software industry
  • In 2002, Rod Jahnson first launched the Spring framework prototype interface21 framework.
  • On March 24, 2004, the Spring framework was redesigned based on the interface 21 framework and released the official version of 1.0.
  • It's hard to imagine Rod Johnson's degree. He is a doctor at the University of Sydney. However, his major is not computer, but musicology.
  • Spring concept: make the existing technology more practical. Itself is a hodgepodge, integrating existing framework technologies

Official website: spring.io/

Official download address: repo.spring.io/libs-releas...

GitHub : github.com/spring-proj...

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.0.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.2.0.RELEASE</version>
</dependency>
Copy code

1.2 advantages

  • Spring is an open source free framework (container)!
  • Spring is a lightweight, non intrusive framework!
  • Inversion of control (IOC), aspect oriented programming (AOP)!
  • Support transaction processing and framework integration!

To sum up: Spring is a lightweight inversion of control (IOC) and aspect oriented programming (AOP) framework!

1.3 composition

The spring framework is a layered architecture consisting of seven well-defined modules. Spring module is built on the core container, which defines the way to create, configure and manage bean s

Each module (or component) that makes up the Spring framework can exist alone or be implemented jointly with one or more other modules. The functions of each module are as follows:

  • Spring Core: the core container provides the basic functions of the spring framework. The main component of the core container is BeanFactory, which is the implementation of the factory pattern. BeanFactory uses the (IOC) pattern to separate the configuration and dependency specifications of the application from the actual application code.

  • Spring Context: Spring context is a configuration file that provides context information to the spring framework. The spring context includes enterprise services such as JNDI, EJB, e-mail, internationalization, checksum and scheduling capabilities.

  • Spring AOP: through the configuration management feature, the spring AOP module directly integrates aspect oriented programming functions into the spring framework. Therefore, you can easily make the spring framework manage any object that supports AOP. The spring AOP module provides transaction management services for objects in spring based applications. By using spring AOP, declarative transaction management can be integrated into applications without relying on components.

  • Spring DAO: the JDBC DAO abstraction layer provides a meaningful exception hierarchy that can be used to manage exception handling and error messages thrown by different database vendors. The exception hierarchy simplifies error handling and greatly reduces the amount of exception code that needs to be written (such as opening and closing connections). Spring DAO's JDBC oriented exceptions follow a common DAO exception hierarchy.

  • Spring ORM: the spring framework inserts several ORM frameworks to provide ORM object relationship tools, including JDO, Hibernate and iBatis SQL Map. All of this follows spring's common transaction and DAO exception hierarchy.

  • Spring Web: the spring web module is built on the application context module and provides context for web-based applications. Therefore, the spring framework supports integration with Jakarta Struts. The web module also simplifies processing multipart requests and binding request parameters to domain objects.

  • Spring MVC framework: the MVC framework is a fully functional MVC implementation for building Web applications. Through the policy interface, the MVC framework becomes highly configurable. MVC accommodates a large number of view technologies, including JSP, Velocity, Tiles, iText and POI.

1.4 expansion

Spring Boot and Spring Cloud

  • Spring Boot is a set of rapid configuration scaffolds of spring, which can quickly develop a single microservice based on Spring Boot;
  • Spring Cloud is implemented based on Spring Boot;
  • Spring Boot focuses on a single micro service individual that is fast and easy to integrate. Spring Cloud focuses on the overall service governance framework;
  • Spring Boot uses the concept of constraint over configuration. Many integration schemes have been selected for you. You can't configure without configuration,
  • A large part of Spring Cloud is implemented based on Spring Boot. Spring Boot can be used independently of Spring Cloud for development projects, but Spring Cloud cannot be separated from Spring Boot and belongs to dependency.
  • SpringBoot plays a connecting role in SpringClound. If you want to learn spring cloud, you must learn SpringBoot.

2. IOC essence

Inversion of control (IoC) is a design idea. DI (dependency injection) is a method to realize IoC. Some people think that DI is just another way of saying IoC. In programs without IoC, we use object-oriented programming. The creation of objects and the dependencies between objects are completely hard coded. In programs, the creation of objects is controlled by the program itself. After the control is reversed, the creation of objects is transferred to a third party. Personally, I think the so-called control reversal is the reversal of the way to obtain dependent objects.

IOC is the core content of the Spring framework. IOC is perfectly implemented in a variety of ways. You can use XML configuration or annotations. The new version of Spring can also implement IOC with zero configuration. During initialization, the Spring container reads the configuration file first, creates and organizes objects according to the configuration file or metadata, and stores them in the container. When the program is used, it takes out the required objects from the IOC container.

3,HelloSpring

3.1. Import Jar package

Note: spring needs to import commons logging for logging We use maven, which will automatically download the corresponding dependencies

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-webmvc</artifactId>
  <version>5.1.10.RELEASE</version>
</dependency>
Copy code

3.2. Code writing

  1. Write an entity class
package com.angus.pojo;

/**
 * @description:
 * @author: angus
 * @date: 2021/12/13 10:14
 */
public class Hello {
    private String name;

    public String getName() {
        return name;
    }

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


    public void show(){
        System.out.println("Hello," + name );
    }
}
Copy code
  1. Write our spring file, here we name it beans xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">


    <!--use Spring To create an object, in Spring These are called Bean
    Type variable name = new type();
    Hello hello = new Hello();

    id = Variable name
    class = new Object of
    property It is equivalent to setting a value for the attribute in the object!
        -->
    <bean id="hello" class="com.angus.pojo.Hello">
        <property name="name" value="NameOfSpring"/>
    </bean>
</beans>
Copy code
  1. test
@Test
public void test(){
  //Parse beans XML file to generate and manage the corresponding Bean objects
  ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
  
  //getBean: the parameter is the id of the bean in the spring configuration file
  Hello hello = (Hello) context.getBean("hello");
  hello.show();
}
Copy code

3.3 thinking

  • Who created the hello object? [the hello object is created by Spring]
  • How are the properties of the Hello object set? [the properties of the Hello object are set by the Spring container]

This process is called control reversal:

  • Control: who controls the creation of objects? Traditional application objects are created by the program itself. After using Spring, objects are created by Spring
  • Inversion: the program itself does not create an object, but becomes a passive receiving object

Dependency injection: it uses the set method to inject

IOC is a programming idea, from active programming to passive reception

You can browse the underlying source code through the new ClassPathXmlApplicationContext

3.4. Case modification

<?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="MysqlImpl" class="com.kuang.dao.impl.UserDaoMySqlImpl"/>
  <bean id="OracleImpl" class="com.kuang.dao.impl.UserDaoOracleImpl"/>
  
  <bean id="ServiceImpl" class="com.kuang.service.impl.UserServiceImpl">
    <!--be careful: there name Is not an attribute , But set The part behind the method , Initial lowercase-->
    <!--Reference another bean , Not with value But with ref-->
    <property name="userDao" ref="OracleImpl"/>
  </bean>
</beans>
Copy code

We don't need to change it in the program at all. To realize different operations, we only need to modify it in the xml configuration file. The so-called IoC is done in one sentence: the objects are created, managed and assembled by Spring!

4. IOC object creation method

4.1. Create by parameterless construction method

  1. User.java
public class User {
  private String name;
  public User() {
    System.out.println("user Nonparametric construction method");
 }
  public void setName(String name) {
    this.name = name;
 }
  public void show(){
    System.out.println("name="+ name );
 }
}
Copy code
  1. beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd">
  <bean id="user" class="com.kuang.pojo.User">
    <property name="name" value="kuangshen"/>
  </bean>
</beans>
Copy code
  1. Test class
@Test
public void test(){
  ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
  //When the getBean is executed, the user has been created and constructed without parameters
  User user = (User) context.getBean("user");
  //Call the method of the object
  user.show();
}
Copy code

4.2. Create by parametric construction method

  1. UserT.java
public class UserT {
  private String name;
  public UserT(String name) {
    this.name = name;
     }
  public void setName(String name) {
    this.name = name;
 }
  public void show(){
    System.out.println("name="+ name );
 }
}
Copy code
  1. beans.xml can be written in three ways
<!-- First basis index Parameter subscript setting -->
<bean id="userT" class="com.kuang.pojo.UserT">
  <!-- index Refers to the construction method , Subscript starts at 0 -->
  <constructor-arg index="0" value="kuangshen2"/>
</bean>
Copy code
<!-- The second is set according to the parameter name -->
<bean id="userT" class="com.kuang.pojo.UserT">
  <!-- name Refers to the parameter name -->
  <constructor-arg name="name" value="kuangshen2"/>
</bean>
Copy code
<!-- The third is set according to the parameter type -->
<bean id="userT" class="com.kuang.pojo.UserT">
  <constructor-arg type="java.lang.String" value="kuangshen2"/>
</bean>
Copy code
  1. test
@Test
public void testT(){
  ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
  UserT user = (UserT) context.getBean("userT");
  user.show();
}
Copy code

Conclusion: when the configuration file is loaded. The managed objects have been initialized!

5. Spring configuration

5.1. alias

Alias sets an alias for a bean. You can set multiple aliases

<!--Setting alias: getting Bean You can use alias to get-->
<alias name="userT" alias="userNew"/>
Copy code

5.2. Bean configuration

<!--bean namely java object,from Spring Create and manage-->
<!--
  id yes bean Identifier of,To be unique,If not configured id,name Is the default identifier
  If configured id,Configured again name,that name It's an alias
  name You can set multiple aliases,You can use commas,semicolon,Space separated
  If not configured id and name,Can be based on applicationContext.getBean(.class)Get object;
class yes bean Fully qualified name of=Package name+Class name
-->
<bean id="hello" name="hello2 h2,h3;h4" class="com.kuang.pojo.Hello">
  <property name="name" value="Spring"/>
</bean>
Copy code

5.3. import

Team cooperation is achieved through import

<import resource="{path}/beans.xml"/> 
Copy code

6. Dependency injection (DI)

  • Dependency injection (DI).
  • Dependency: the creation of Bean objects depends on the container The dependent resources of the Bean object
  • Injection: refers to the resources that the Bean object depends on, which are set and assembled by the container

6.1 constructor injection

Refer to 4. How IOC creates objects

6.2 set injection (key)

The injected attribute must have a set method. The method name of the set method is capitalized by the initial letter of set + attribute. If the attribute is of boolean type and there is no set method, it is

Test pojo class: address java

public class Address {
  private String address;
  public String getAddress() {
    return address;
 }
  public void setAddress(String address) {
    this.address = address;
 }
}
Copy code

Student.java

package com.angus.pojo;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public class Student {
  private String name;
  private Address address;
  private String[] books;
  private List<String> hobbys;
  private Map<String,String> card;
  private Set<String> games;
  private String wife;
  private Properties info;
  public void setName(String name) {
    this.name = name;
 }
  public void setAddress(Address address) {
    this.address = address;
 }
  public void setBooks(String[] books) {
    this.books = books;
 }
  public void setHobbys(List<String> hobbys) {
    this.hobbys = hobbys;
 }
  public void setCard(Map<String, String> card) {
    this.card = card;
 }
  public void setGames(Set<String> games) {
    this.games = games;
 }
  public void setWife(String wife) {
    this.wife = wife;
 }
  public void setInfo(Properties info) {
    this.info = info;
 }
  public void show(){
    System.out.println("name="+ name
        + ",address="+ address.getAddress()
        + ",books="
   );
    for (String book:books){
      System.out.print("<<"+book+">>\t");
   }
    System.out.println("\n hobby:"+hobbys);
    System.out.println("card:"+card);
    System.out.println("games:"+games);
    System.out.println("wife:"+wife);
    System.out.println("info:"+info);
 }
}
Copy code

1. Constant injection

<bean id="student" class="com.angus.pojo.Student">
  <property name="name" value="Xiao Ming"/>
</bean>
Copy code

Test:

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        
        Student student = (Student) context.getBean("student");
        System.out.println(student.getName());
    }
}
Copy code

2. Bean injection

Note: the value here is a reference, ref

<bean id="addr" class="com.angus.pojo.Address">
  <property name="address" value="Chongqing"/>
</bean>
<bean id="student" class="com.angus.pojo.Student">
  <property name="name" value="angus"/>
  <property name="address" ref="addr"/>
</bean>
Copy code

3. Array injection

<bean id="student" class="com.angus.pojo.Student">
  <property name="name" value="angus"/>
  <property name="address" ref="addr"/>
  <property name="books">
    <array>
      <value>Journey to the West</value>
      <value>The Dream of Red Mansion</value>
      <value>Water Margin</value>
    </array>
  </property>
</bean>
Copy code

4. List injection

<property name="hobbys">
  <list>
    <value>listen to the music</value>
    <value>watch movie</value>
    <value>Mountain climbing</value>
  </list>
</property>
Copy code

5. Map injection

<property name="card">
  <map>
    <entry key="China Post" value="456456456465456"/>
    <entry key="build" value="1456682255511"/>
  </map>
</property>
Copy code

6. set injection

<property name="games">
  <set>
    <value>LOL</value>
    <value>BOB</value>
    <value>COC</value>
  </set>
</property>
Copy code

7. Null injection

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

8. Properties injection

<property name="info">
  <props>
    <prop key="Student number">20190604</prop>
    <prop key="Gender">male</prop>
    <prop key="full name">angus</prop>
  </props>
</property>
Copy code

test result

6.3 realization of expansion injection

User.java: [Note: there is no parameter constructor here!]

public class User {
  private String name;
  private int age;
  public void setName(String name) {
    this.name = name;
 }
  public void setAge(int age) {
    this.age = age;
 }
  @Override
  public String toString() {
    return "User{" +
        "name='" + name + '\'' +
        ", age=" + age +
        '}';
 }
}
Copy code

1. P namespace injection: you need to create a constraint file in the header file

Import constraints : xmlns:p="http://www.springframework.org/schema/p"
<!--P(attribute: properties)Namespace , Property should still be set set method-->
<bean id="user" class="com.angus.pojo.User" p:name="Mad God" p:age="18"/>
Copy code

2. c namespace injection: constraint files need to be added to the header file

Import constraints : xmlns:c="http://www.springframework.org/schema/c"
<!--C(structure: Constructor)Namespace , Property should still be set set method-->
<bean id="user" class="com.kuang.pojo.User" c:name="Mad God" c:age="18"/>
Copy code

Problem found: it's red. We didn't write a reference structure just now! Solution: add the parameter constructor, and you can know here that c is the so-called constructor injection!

Test code:

@Test
public void test02(){
  ApplicationContext context = new
ClassPathXmlApplicationContext("applicationContext.xml");
  User user = (User) context.getBean("user");
  System.out.println(user);
}
Copy code

6.4 scope of bean

In Spring, the main bodies that make up the application and the objects managed by the Spring IoC container are called beans. Simply put, a bean is an object initialized, assembled and managed by the IoC container

Among the several scopes, the request and session scopes are only used in web-based applications (don't care what web application framework you use), and can only be used in Web-based Spring ApplicationContext environment.

6.4.1 Singleton

When the scope of a bean is singleton, there will only be one shared bean instance in the Spring IoC container, and all requests for a bean will only return the same instance of the bean as long as the id matches the bean definition. Singleton is a singleton type, which automatically creates a bean object when creating a container. It exists whether you use it or not, and the object obtained each time is the same object. Note that the singleton scope is the default scope in Spring. To define a bean as a singleton in XML, you can configure it as follows:

<bean id="ServiceImpl" class="cn.csdn.service.ServiceImpl" scope="singleton"> 
Copy code

Test:

@Test
public void test03(){
  ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
  User user = (User) context.getBean("user");
  User user2 = (User) context.getBean("user");
  System.out.println(user==user2);
}
Copy code

6.4.2 Prototype

When the scope of a bean is prototype, it means that a bean definition corresponds to multiple object instances. A prototype scoped bean will cause a new bean instance to be created each time a request is made to the bean (inject it into another bean, or call the container's getBean() method programmatically). Prototype is a prototype type. It is not instantiated when we create a container. Instead, we create an object when we obtain a bean, and the object we obtain each time is not the same object. As a rule of thumb, you should use the prototype scope for stateful beans and the singleton scope for stateless beans. Define a bean as a prototype in XML, which can be configured as follows:

<bean id="account" class="com.foo.DefaultAccount" scope="prototype"/> 
perhaps
<bean id="account" class="com.foo.DefaultAccount" singleton="false"/>
Copy code

6.4.3 Request

When the scope of a bean is Request, it means that in an HTTP Request, a bean definition corresponds to an instance; That is, each HTTP Request will have its own bean instance, which is created according to a bean definition. This scope is only valid in the case of web-based Spring ApplicationContext. Consider the following bean definitions:

<bean id="loginAction" class=cn.csdn.LoginAction" scope="request"/> 
Copy code

For each HTTP request, the Spring container will create a new loginaction bean instance according to the loginaction bean definition, and the loginaction bean instance is only valid in the current HTTP request. Therefore, you can safely change the internal state of the created instance according to the needs, while the instances created according to the loginaction bean definition in other requests, You will not see these state changes specific to a request. When the processing of the request ends, the bean instance of the request scope will be destroyed.

6.4.4 Session

When the scope of a bean is Session, it means that in an HTTP Session, a bean definition corresponds to an instance. This scope is only valid in the case of web-based Spring ApplicationContext. Consider the following bean definitions:

<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/> 
Copy code

For an HTTP Session, the Spring container will create a new userPreferences bean instance according to the userPreferences bean definition, and the userPreferences bean is only valid in the current HTTP Session. Like the request scope, you can safely change the internal state of the created instance as needed. For instances created according to userPreferences in other HTTP sessions, you will not see these state changes specific to an HTTP Session. When the HTTP Session is finally discarded, the beans within the scope of the HTTP Session will also be discarded.

7. Automatic assembly of Bean

  • Automatic assembly is a way to use spring to meet bean dependencies
  • spring will find the bean that a bean depends on in the application context.

There are three assembly mechanisms for bean s in Spring:

  1. Explicit configuration in xml;
  2. Explicit configuration in java;
  3. Implicit bean discovery mechanism and automatic assembly.

Here we mainly talk about the third kind: automated assembly bean.

Spring's automatic assembly needs to be implemented from two perspectives, or two operations:

  1. Component scanning: spring will automatically discover the bean s created in the application context;
  2. Autowiring: spring automatically satisfies the dependencies between bean s, which is what we call IoC/DI;

The combination of component scanning and automatic assembly exerts great power to minimize the configuration of display.
It is recommended to use annotations instead of automatic assembly xml configuration

7.1 construction of test environment

  1. Create a new project
  2. Create two new entity classes. Cat Dog has a method called
public class Cat {
  public void shout() {
    System.out.println("miao~");
 }
}
Copy code
public class Dog {
  public void shout() {
    System.out.println("wang~");
 }
}
Copy code
  1. Create a new User class User
public class User {
  private Cat cat;
  private Dog dog;
  private String str;
}
Copy code
  1. Writing Spring configuration files
<?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="dog" class="com.angus.pojo.Dog"/>
  <bean id="cat" class="com.angus.pojo.Cat"/>
  <bean id="user" class="com.angus.pojo.User">
    <property name="cat" ref="cat"/>
    <property name="dog" ref="dog"/>
    <property name="str" value="qinjiang"/>
  </bean>
</beans>
Copy code
  1. test
public class MyTest {
  @Test
  public void testMethodAutowire() {
    ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
    User user = (User) context.getBean("user");
    user.getCat().shout();
    user.getDog().shout();
 }
}
Copy code

7.2,byName

autowire byName (automatic assembly by name) can not be checked due to the frequent errors such as missing letters and case in the process of manually configuring xml, which reduces the development efficiency. Using automatic assembly will avoid these errors and simplify the configuration.

Test:

  1. Modify the bean configuration and add an attribute autowire="byName"
<bean id="user" class="com.angus.pojo.User" autowire="byName">
  <property name="str" value="qinjiang"/>
</bean>
Copy code
  1. Test again and the result is still output successfully!
  2. We modify the bean id of cat to catXXX
  3. Test again and execute the null pointer Java lang.NullPointerException. Because the wrong set method is found according to the byName rule, the real setCat is not executed and the object is not initialized, so a null pointer error will be reported when calling.

Summary: when a bean node has the attribute autowire byName.

  1. All set method names in its class, such as setCat, will be searched to obtain a string with set removed and lowercase, that is, cat.
  2. Go to the spring container to find whether there is an object with this string name id.
  3. If any, take out the injection; If not, a null pointer exception is reported.

7.3,byType

autowire byType (auto assemble by type) using autowire byType first needs to ensure that objects of the same type are unique in the spring container. If it is not unique, a non unique exception will be reported.

NoUniqueBeanDefinitionException 
Copy code

Test:

  1. Modify the bean configuration of user: autowire="byType"
  2. Test, normal output
  3. Register a cat bean object!
<bean id="dog" class="com.angus.pojo.Dog"/>
<bean id="cat" class="com.angus.pojo.Cat"/>
<bean id="cat2" class="com.angus.pojo.Cat"/>
<bean id="user" class="com.angus.pojo.User" autowire="byType">
  <property name="name" value="angus"/>
</bean>
Copy code
  1. Test, error: NoUniqueBeanDefinitionException
  2. Delete cat2 and change the bean name of cat! Test! Because it is assembled by type, it will not report exceptions and will not affect the final assembly

Results. Even removing the id attribute does not affect the result.

This is automatic assembly by type!

7.4 use notes

jdk1.5 start supporting annotations, spring 2 5 begin to fully support annotations.
Preparation: inject attributes by annotation.

  1. Introduce the context file header into the spring configuration file
xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
 Copy code

Results after adding

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd"
>
    <context:annotation-config/>
    <bean id="dog" class="com.angus.pojo.Dog"/>
    <bean id="cat" class="com.angus.pojo.Cat"/>
    <bean id="user" class="com.angus.pojo.User"/>

</beans>

Copy code
  1. Enable attribute annotation support!
<context:annotation-config/> 
Copy code

7.4.1,@Autowired

  • @Autowired is automatically transferred by type and does not support id matching.
  • You need to import the package of spring AOP!

Test:

  1. Remove the set method from the User class and use the @ Autowired annotation
public class User {
  @Autowired
  private Cat cat;
  @Autowired
  private Dog dog;
  private String str;
  public Cat getCat() {
    return cat;
 }
  public Dog getDog() {
      return dog;
 }
  public String getStr() {
    return str;
 }
}
Copy code
  1. The contents of the configuration file are displayed
<context:annotation-config/>
<bean id="dog" class="com.kuang.pojo.Dog"/>
<bean id="cat" class="com.kuang.pojo.Cat"/>
<bean id="user" class="com.kuang.pojo.User"/>
Copy code
  1. Test, output results successfully!

@Autowired(required=false) Description: false, the object can be null; true, the object must be saved and cannot be null.

//If the allowed object is null, set required = false, and the default is true
@Autowired(required = false)
private Cat cat;
Copy code

7.4.2,@Qualifier

  • @Autowired is automatically assembled according to the type. With @ Qualifier, it can be automatically assembled according to byName
  • @Qualifier cannot be used alone.

Test steps:

  1. Modify the content of the configuration file to ensure that there are objects of type. And the name is not the default name of the class!
<bean id="dog1" class="com.kuang.pojo.Dog"/>
<bean id="dog2" class="com.kuang.pojo.Dog"/>
<bean id="cat1" class="com.kuang.pojo.Cat"/>
<bean id="cat2" class="com.kuang.pojo.Cat"/>
Copy code
  1. No Qualifier test was added and an error was reported directly
  2. Add a Qualifier annotation to the attribute
@Autowired
@Qualifier(value = "cat2")
private Cat cat;
@Autowired
@Qualifier(value = "dog2")
private Dog dog;
Copy code
  1. Test, successful output!

7.4.3,@Resource

  • @If the Resource has a specified name attribute, first search the assembly by name according to the attribute;
  • Secondly, assemble in the default byName mode;
  • If none of the above is successful, it will be assembled automatically by byType.
  • If they are not successful, an exception is reported.

Entity class:

public class User {
  //If the allowed object is null, set required = false, and the default is true
  @Resource(name = "cat2")
  private Cat cat;
  @Resource
  private Dog dog;
  private String str;
}
Copy code

beans.xml

<bean id="dog" class="com.kuang.pojo.Dog"/>
<bean id="cat1" class="com.kuang.pojo.Cat"/>
<bean id="cat2" class="com.kuang.pojo.Cat"/>
<bean id="user" class="com.kuang.pojo.User"/>
Copy code

Test result: OK configuration file 2: beans XML, delete cat2

<bean id="dog" class="com.kuang.pojo.Dog"/>
<bean id="cat1" class="com.kuang.pojo.Cat"/>
Copy code

Only annotations are retained on entity classes

@Resource
private Cat cat;
@Resource
private Dog dog;
Copy code

Result: OK
Conclusion: byName search failed first; The byType search is successful.

7.5 summary

@Similarities and differences between Autowired and @ Resource:

  1. @Both Autowired and @ Resource can be used to assemble bean s. Can be written on a field or on a setter method.
  2. @Autowired is assembled by type by default (belonging to the spring specification). By default, dependent objects must exist. If null value is allowed, its required property can be set to false, such as @ Autowired(required=false). If we want to use name assembly, it can be used in combination with @ Qualifier annotation
  3. @Resource (belonging to J2EE complex), the assembly is performed by name by default, and the name can be specified through the name attribute. If the name attribute is not specified, when the annotation is written on the field, the default is to find the field name by name. If the annotation is written on the setter method, the default is to find the property name for assembly. When the bean matching the name cannot be found, the assembly is performed by type. However It should be noted that once the name attribute is specified, it will only be assembled by name. They have the same function. They inject objects by annotation, but the execution order is different@ Autowired byType first, @ resource byName first.

8. Using annotation development

8.1 description

After spring 4, if you want to use annotation form, you must introduce aop package

In the configuration file, a context constraint must also be introduced

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:context="http://www.springframework.org/schema/context"
   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">
</beans>
Copy code

8.2 implementation of Bean

We used to use bean tags for bean injection, but in actual development, we usually use annotations!

  1. Configure which packages to scan for annotations
<!--Specify annotation scan package-->
<context:component-scan base-package="com.angus.pojo"/>
Copy code
  1. Write classes under the specified package and add annotations
@Component("user")
// Equivalent to < bean id = "user" class = "currently annotated class" / > in the configuration file
public class User {
  public String name = "angus";
}
Copy code
  1. test
@Test
public void test(){
  ApplicationContext applicationContext =
    new ClassPathXmlApplicationContext("beans.xml");
  User user = (User) applicationContext.getBean("user");
  System.out.println(user.name);
}
Copy code

8.3 attribute injection

Using annotation injection properties

  1. You can directly add @ value("value") to the direct name without providing a set method
@Component("user")
// Equivalent to < bean id = "user" class = "currently annotated class" / > in the configuration file
public class User {
  @Value("angus")
  // Equivalent to < property name = "name" value = "Angus" / > in the configuration file
  public String name;
}
Copy code
  1. If a set method is provided, @ value("value") is added to the set method;
@Component("user")
public class User {
  public String name;
  @Value("angus")
  public void setName(String name) {
    this.name = name;
 }
}
Copy code

8.4 derived notes

These annotations replace the configuration steps in the configuration file! More convenient and fast!
@Component three derived annotations
For better layering, Spring can use the other three annotations with the same functions. At present, which function is used is the same.

  • @Controller: web layer
  • @Service: service layer
  • @Repository: dao layer

Writing these annotations is equivalent to giving this class to the Spring management assembly!

8.5 automatic assembly notes

The automatic assembly of Bean has been talked about, which can be reviewed!

8.6 scope

@scope

  • Singleton: by default, Spring creates this object in singleton mode. Close the factory and all objects will be destroyed.
  • prototype: multi instance mode. Close the factory and all objects will not be destroyed. The internal garbage collection mechanism will recycle
@Controller("user")
@Scope("prototype")
public class User {
  @Value("angus")
  public String name;
}
Copy code

8.7 summary

XML and annotation comparison

  • XML can be applied to any scenario, with clear structure and convenient maintenance
  • Annotations are not self provided classes and cannot be used. Development is simple and convenient

xml and annotation integrated development: Recommended Best Practices

  • xml management Bean
  • Annotation complete attribute injection
  • In the process of use, there is no need to scan. The scanning is for the annotation on the class

effect:

  • Make annotation driven registration to make annotations effective
  • It is used to activate the annotations on the bean s that have been registered in the spring container, that is, to register with spring
  • If you do not scan the package, you need to manually configure the bean
  • If it is driven without annotation, the injected value is null!

8.8. Configuration based on Java classes

JavaConfig was originally a sub project of Spring. It provides Bean definition information through Java classes. In the version of Spring 4, JavaConfig has officially become the core function of Spring 4.
Test:

  1. Write an entity class, Dog
    @Component  //Mark this class as a component of Spring and put it in the container!
    public class Dog {
      public String name = "dog";
    }
Copy code
  1. Create a new config configuration package and write a MyConfig configuration class
@Configuration  //Represents that this is a configuration class
public class MyConfig {
  @Bean //Register a bean through the method. The return value here is the bean type, and the method name is the bean id!
  public Dog dog(){
    return new Dog();
 }
}
Copy code
  1. test
@Test
public void test2(){
  ApplicationContext applicationContext =
      new AnnotationConfigApplicationContext(MyConfig.class);
  Dog dog = (Dog) applicationContext.getBean("dog");
  System.out.println(dog.name);
}
Copy code
  1. Output results successfully!

How do I import other configurations?

  1. Let's write another configuration class!
@Configuration  //Represents that this is a configuration class
public class MyConfig2 {
}
Copy code
  1. In the previous configuration class, we choose to import this configuration class
@Configuration
@Import(MyConfig2.class)  //Import and merge other configuration classes, similar to the inculde label in the configuration file
public class MyConfig {
  @Bean
  public Dog dog(){
    return new Dog();
 }
}
Copy code

We will see a lot about the configuration of this Java class in SpringBoot and SpringCloud later. We need to know the role of these annotations!

9. Agent mode

Why learn the agent mode? Because the underlying mechanism of AOP is dynamic agent!

9.1 static agent

Static agent role analysis

  • Abstract role: generally implemented using interfaces or abstract classes
  • Real role: the role represented
  • Agent role: agent real role; After representing a real role, you usually do some ancillary operations
  • Customer: use the agent role to perform some operations

The code implements rent Java is an abstract role

//Abstract role: rent a house
public interface Rent {
  public void rent();
}
Copy code

Host.java is the real role

//Real role: landlord, the landlord wants to rent the house
public class Host implements Rent{
  public void rent() {
    System.out.println("House rental");
 }
}
Copy code

Proxy.java is the proxy role

//Agent role: Intermediary
public class Proxy implements Rent {
  private Host host;
  public Proxy() { }
  public Proxy(Host host) {
    this.host = host;
 }
  //Rent a house
  public void rent(){
    seeHouse();
    host.rent();
    fare();
 }
  //House viewing
  public void seeHouse(){
    System.out.println("Show the tenant");
 }
  //Intermediary fee
  public void fare(){
    System.out.println("Intermediary fee");
 }
}
Copy code

Client . java is the customer

//Customers, general customers will find agents!
public class Client {
  public static void main(String[] args) {
    //The landlord wants to rent a house
    Host host = new Host();
    //The intermediary helps the landlord
    Proxy proxy = new Proxy(host);
    //You go to the agency!
    proxy.rent();
 }
}
Copy code

Analysis: in this process, you are in direct contact with an intermediary, just like in real life. You can't see the landlord, but you still rent the landlord's house through an agent. This is the so-called agent model. The program comes from life, so people who learn programming can generally look at what happens in life more abstractly.

9.2 benefits of static agent

  • It can make our real role more pure Stop paying attention to some public things
  • The public business is completed by the agent, which realizes the division of business
  • When the public business expands, it becomes more centralized and convenient

Disadvantages:

  • With more classes and more proxy classes, the workload becomes larger Reduced development efficiency

We want the benefits of static agent, but we don't want the disadvantages of static agent, so we have dynamic agent!

9.3 re understanding of static agent

After the students' practice, let's give another example to consolidate everyone's learning! Exercise steps:

  1. Create an abstract role, such as the user business we usually do, which is abstracted to add, delete, modify and check!
//Abstract role: add, delete, modify and query business
public interface UserService {
  void add();
  void delete();
  void update();
  void query();
}
Copy code
  1. We need a real object to complete these operations
//Real object, the person who completes the operation of addition, deletion, modification and query
public class UserServiceImpl implements UserService {
  public void add() {
    System.out.println("Added a user");
 }
  public void delete() {
    System.out.println("A user was deleted");
 }
  public void update() {
    System.out.println("A user has been updated");
 }
  public void query() {
    System.out.println("A user was queried");
 }
}
Copy code
  1. The demand is coming. Now we need to add a log function. How to implement it!
  • Idea 1: add code on the implementation class [trouble!]
  • Idea 2: using an agent to do this, you can realize this function without changing the original business!
  1. Set up a proxy class to handle logs! delegable role
//Agent role, in which the implementation of log is added
public class UserServiceProxy implements UserService {
  private UserServiceImpl userService;
  public void setUserService(UserServiceImpl userService) {
    this.userService = userService;
 }
  public void add() {
    log("add");
    userService.add();
 }
  public void delete() {
    log("delete");
    userService.delete();
 }
  public void update() {
    log("update");
    userService.update();
 }
   public void query() {
    log("query");
    userService.query();
 }
  public void log(String msg){
    System.out.println("Yes"+msg+"method");
 }
}
Copy code
  1. Test access class:
public class Client {
  public static void main(String[] args) {
    //Real business
    UserServiceImpl userService = new UserServiceImpl();
    //proxy class
    UserServiceProxy proxy = new UserServiceProxy();
    //Use the agent class to realize the log function!
    proxy.setUserService(userService);
    proxy.add();
 }
}
Copy code

OK, by now, there should be no problem with the agent mode. The key point is that you need to understand the idea; We have enhanced the original functions without changing the original code, which is the core idea of AOP [talk about AOP: vertical development, horizontal development]

9.4 dynamic agent

  • The role of dynamic agent is the same as that of static agent
  • The proxy class of dynamic proxy is generated dynamically The proxy class of static proxy is written in advance
  • Dynamic agents are divided into two categories: one is interface based dynamic agents, and the other is class based dynamic agents
    • Dynamic agent based on interface -- JDK dynamic agent
    • Class based dynamic proxy -- cglib
    • Now Java sist is used to generate dynamic proxy Baidu javasist
    • We use the native code of JDK here. The rest is the same!

The dynamic Proxy of JDK needs to understand two core classes: InvocationHandler and Proxy. Open the JDK help document to see [InvocationHandler: call handler]

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

[Proxy: Proxy]

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

The code implements the abstract role and real role as before! Rent.java is an abstract role

//Abstract role: rent a house
public interface Rent {
  public void rent();
}
Copy code

Host.java is the real role

//Real role: landlord, the landlord wants to rent the house
public class Host implements Rent{
  public void rent() {
    System.out.println("House rental");
 }
}
Copy code

ProxyInvocationHandler. java is the proxy role

public class ProxyInvocationHandler implements InvocationHandler {
  private Rent rent;
  public void setRent(Rent rent) {
    this.rent = rent;
     }
  //Generate an agent class, focusing on the second parameter to obtain the abstract role to be represented! It used to be a role, but now it can act as an agent
 Class role
  public Object getProxy(){
    return Proxy.newProxyInstance(this.getClass().getClassLoader(),
        rent.getClass().getInterfaces(),this);
 }
  // Proxy: proxy class method: the method object of the calling handler of the proxy class
  // Process method calls on proxy instances and return results
  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws
Throwable {
    seeHouse();
    //Core: essence is realized by reflection!
    Object result = method.invoke(rent, args);
    fare();
    return result;
 }
  //House viewing
  public void seeHouse(){
    System.out.println("Show the tenant");
 }
  //Intermediary fee
  public void fare(){
    System.out.println("Intermediary fee");
 }
}
Copy code

Client.java

//tenant
public class Client {
  public static void main(String[] args) {
    //Real role
    Host host = new Host();
    //Call handler for proxy instance
    ProxyInvocationHandler pih = new ProxyInvocationHandler();
    pih.setRent(host); //Put the real character in!
    Rent proxy = (Rent)pih.getProxy(); //Dynamically generate the corresponding proxy class!
    proxy.rent();
 }
}
Copy code

Core: a dynamic agent generally represents a certain type of business. A dynamic agent can represent multiple classes, and the agent is the interface!

9.5 deepening understanding

Let's use dynamic proxy to implement UserService written later! We can also write a general dynamic proxy implementation class! All proxy objects can be set to Object!

public class ProxyInvocationHandler implements InvocationHandler {
  private Object target;
  public void setTarget(Object target) {
    this.target = target;
 }
  //Generate proxy class
  public Object getProxy(){
    return Proxy.newProxyInstance(this.getClass().getClassLoader(),
        target.getClass().getInterfaces(),this);
 }
  // Proxy: proxy class
  // Method: the method object of the calling handler of the proxy class
  public Object invoke(Object proxy, Method method, Object[] args) throws
Throwable {
    log(method.getName());
    Object result = method.invoke(target, args);
    return result;
 }
  public void log(String methodName){
    System.out.println("Yes"+methodName+"method");
 }
}
Copy code

Test!

public class Test {
  public static void main(String[] args) {
    //Real object
    UserServiceImpl userService = new UserServiceImpl();
    //Call handler for proxy object
    ProxyInvocationHandler pih = new ProxyInvocationHandler();
    pih.setTarget(userService); //Sets the object to proxy
    UserService proxy = (UserService)pih.getProxy(); //Dynamically generate proxy class!
    proxy.delete();
 }
}
Copy code

[test, add, delete, modify, query and view the results]

9.6 benefits of dynamic agent

It has all the static agents. It also has all the static agents that don't have!

  • It can make our real role more pure Stop paying attention to some public things
  • Public business is done by agents The division of business is realized,
  • When the public business expands, it becomes more centralized and convenient
  • A dynamic agent, generally acting for a certain kind of business
  • A dynamic proxy can proxy multiple classes, and the proxy is the interface!

10,AOP

10.1 what is AOP

AOP (Aspect Oriented Programming) means: Aspect Oriented Programming, which realizes 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 be used for all parts of business logic It can reduce the coupling between various parts of business logic, improve the reusability of programs, and improve the efficiency of development.

10.2 role of AOP in Spring

Provide declarative transactions; Allows you to customize the cut plane

  • Crosscutting concerns: methods or functions that span multiple modules of an application. That is, it has nothing to do with our business logic, but we need
  • The focus is crosscutting concerns. Such as logging, security, caching, transactions, etc
  • ASPECT: a special object whose crosscutting concerns are modularized. That is, it is a class.
  • Advice: the work that must be done in the aspect. That is, it is a method in the class.
  • Target: the notified object.
  • Proxy: an object created after notification is applied to the target object.
  • PointCut: the definition of the "place" where the aspect notification is executed.
  • Join point: the execution point that matches the pointcut.

In spring AOP, crosscutting logic is defined through Advice. Spring supports five types of Advice:

That is, Aop adds new functions without changing the original code.

10.3 using Spring to implement Aop

[key] to use AOP weaving, you need to import a dependency package!

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

The first way

Through the Spring API implementation, we first write our business interface and implementation class

public interface UserService {
  public void add();
  public void delete();
  public void update();
  public void search();
}
Copy code
public class UserServiceImpl implements UserService{
  @Override
  public void add() {
    System.out.println("Add user");
 }
  @Override
  public void delete() {
    System.out.println("delete user");
 }
  @Override
  public void update() {
    System.out.println("Update user");
 }
  @Override
  public void search() {
    System.out.println("Query user");
 }
}
Copy code

Then write our enhancement class. We write two, one pre enhancement and one post enhancement

public class Log implements MethodBeforeAdvice {
  //Method: the method of the target object to execute
  //objects: parameters of the called method
  //Object: target object
  @Override
  public void before(Method method, Object[] objects, Object o) throws
Throwable {
    System.out.println( o.getClass().getName() + "of" + method.getName()
+ "Method was executed");
 }
}
Copy code
public class AfterLog implements AfterReturningAdvice {
  //returnValue return value
  //Method called method
  //args parameter of the object of the called method
  //Target the called target object
  @Override
  public void afterReturning(Object returnValue, Method method, Object[]
args, Object target) throws Throwable {
    System.out.println("Yes" + target.getClass().getName()
    +"of"+method.getName()+"method,"
    +"Return value:"+returnValue);
 }
}
Copy code

Finally, register in the spring file and implement aop cut in implementation. Pay attention to import constraints

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:aop="http://www.springframework.org/schema/aop"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd">
  <!--register bean-->
  <bean id="userService" class="com.kuang.service.UserServiceImpl"/>
  <bean id="log" class="com.kuang.log.Log"/>
  <bean id="afterLog" class="com.kuang.log.AfterLog"/>
  <!--aop Configuration of-->
  <aop:config>
    <!--breakthrough point expression:The expression matches the method to execute-->
    <aop:pointcut id="pointcut" expression="execution(*
com.kuang.service.UserServiceImpl.*(..))"/>
    <!--Perform wrap; advice-ref Execution method . pointcut-ref breakthrough point-->
    <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
    <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
  </aop:config>
</beans>
Copy code

test

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

The importance of Aop: very important. We must understand the ideas, mainly the understanding of ideas
Spring's Aop combines public business (logging, security, etc.) with domain business. When implementing domain business, public business will be added Realize the reuse of public business The domain business is more pure. The program ape focuses on the domain business, and its essence is dynamic agent

The second way

Custom classes to implement Aop
The target business class remains the same as userServiceImpl
Step 1: write our own cut in class

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

To configure in spring

<!--The second way is to customize the implementation-->
<!--register bean-->
<bean id="diy" class="com.kuang.config.DiyPointcut"/>
<!--aop Configuration of-->
<aop:config>
  <!--The second way: use AOP Label Implementation of-->
  <aop:aspect ref="diy">
    <aop:pointcut id="diyPonitcut" expression="execution(*
com.kuang.service.UserServiceImpl.*(..))"/>
    <aop:before pointcut-ref="diyPonitcut" method="before"/>
    <aop:after pointcut-ref="diyPonitcut" method="after"/>
  </aop:aspect>
</aop:config>
Copy code

Test:

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

The third way

Implementation using annotations
Step 1: write an enhanced class for annotation implementation

package com.angus.config;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class AnnotationPointcut {
  @Before("execution(* com.angus.service.UserServiceImpl.*(..))")
  public void before(){
    System.out.println("---------Before method execution---------");
 }
  @After("execution(* com.angus.service.UserServiceImpl.*(..))")
  public void after(){
    System.out.println("---------After method execution---------");
 }
  @Around("execution(* com.angus.service.UserServiceImpl.*(..))")
  public void around(ProceedingJoinPoint jp) throws Throwable {
    System.out.println("Surround front");
    System.out.println("autograph:"+jp.getSignature());
    //Execute target method
    Object proceed = jp.proceed();
    System.out.println("After surround");
    System.out.println(proceed);
 }
}
Copy code

Step 2: register the bean in the Spring configuration file and add the configuration supporting annotation

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

AOP: AspectJ AutoProxy: description

adopt aop Namespace<aop:aspectj-autoproxy />Declaration is automatically spring Which configurations are in the container@aspectJ section
 of bean Create a proxy and weave in the cut. of course, spring It is still used internally AnnotationAwareAspectJAutoProxyCreator The creation of automatic agent has been carried out, but the details of the specific implementation have been
<aop:aspectj-autoproxy />Hidden.

<aop:aspectj-autoproxy />There is one proxy-target-class Property, default to false,Indicates use jdk dynamic
 Agent weaving enhancement when configured as<aop:aspectj-autoproxy  poxy-target-class="true"/>When, it means to use
CGLib Dynamic agent technology weaving enhancement. But even if proxy-target-class Set to false,If the target class does not declare
 Mouth, then spring Will be used automatically CGLib Dynamic proxy.
Copy code

11. Integrate Mybatis

Steps:

  1. Import related jar packages
    1. junit
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
    </dependency>
    Copy code
    1. mybatis
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.2</version>
    </dependency>
    Copy code
    1. mysql-connector-java
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.47</version>
    </dependency>
    Copy code
    1. spring related
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.1.10.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>5.1.10.RELEASE</version>
    </dependency>
    Copy code
    1. aspectJ AOP Weaver
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.9.4</version>
    </dependency>
    Copy code
    1. Mybatis spring integration package [key]
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>2.0.2</version>
    </dependency>
    Copy code
    1. Configure Maven static resource filtering problem!
    <build>
      <resources>
        <resource>
          <directory>src/main/java</directory>
          <includes>
            <include>**/*.properties</include>
            <include>**/*.xml</include>
          </includes>
          <filtering>true</filtering>
        </resource>
      </resources>
    </build>
    Copy code
  2. Write configuration file
  3. code implementation

Recall MyBatis

Writing pojo entity classes

package com.kuang.pojo;
public class User {
  private int id;  //id
  private String name;  //full name
  private String pwd;  //password
}
Copy code

Configuration file for implementing mybatis

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
    PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
  <typeAliases>
    <package name="com.kuang.pojo"/>
  </typeAliases>
    <environments default="development">
    <environment id="development">
      <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
        <property name="driver" value="com.mysql.jdbc.Driver"/>
        <property name="url"
value="jdbc:mysql://localhost:3306/mybatis?
useSSL=true&amp;useUnicode=true&amp;characterEncoding=utf8"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
      </dataSource>
    </environment>
  </environments>
  <mappers>
    <package name="com.kuang.dao"/>
  </mappers>
</configuration>
Copy code

Written by UserDao interface

public interface UserMapper {
  public List<User> selectUser();
}
Copy code

Mapper mapping file corresponding to interface

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.kuang.dao.UserMapper">
  <select id="selectUser" resultType="User">
  select * from user
  </select>
</mapper>
Copy code

Test class

@Test
public void selectUser() throws IOException {
  String resource = "mybatis-config.xml";
  InputStream inputStream = Resources.getResourceAsStream(resource);
  SqlSessionFactory sqlSessionFactory = new
SqlSessionFactoryBuilder().build(inputStream);
  SqlSession sqlSession = sqlSessionFactory.openSession();
  UserMapper mapper = sqlSession.getMapper(UserMapper.class);
  List<User> userList = mapper.selectUser();
  for (User user: userList){
    System.out.println(user);
 }
  sqlSession.close();
}
Copy code

Mybatis spring learning

Before introducing Spring, you need to understand some important classes in the mybatis Spring package; www.mybatis.org/spring/zh/i...

What is mybatis spring?
MyBatis Spring will help you seamlessly integrate MyBatis code into Spring.
Knowledge base before you start using MyBatis Spring, you need to be familiar with the two frameworks Spring and MyBatis and their terms. This is important.
Mybatis spring requires the following versions:

If you use Maven as a build tool, you only need to use it in POM Add the following code to XML:

<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis-spring</artifactId>
  <version>2.0.2</version>
</dependency>
Copy code

To use MyBatis with Spring, you need to define at least two things in the Spring application context: a SqlSessionFactory and at least one data mapper class. In MyBatis Spring, SqlSessionFactory bean can be used to create SqlSessionFactory. To configure this factory bean, you only need to put the following code in the XML configuration file of Spring:

<bean id="sqlSessionFactory"
class="org.mybatis.spring.SqlSessionFactoryBean">
 <property name="dataSource" ref="dataSource" />
</bean>
Copy code

Note: SqlSessionFactory requires a DataSource (data source). This can be any DataSource. You only need to configure it as other Spring database connections. In the basic MyBatis usage, SqlSessionFactory is created through SqlSessionFactoryBuilder. In MyBatis Spring, SqlSessionFactoryBean is used.

In MyBatis, you can use SqlSessionFactory to create sqlsessions. Once you get a session, you can use it to execute mapped statements, commit or rollback connections, and finally close the session when it is no longer needed.
SqlSessionFactory has a unique required property: DataSource for JDBC. This can be any DataSource object, and its configuration method is the same as that of other Spring database connections.

A common attribute is configLocation, which is used to specify the XML configuration file path of MyBatis. It is very useful when you need to modify the basic configuration of MyBatis. Generally, the basic configuration refers to < Settings > or < typealiases > elements. It should be noted that this configuration file does not need to be a complete MyBatis configuration. Specifically, any Environment configuration (< environments >), data source (< datasource >) and MyBatis transaction manager (< transactionmanager >) will be ignored. SqlSessionFactoryBean will create its own MyBatis Environment configuration (Environment) and set the value of custom Environment as required.

SqlSessionTemplate is the core of mybatis spring. As an implementation of SqlSession, this means that it can be used to seamlessly replace the SqlSession already in use in your code.

Templates can participate in Spring's transaction management, and because they are thread safe, they can be used by multiple mapper classes. You should always use SqlSessionTemplate to replace the default DefaultSqlSession implementation of MyBatis. Mixing different classes in the same application may cause data consistency problems. You can use SqlSessionFactory as a parameter of the construction method to create a SqlSessionTemplate object.

<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
 <constructor-arg index="0" ref="sqlSessionFactory" />
</bean>
Copy code

Now, this bean can be directly injected into your DAO bean. You need to add a SqlSession attribute to your bean, as follows:

public class UserDaoImpl implements UserDao {
 private SqlSession sqlSession;
 public void setSqlSession(SqlSession sqlSession) {
  this.sqlSession = sqlSession;
}
 public User getUser(String userId) {
  return sqlSession.getMapper...;
}
}
Copy code

Inject SqlSessionTemplate as follows:

<bean id="userDao" class="org.mybatis.spring.sample.dao.UserDaoImpl">
 <property name="sqlSession" ref="sqlSession" />
</bean>
Copy code

Integration implementation I

  1. Introduce the Spring configuration file beans xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd">
Copy code
  1. Configure the data source to replace the data source of mybaits
<!--Configure data sources: there are many data sources. You can use third-party or Spring of-->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
  <property name="url" value="jdbc:mysql://localhost:3306/mybatis?
useSSL=true&amp;useUnicode=true&amp;characterEncoding=utf8"/>
  <property name="username" value="root"/>
  <property name="password" value="123456"/>
</bean>
Copy code
  1. Configure SqlSessionFactory and associate MyBatis
<!--to configure SqlSessionFactory-->
<bean id="sqlSessionFactory"
class="org.mybatis.spring.SqlSessionFactoryBean">
  <property name="dataSource" ref="dataSource"/>
  <!--relation Mybatis-->
  <property name="configLocation" value="classpath:mybatis-
config.xml"/>
  <property name="mapperLocations"
value="classpath:com/kuang/dao/*.xml"/>
</bean>
Copy code
  1. Register sqlSessionTemplate and associate sqlSessionFactory;
<!--register sqlSessionTemplate , relation sqlSessionFactory-->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
  <!--Using constructor injection-->
  <constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>
Copy code
  1. Add the implementation class of Dao interface; Privatize sqlSessionTemplate
public class UserDaoImpl implements UserMapper {
  //sqlSession does not need to be created by ourselves, but managed by Spring
  private SqlSessionTemplate sqlSession;
  public void setSqlSession(SqlSessionTemplate sqlSession) {
    this.sqlSession = sqlSession;
 }
  public List<User> selectUser() {
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    return mapper.selectUser();
 }
}
Copy code
  1. Register bean implementation
<bean id="userDao" class="com.kuang.dao.UserDaoImpl">
  <property name="sqlSession" ref="sqlSession"/>
</bean>
Copy code
  1. test
  @Test
  public void test2(){
    ApplicationContext context = new
ClassPathXmlApplicationContext("beans.xml");
    UserMapper mapper = (UserMapper) context.getBean("userDao");
    List<User> user = mapper.selectUser();
    System.out.println(user);
 }
Copy code

The result is output successfully! Now the status of our Mybatis configuration file! Discovery can be integrated by Spring!

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
    PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
  <typeAliases>
    <package name="com.kuang.pojo"/>
  </typeAliases>
</configuration>
Copy code

Integration implementation II

mybatis-spring1. Only those above version 2.3 have this Screenshot of official document: dao inherits the Support class, obtains it directly using getSqlSession(), and then injects it directly into SqlSessionFactory Compared with mode 1, there is no need to manage SqlSessionTemplate, and the Support for transactions is more friendly Traceable source code view

Test:

  1. Modify the UserDaoImpl we wrote above
public class UserDaoImpl extends SqlSessionDaoSupport implements
UserMapper {
  public List<User> selectUser() {
    UserMapper mapper = getSqlSession().getMapper(UserMapper.class);
    return mapper.selectUser();
 }
}
Copy code
  1. Modify bean configuration
<bean id="userDao" class="com.kuang.dao.UserDaoImpl">
  <property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
Copy code
  1. test
@Test
public void test2(){
  ApplicationContext context = new
ClassPathXmlApplicationContext("beans.xml");
  UserMapper mapper = (UserMapper) context.getBean("userDao");
  List<User> user = mapper.selectUser();
  System.out.println(user);
}
Copy code

Conclusion: after integration into spring, we can completely eliminate the configuration file of mybatis. In addition to these methods, we can also use annotations to realize the integration. This will be tested when we learn about SpringBoot later!

12. Declarative transaction

12.1 review

  • Transaction is very important in the project development process. It involves the problem of data consistency, which should not be careless!
  • Transaction management is a necessary technology in enterprise application development to ensure data integrity and consistency.

Transaction is to treat a series of actions as an independent unit of work, which are either completed or ineffective.

Transaction four attribute ACID

  1. atomicity
    • A transaction is an atomic operation, which consists of a series of actions. The atomicity of a transaction ensures that the actions either complete or fail to work at all
  2. consistency
    • Once all transaction actions are completed, the transaction is committed. Data and resources are in a consistent state that meets business rules
  3. isolation
    • Multiple transactions may process the same data at the same time, so each transaction should be isolated from other transactions to prevent data corruption
  4. Persistence
    • Once the transaction is completed, no matter what error occurs in the system, the result will not be affected. Typically, the result of a transaction is written to persistent storage

12.2 test

Copy the above code to a new project. In the previous case, we added two methods to the userDao interface, delete and add users;

//Add a user
int addUser(User user);
//Delete user by id
int deleteUser(int id);
Copy code

mapper file, we deliberately write delete wrong, test!

<insert id="addUser" parameterType="com.kuang.pojo.User">
insert into user (id,name,pwd) values (#{id},#{name},#{pwd})
</insert>
<delete id="deleteUser" parameterType="int">
deletes from user where id = #{id}
</delete>
Copy code

Write the implementation class of the interface. In the implementation class, we operate a wave

public class UserDaoImpl extends SqlSessionDaoSupport implements UserMapper
{
  //Add some operations
  public List<User> selectUser() {
    User user = new User(4,"Xiao Ming","123456");
    UserMapper mapper = getSqlSession().getMapper(UserMapper.class);
    mapper.addUser(user);
    mapper.deleteUser(4);
    return mapper.selectUser();
 }
  //newly added
  public int addUser(User user) {
    UserMapper mapper = getSqlSession().getMapper(UserMapper.class);
    return mapper.addUser(user);
 }
  //delete
  public int deleteUser(int id) {
    UserMapper mapper = getSqlSession().getMapper(UserMapper.class);
    return mapper.deleteUser(id);
 }
}
Copy code

test

@Test
public void test2(){
  ApplicationContext context = new
ClassPathXmlApplicationContext("beans.xml");
  UserMapper mapper = (UserMapper) context.getBean("userDao");
  List<User> user = mapper.selectUser();
  System.out.println(user);
}
Copy code

Error reporting: sql exception. delete is written incorrectly
Result: insertion succeeded!
No transaction management; We want them to succeed only when they succeed. If there is a failure, they will all fail. We should need affairs!
In the past, we all needed to manage affairs manually, which was very troublesome!
However, Spring provides us with transaction management, and we only need to configure it;

12.3 transaction management in Spring

Spring defines an abstraction layer on top of different transaction management APIs, so that developers can use spring's transaction management mechanism without understanding the underlying transaction management API. Spring supports programmatic transaction management and declarative transaction management.

Programming transaction management

  • Embed transaction management code into business methods to control transaction commit and rollback
  • Disadvantages: additional transaction management code must be included in each transaction operation business logic

Declarative transaction management

  • Generally, it works better than programmatic transactions.
  • The transaction management code is separated from the business method to realize the transaction management in a declarative way.
  • Transaction management is regarded as a crosscutting concern and modularized through aop method. Spring supports declarative transaction management through the Spring AOP framework

Using Spring to manage transactions, pay attention to the constraint import of header file: tx

xmlns:tx="http://www.springframework.org/schema/tx"
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
Copy code

Transaction manager

  • No matter which transaction management strategy (programmatic or declarative) Spring uses, the transaction manager is required.
  • Spring's core transaction management abstraction encapsulates a set of technology independent methods.

JDBC transaction

<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
</bean>
Copy code

After configuring the transaction manager, we need to configure the notification of transactions

<!--Configure transaction notifications-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
  <tx:attributes>
    <!--What methods are configured and what transactions are used,Configure propagation properties of transactions-->
    <tx:method name="add" propagation="REQUIRED"/>
    <tx:method name="delete" propagation="REQUIRED"/>
    <tx:method name="update" propagation="REQUIRED"/>
    <tx:method name="search*" propagation="REQUIRED"/>
    <tx:method name="get" read-only="true"/>
    <tx:method name="*" propagation="REQUIRED"/>
  </tx:attributes>
</tx:advice>
Copy code

spring transaction propagation feature: transaction propagation behavior is how transactions propagate among multiple transaction methods when they call each other. spring supports seven transaction propagation behaviors:

  • propagation_requierd: if there is no transaction at present, create a new transaction. If there is already a transaction, join it

This is the most common choice of transactions.

  • propagation_supports: supports the current transaction. If there is no current transaction, it will be executed in a non transaction method.
  • propagation_mandatory: use the current transaction. If there is no current transaction, an exception will be thrown.
  • propagation_required_new: create a new transaction. If there is a current transaction, suspend the current transaction.
  • propagation_not_supported: perform operations in a non transactional manner. If there is a transaction, suspend the current transaction.
  • propagation_never: execute the operation in a non transactional manner. If the current transaction exists, an exception will be thrown.
  • propagation_nested: if a transaction currently exists, it is executed within a nested transaction. If there are currently no transactions, execute and
  • propagation_required similar operations

The default transaction propagation behavior of Spring is PROPAGATION_REQUIRED, which is suitable for most situations.

Assuming that ServiveX#methodX() works in a transaction environment (that is, they are enhanced by Spring transactions), assuming that there is the following call chain in the program: service1 #method1 () - > service2 #method2 () - > service3 #method3 (), then the three methods of the three service classes work in the same transaction through the transaction propagation mechanism of Spring.

For example, the methods we just mentioned are called, so they will be placed in a group of transactions!

Configure the header file of aop import!

<!--to configure aop Weaving transaction-->
<aop:config>
  <aop:pointcut id="txPointcut" expression="execution(* com.kuang.dao.*.*
(..))"/>
  <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
</aop:config>
Copy code

Test, delete the data just inserted, and test again!

@Test
public void test2(){
  ApplicationContext context = new
ClassPathXmlApplicationContext("beans.xml");
  UserMapper mapper = (UserMapper) context.getBean("userDao");
  List<User> user = mapper.selectUser();
  System.out.println(user);
}
Copy code

Thinking?

Why do I need to configure transactions?

  • If it is not configured, we need to manually submit the control transaction;
  • Transaction is very important in the project development process. It involves the problem of data consistency, which should not be careless!


Author: angus_study
Link: https://juejin.cn/post/7041092696567447589

Topics: Java Spring Back-end