Spring IOC DI - Integrate MyBatis

Spring IOC directory

main content

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-TX2jinQt-1682532373362)(01-Spring IOC.assets/Spring-48.png)]

Introduction to Spring Framework

Advantages of the Spring framework (compared to the disadvantages of previous projects)

(1) Simply using the Mybatis framework, the business layer code is complex, and a large amount of code needs to be used to parse the mybatis.xml configuration file by itself. The pressure is given to the business layer code, as follows:

public class Test2 {
    
    
    public static void main(String[] args) throws IOException {
    
    
        //指定核心配置文件的路径:
        String resource = "mybatis.xml";
        //获取加载配置文件的输入流:
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //加载配置文件,创建工厂类
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //通过工厂类获取一个会话:
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //代理
        BookMapper mapper = sqlSession.getMapper(BookMapper.class);
        //Book book = mapper.selectOneBook("项目驱动零起点学Java", "马士兵、赵珊珊");
        Book b = new Book();
        b.setName("项目驱动零起点学Java");
        b.setAuthor("马士兵、赵珊珊");
        //Book book = mapper.selectOneBook2(b);
        Book book = mapper.selectOneBook3("项目驱动零起点学Java", b);

        System.out.println(book.getName());
        //关闭资源:
        sqlSession.close();
    }
}

After learning spring, the use of mybaits will be easier and the code for business layer processing will be simplified.

(2) The coupling between layers is too high. For example, in layered thinking, the controller layer calls the service layer, and the service layer calls the mapper layer (dao layer). When the controller layer calls objects in the service layer, it is necessary to build service layer objects. The positions of all new service layer objects need to be changed. After learning spring, you can't see the new object, and the object creation is done by spring, which is the ioc/di part we want to learn.

(3) The transaction processing method in mybatis is the same as that of traditional JDBC, and the transaction management is not convenient enough, so it can now be managed by Spring. It is the tx part we are going to learn.

(4) The current project is not scalable. For example, if we have written a good project deployment, we need to send the war package of the project to the server, but the war package is full of class files, there is no way to modify it, and you can’t do it if you want to expand a certain function. Learned After spring, you can expand on it without changing the original code, which is the aop part we want to learn.

(5) Spring can integrate various excellent frameworks. Spring is also called a framework framework, such as integrating springmvc and mybatis, which is our commonly used SSM framework. Many years ago: SSH framework.

To sum up: Spring is a full-featured stack framework with very complete functions.

Spring framework introduction

​ Spring Framework (Spring Framework), formerly known as interface21, was developed by Rod Johnson in 2002.

​

​ Spring is one of many open source java projects. Based on the layered javaEE application one-stop lightweight open source framework, the main core is the two major technologies of IOC/DI and AOP, which realizes the easy decoupling of the project during the development process. Improve project development efficiency. (We have already explained in the advantages of the last lesson)

​ The reason for Spring's initial fire is-the wheel theory.

History development

  • About 30,000 lines of code in 2002, interface21 appeared
  • In 2003, Rod Johnson and his friends developed Spring on the basis of interface21.
  • In March 2004, Spring 1.0 was released
  • In October 2006, Spring 2.0 was released
  • In November 2007, the name was changed to SpringSource, and Spring 2.5 was released at the same time.
  • In December 2009, Spring 3.0 was released. At the same time, Spring is divided into multiple jar packages from one jar package to truly achieve modularization.
  • In December 2013, Spring Framework 4.0 was released
  • In September 2017, Spring Framework 5.0 was released.
  • In November 2022, Spring Framework 6.0 will be released. (Milestone version, the beginning of the next decade)

At the time of document creation, the latest version of the Spring framework is 6.0.5.

spring official website: https://spring.io/

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-UvzHjN2x-1682532373364)(01-Spring IOC.assets/Spring-12.png)]

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-DEobc7fo-1682532373364)(01-Spring IOC.assets/Spring-13.png)]

Three elements of framework learning

Framework learning three elements: jar package, API, source code.

(1) jar package: you can search it in the Maven repository when using it.

Note: In December 2009, Spring 3.0 was released. At the same time, Spring is divided into multiple jar packages from one jar package to truly achieve modularization.

With the continuous development of the Spring framework, there are more and more jars corresponding to the modules contained in the Spring official compressed package. Learning Spring is actually learning the functions of all Spring modules separately.

If you want to download the official compressed package and view all jar packages, you can download it through the link below. In a Maven project, there is no need to download the following content separately:

https://repo.spring.io/libs-release-local/org/springframework/spring/ (download the official compressed package of spring)

(2)API:

Check it out at https://spring.io/:

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-V6PGxDNY-1682532373365)(01-Spring IOC.assets/Spring-14.png)]

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-UpWqKch3-1682532373366)(01-Spring IOC.assets/Spring-15.png)]

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-3VIcN06I-1682532373367)(01-Spring IOC.assets/Spring-16.png)]

(3) Source code:

Open source, you can download the source code yourself:

https://github.com/spring-projects/spring-framework/tags (download source code)

Introduction to Spring modules

​ Spring is a full-featured stack framework. Learning Spring is actually learning the functions of all Spring modules. Spring modules (components of Spring) are divided as follows:

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-vnhbTCCe-1682532373368)(.\01-Spring IOC.assets/Spring-01.png)]

​ Spring has about 20 modules in total, consisting of more than 1300 different files. These components are respectively integrated in the core container (Core Container), Aop (Aspect Oriented Programming) and device support (Instrmentation), data access and integration (Data Access/Integration), Web, message sending (Messaging), test module set middle.

  1. Core container: Spring-beans and Spring-core modules are the core modules of the Spring framework, including inversion of control (Inversion of Control, IoC) and dependency injection (Dependency Injection, DI). The core container provides the basic functions of the Spring framework. The main component of the core container is BeanFactory, the implementation of the factory pattern. The BeanFactory uses the idea of ​​Inversion of Control (IOC) to separate an application's configuration and dependency specification from the actual application code.

    Spring Context - Spring Context: A Spring Context is a configuration file that provides context information to the Spring framework. The Spring context includes enterprise services such as JNDI, EJB, email, internationalization, validation, and dispatch functionality.

    The Spring-Expression module is an extension module of the unified expression language (unified EL), which can query and manage running objects, and can also conveniently call object methods, operate arrays, collections, etc. Its syntax is similar to traditional EL, but provides additional features, most notably function calls and template functions for simple strings.

  2. Spring-AOP: Spring-aop is another core module of Spring. In Spring, it is based on the dynamic proxy technology of JVM, and then designs a series of Aop cross-cutting implementations, such as pre-notification, return notification, Exception notification, etc. Through its configuration management features, the Spring AOP module directly integrates aspect-oriented programming capabilities into the Spring framework. Therefore, any object managed by the Spring framework can be easily AOP-enabled.

  3. Spring Data Access (data access): consists of 5 modules: Spring-jdbc, Spring-tx, Spring-orm, Spring-jms and Spring-oxm.

    The Spring-jdbc module is the main implementation module of the JDBC abstract framework provided by Spring, which is used to simplify Spring JDBC.

    The Spring-tx module is a Spring JDBC transaction control implementation module. Using the Spring framework, it encapsulates the transaction very well, and through its Aop configuration, it can be flexibly configured at any layer.

    The Spring-Orm module is an ORM framework support module, which mainly integrates hibernate, Java Persistence API (JPA) and Java Data Objects (JDO) for resource management, data access object (DAO) implementation and transaction strategy.

    The Spring-Jms module (Java Messaging Service) is able to send and receive messages.

    The Spring-Oxm module mainly provides an abstraction layer to support OXM (OXM is the abbreviation of Object-to-XML-Mapping, which is an O/M-mapper that maps java objects into XML data, or maps XML data into java objects ), such as: JAXB, Castor, XMLBeans, JiBX and XStream etc.

  4. Web module: It consists of four modules: Spring-web, Spring-webmvc, Spring-websocket and Spring-webmvc-portlet. The Web context module is built on the application context module and provides a context for Web-based applications. The web module also simplifies handling multipart requests and binding request parameters to domain objects. (This part is to learn SpringMVC. It can be seen here that Springmvc is a framework included in spring.)

  5. Message sending: the Spring-messaging module.

    Spring-messaging is a new module added by Spring4. Its main responsibility is to integrate some basic messaging applications for the Spring framework.

  6. Unit test: the Spring-test module. The Spring-test module mainly provides support for unit testing.

Spring IoC/DI - Import

IoC/DI Concept Discrimination

【1】IoC/DI

IoC (Inversion of Control) Chinese name: Inversion of Control, also known as DI (dependency injection): dependency injection, two names belonging to the same thing. (Be sure to pay attention, it is one thing, not two things)

IoC/DI refers to a process: the right to create an object, or the position of control, is transferred from the JAVA code to the spring container, and the creation of the object is controlled by the spring container, which is inversion of control. When spring creates an object, it will read the configuration The information in the file, and then use reflection to create objects for us and store them in the container (actually a map collection). When we need an object, we can get the object through the id, and we don’t need to go to new ourselves.

In a word: Create objects and leave them to the container.

Due to the ambiguity of the concept of inversion of control, in 2004 the master Martin Fowler gave a new name: "Dependency Injection". Compared with LoC, "Dependency Injection" clearly describes that "the injected object depends on the loC container To configure dependent objects", Dl (English full name is Dependency Injection, Chinese translation is Dependency Injection) is an alias of loC. It can be simply understood that the container creates a dependent object and injects the dependent object into the place where the dependent object is needed (also called the injected object).

【2】Container

Spring container, where all managed objects are placed. Its essence is that there is a global Map object in the container object, and all managed objects are placed in the map object. The container in Spring refers to the ApplicationContext interface and sub-interfaces or implementation classes.

【3】bean

All managed objects in the container are called beans, if only one of the objects can be called a bean.

Benefits of Using IoC/DI

After Spring IoC/DI is used, it can manage related objects in the project, so that object management can be separated from business (decoupling). At the same time, the programmer does not manage the dependencies of the objects, and all the dependencies are handed over to the Spring container for management.

case:

Before using spring:

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-SvBbMNiF-1682532373368)(01-Spring IOC.assets/Spring-22.png)]

After using spring-IoC/DI:

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-pQkBHXlI-1682532373369)(01-Spring IOC.assets/Spring-23.png)]

If you change the implementation class in the future, you only need to modify the configuration file, and you don't need to operate in the java code.

It should be noted that we only change the implementation class, and will not change the interface. The interface is a specification, just like when the light is broken, we usually change the light bulb, and we will not dismantle the light.

Specific application scenarios of IoC/DI

The main function of IoC/DI is to manage the instantiation of objects and the dependencies between objects. In the project, the layer objects that need to be instantiated before, and the entry classes that need to instantiate the framework or toolkit can be handed over to the Spring container for management.

  • Layer object: PeopleMapper interface proxy object, PeopleDaoImpl, PeopleServiceImpl
  • Framework entry class: SqlSessionFactory, etc.

The corresponding common classes PeopleMapper and PeopleServiceImpl in the figure below can be handed over to the Spring container for management. Objects placed into containers can directly depend on each other. But Servlet can only be managed by Tomcat (created by Tomcat to help instantiate), so the Spring container cannot manage Servlet. But Servlet can fetch objects from Spring container.

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-cteWrl22-1682532373370)(01-Spring IOC.assets/Spring-24.png)]

Spring IoC/DI - code implementation

Environmental preparation

(1) idea version: IntelliJ IDEA 2022.3.1

(2) Maven version: 3.6+

Determine the Maven environment:

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-HzT4E4PZ-1682532373370)(01-Spring IOC.assets/Spring-17.png)]

(3) Spring6 requires JDK to be 17 or above:

Install JDK17:

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-vW86ZvkE-1682532373371)(01-Spring IOC.assets/Spring-18.png)]

Set jdk in idea:

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-NNKt75RN-1682532373372)(01-Spring IOC.assets/Spring-19.png)]

(4) spring version: 6.0.5

Spring framework environment construction

Realization case: Create a Person class and let Spring help us manage objects.

Create a Maven aggregate project

After using the aggregation project, future projects can be created in the aggregation project and exist in the form of modules.

Create a Maven aggregate project:

Because there is no need to write java code in the aggregation project, src can be deleted:

Create a new Maven project (module)

Aggregation project Spring6–”Right click—”New—”Module:

The Spring project does not need to depend on tomcat, so just build a normal java project:

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-psxT5Sfa-1682532373372)(01-Spring IOC.assets/Spring-25.png)]

After creation, it becomes as follows:

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-2w8OMsWZ-1682532373373)(01-Spring IOC.assets/Spring-26.png)]

Add spring dependencies in pom.xml

Add spring dependencies in pom.xml under the Spring6Demo01 module.

The most basic dependencies of a Spring project include:

  • spring-context. jar. The spring context depends on the following four jars.
  • spring-core.jar. Spring core jar package. It depends on spring-jcl.jar
  • spring-aop. jar. Basic support for aspect-oriented programming in Spring AOP.
  • spring-expression.jar. Spring's expression language support.
  • spring-beans. jar. The bean management of the Spring container is a very important package for creating objects.
  • spring-jcl. jar. The built-in log package, the Spring 4 version still uses common-logging.jar, but since Spring 5, Spring has encapsulated the log itself.

However, if you want to use the Spring framework in a Maven project, you only need to import spring-context in the project, and other jar packages can be imported according to the Maven dependency transitivity.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.msb</groupId>
        <artifactId>Spring6</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>Spring6Demo01</artifactId>
    <packaging>jar</packaging>

    <name>Spring6Demo01</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <!--添加spring-context依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>6.0.5</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

View project dependencies as:

Feel free to create a class: Create a Person class

package com.msb.pojo;

/**
 * @Author: zhaoss
 */
public class Person {
    
    
    // 属性
    private int age;
    private String name;
    private double height;

    public int getAge() {
    
    
        return age;
    }
    // 提供setter\getter方法
    public void setAge(int age) {
    
    
        this.age = age;
    }

    public String getName() {
    
    
        return name;
    }

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

    public double getHeight() {
    
    
        return height;
    }

    public void setHeight(double height) {
    
    
        this.height = height;
    }

    public Person() {
    
    
        System.out.println("空参构造器");
}

    public Person(int age, String name, double height) {
    
    
        System.out.println("有参构造器");
        this.age = age;
        this.name = name;
        this.height = height;
    }

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

Add Spring configuration file

Create a new resources directory under src\main\.

Create a new applicationContext.xml file in the src\main\resources directory, and copy the template content provided by the official website document to xml.

The file name is not mandatory. The name of the configuration file in the official example is applicationContext.xml, so we also call the Spring configuration file applicationContext.xml

Configure beans into xml, and incorporate corresponding beans into the Spring container for management

applicationContext.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">
    <!--
            id:bean对象的id,唯一标识。一般是Bean对象的名称的首字母小写
            class:bean对象的类路径
    -->
    <bean id="p" class="com.zss.pojo.Person"></bean>

</beans>

PS: The above document header and constraints can be pasted from the official document: https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-factory-metadata

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-9gxUK3f6-1682532373373)(01-Spring IOC.assets/Spring-28.png)]

Project structure:

Load the configuration file and get the instantiated object

import com.zss.pojo.Person;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    
    
    public static void main(String[] args) {
    
    
        // Spring通过加载配置文件,创建Spring容器。
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 从容器中取出叫做p的bean
        // 第二个参数设置取出Bean的类型。如果没有第二个参数,返回值类型为Object
        Person p = ac.getBean("p", Person.class);//这种方式不需要强转
        Person p2 = (Person)ac.getBean("p");//这种方式需要强转
        System.out.println(p == p2);//这个结果为true,证明从容器中获取的对象是同一个对象
        System.out.println(p);
        System.out.println(p2);
    }
}

You can verify it by yourself, comment out the rest of the code, leaving only ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); after this sentence is executed, the constructor without parameters will be called, and the side verification shows that after parsing the xml file, it will First put each bean into the container for us to use.

The result of the above code:

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-FlaNws8L-1682532373374)(01-Spring IOC.assets/Spring-30.png)]

Spring IoC/DI - container bean object instantiation simulation

I have understood the principle of IOC before:

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-TRX4kij2-1682532373374)(01-Spring IOC.assets/Spring-23.png)]

Without relying on spring, simulate the process of bean object instantiation by yourself.

Create a new Spring6Demo02 project (Maven-jar project)

Ideas:

(1) Define the xml file, which defines the bean tag, because each subsequent bean tag will be parsed into an object

(2) Parse the xml file (dom4j). When parsing, it will parse the bean tags in the xml file. Each bean tag is converted into a bean object. This object contains two attributes: id and class. This object is used to store beans id and class values.

(3) Because there may be multiple bean tags in the xml file, define a List collection to store bean objects.

(4) Traverse the List collection to get each bean object, and create the corresponding object through reflection through the class attribute of the bean object.

(5) After the object is created, put the id of the bean object and the object created by reflection into the map collection.

(6) Define a factory, and the steps (2)-(5) are completed in the constructor of the factory

(7) Define the method of obtaining objects in the factory, and obtain objects from the map collection through id.

Build entity classes Person and User classes

package com.msb.pojo;

/**
 * @Author: zhaoss
 */
public class Person {
    
    
    private int age;
    private String name;

    public int getAge() {
    
    
        return age;
    }

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

    public String getName() {
    
    
        return name;
    }

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

    public Person() {
    
    
        System.out.println("Person空构造器");
    }

    public Person(int age, String name) {
    
    
        System.out.println("Person有参构造器");
        this.age = age;
        this.name = name;
    }

    @Override
    public String toString() {
    
    
        return "Person{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
    
    public void eat(){
    
    
        System.out.println("Person.eat");
    }
}

package com.msb.pojo;

/**
 * @Author: zhaoss
 */
public class User {
    
    
    private String uname;
    private String pwd;

    public String getUname() {
    
    
        return uname;
    }

    public void setUname(String uname) {
    
    
        this.uname = uname;
    }

    public String getPwd() {
    
    
        return pwd;
    }

    public void setPwd(String pwd) {
    
    
        this.pwd = pwd;
    }

    public User() {
    
    
        System.out.println("User空构造器");
    }

    public User(String uname, String pwd) {
    
    
        System.out.println("User有参构造器");
        this.uname = uname;
        this.pwd = pwd;
    }

    @Override
    public String toString() {
    
    
        return "User{" +
                "uname='" + uname + '\'' +
                ", pwd='" + pwd + '\'' +
                '}';
    }
    
    public void sleep(){
    
    
        System.out.println("User.sleep");
    }
}

Prepare custom configuration files

applicationContext.xml:

<?xml version="1.0" encoding="utf-8" ?>
<beans>
    <bean id="person" class="com.msb.pojo.Person"></bean>
    <bean id="user" class="com.msb.pojo.User"></bean>
</beans>

At this point the directory structure is:

Define the Bean property object

package com.msb.spring;


/**
 * @Author: zhaoss
 * bean对象
 *      用来接收配置文件中bean标签的id与class属性值
 */
public class MyBean {
    
    

    private String id; //bean标签的id的属性值
    private String clazz; //bean标签的class的属性值

    public MyBean() {
    
    
    }

    public MyBean(String id, String clazz) {
    
    
        this.id = id;
        this.clazz = clazz;
    }

    public String getId() {
    
    
        return id;
    }

    public void setId(String id) {
    
    
        this.id = id;
    }

    public String getClazz() {
    
    
        return clazz;
    }

    public void setClazz(String clazz) {
    
    
        this.clazz = clazz;
    }
}

Add dom4j coordinate dependency

<!-- dom4j -->
<dependency>
    <groupId>dom4j</groupId>
    <artifactId>dom4j</artifactId>
    <version>1.6.1</version>
</dependency>
<!-- XPath :XPath即为XML路径语言(XML Path Language),它是一种用来确定XML文档中某部分位置的语言。
Jaxen是Java的通用XPath引擎。-->
<dependency>
    <groupId>jaxen</groupId>
    <artifactId>jaxen</artifactId>
    <version>1.1.6</version>
</dependency>

Define the Bean Factory Interface

package com.msb.spring;

/**
 * Bean 工厂接口定义
 */
public interface MyFactory {
    
    
    // 通过id值获取对象
    public Object getBean(String id);
}

Define the implementation class of the Bean interface

package com.msb.spring;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 模拟Spring的实现
 *  1、通过构造器得到相关配置文件
 *  2、通过dom4j解析xml文件,得到List   存放id和class
 *  3、通过反射实例化得到对象   Class.forName(类的全路径).newInstance(); 通过Map<id,Class>存储
 *  4、得到指定的实例化对象
 */
public class MyClassPathXmlApplicationContext implements BeanFactory {
    
    

    private Map beans = new HashMap(); // 实例化后的对象放入map
    private List<MyBean> myBeans; // 存放已读取bean 配置信息

    /* 1、通过构造器得到相关配置文件 */
    public MyClassPathXmlApplicationContext(String fileName) {
    
    

        /* 2、通过dom4j解析xml文件,得到List (存放id和class) */
        this.parseXml(fileName);

        /* 3、通过反射实例化得到对象Class.forName(类路径).newInstance();  通过Map存储 */
        this.instanceBean();

    }

    /**
     * 通过dom4j解析xml文件,得到List   存放id和class
     *  1、获取解析器
     *  2、得到配置文件的URL
     *  3、通过解析器解析xml文件(applicationContext.xml)
     *  4、通过xpath语法,获取beans标签下的所有bean标签
     *  5、通过指定语法解析文档对象,返回集合
     *  6、判断集合是否为空,遍历集合
     *  7、获取标签元素中的属性
     *  8、得到Bean对象,将Bean对象设置到集合中
     * @param fileName
     */
    private void parseXml(String fileName) {
    
    
        // 1、获取解析器
        SAXReader reader = new SAXReader();
        // 2、得到配置文件的URL
        URL url = this.getClass().getClassLoader().getResource(fileName);
        try {
    
    
            // 3、通过解析器解析xml文件(applicationContext.xml)
            Document document = reader.read(url);
            // 4、通过xpath语法,获取beans标签下的所有bean标签
            XPath xPath = document.createXPath("beans/bean");
            // 通过指定语法解析文档对象,返回集合
            List<Element> list = xPath.selectNodes(document);
            // 每个文档对象Element可以看一下长什么样:
            for(Element el : list) {
    
    
                System.out.println(el + "--------");
            }
            // 判断集合是否为空,遍历集合 :把文档对象转为 MyBean对象
            if (list != null && list.size() > 0) {
    
    
                myBeans = new ArrayList<>();
                for(Element el : list) {
    
    
                    // 获取标签元素中的属性
                    String id = el.attributeValue("id"); // id 属性值
                    String clazz = el.attributeValue("class"); // class 属性值
                    System.out.println(el.attributeValue("id"));
                    System.out.println(el.attributeValue("class"));
                    // 得到Bean对象
                    MyBean bean = new MyBean(id, clazz);
                    // 将Bean对象设置到集合中
                    myBeans.add(bean);
                }
            }
        } catch (DocumentException e) {
    
    
            e.printStackTrace();
        }
    }

    /**
     * 通过反射实例化得到对象  
     * 	Class.forName(类的全路径).newInstance();  
     *	通过Map<id,Class>存储
     */
    private void instanceBean() {
    
    
        // 判断bean集合是否为空,不为空遍历得到对应Bean对象
        if (myBeans != null && myBeans.size() > 0) {
    
    
            for (MyBean bean : myBeans){
    
                                          
                try {
    
    
                    // 通过类的全路径实例化对象
                    Object object = Class.forName(bean.getClazz()).newInstance();
                    // 将id与实例化对象设置到map对象中
                    beans.put(bean.getId(), object);
                } catch (Exception e) {
    
    
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 通过key获取map中的指定value
     * @param id
     * @return
     */
    @Override
    public Object getBean(String id) {
    
    
        Object object = beans.get(id);
        return object;
    }
}

At this point the directory structure is:

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-84iRMQJH-1682532373375)(01-Spring IOC.assets/Spring-32.png)]

Test custom IOC container

Test whether the instantiated Bean object can be obtained

package com.msb;

import com.msb.pojo.Person;
import com.msb.pojo.User;
import com.msb.springdiy.MyClassPathXmlApplicationContext;
import com.msb.springdiy.MyFactory;

/**
 * Hello world!
 *
 */
public class App 
{
    
    
    public static void main( String[] args )
    {
    
    
       // 构建工厂对象:
        MyFactory factory = new MyClassPathXmlApplicationContext("applicationContext.xml");
        // 获取对象:
        Person person = (Person)factory.getBean("person");
        User user = (User)factory.getBean("user");
        // 调用对象的方法:
        person.eat();
        user.sleep();

    }
}

Test Results:

​ [External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-wZyKYpgF-1682532373376)(01-Spring IOC.assets/Spring-34.png)]

The simulation is roughly completed: read the xml configuration information at startup, and instantiate the configured bean (the simulation here is relatively simple, just to help everyone understand), and get it through the getBean() method provided by the context object The bean object we configure, so as to achieve the effect of automatic maintenance and creation of beans by the external container.

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-knQutnIE-1682532373376)(01-Spring IOC.assets/Spring-33.png)]

Spring IoC/DI - Bean object instantiation method

There are three ways to instantiate beans in Spring:

  • Instantiation via the constructor. By default, no-argument construction is used. This method is equivalent to the previous new method. <bean>The above introductory Spring project is actually this kind. You only need to specify the fully qualified path of the class through the class attribute in XML , and then you can instantiate the object.
  • Instantiation via a factory. There are two types, which can be instantiated through static factories and instance factories. This method is completely developed based on the idea of ​​the factory pattern in the design pattern. Spring considers that if objects of a certain class need to be instantiated frequently, the factory pattern is undoubtedly a good choice.

Method 1: Instantiate through the constructor

Note: The empty constructor created by the default constructor must exist or the creation will fail

The process of creating a project and importing dependencies is omitted, the key code:

  1. Set the configuration file applicationContext.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">
    
        <bean id="person" class="com.msb.pojo.Person"></bean>
    
    </beans>
    
  2. Create a test class and get an instantiated object

    package com.msb;
    
    import com.msb.pojo.Person;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    /**
     * Hello world!
     *
     */
    public class App 
    {
          
          
        public static void main( String[] args )
        {
          
          
            //  解析xml:
            ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
            // 获取对象:
            Person person = ac.getBean("person", Person.class);
            person.eat();
        }
    }
    
    

Introduction to factory pattern

Usually when we build objects, we use new objects everywhere. Using the factory pattern provides the best way to create objects. The factory pattern (Factory Pattern) is one of the most commonly used design patterns in Java. The creation of objects is left to the factory. If you need an object, just get it from the factory.

In the factory pattern, objects are created without exposing the creation logic to the client, and by using a common interface to point to the newly created object.

Benefits of using the factory pattern

(1) Decoupling
The creation and use of objects can be separated through the factory pattern. For example, if Class A wants to call the method of Class B, then we don't need to care about how B is created, just go to the factory to get it.

(2) Reduce the amount of code and make it easy to maintain.
If we directly new an object, if the required object construction method is more complicated, then a series of codes may be required to create the object. If the object needs to be created in another class, then the code The degree of repetition is certainly not small. Through the factory mode, we hide the specific logic of object creation and hand it over to the factory for unified management. This not only reduces the amount of code, but if you want to change the code in the future, you only need to change one place, which is also convenient for our daily work. maintain.

Scenarios used by the factory pattern

The process of creating an object instance is complex and requires preparation of many parameters.
A class has many subclasses, and the creation process of these classes is easy to change in the business. If there is no factory, it needs to be modified one by one at the creation object. After there is a factory, you only need to modify it in the factory.

Case: Buying pets at a pet store

interface:

package com.msb.factory;

/**
 * @Author: zhaoss
 */
public interface Animal {
    
    
}

Implementation class:

package com.msb.factory;

/**
 * @Author: zhaoss
 */
public class Dog implements Animal {
    
    

}
package com.msb.factory;

/**
 * @Author: zhaoss
 */
public class Cat implements Animal{
    
    
}

factory:

package com.msb.factory;

/**
 * @Author: zhaoss
 * 宠物店,需要动物的话就去宠物店购买:
 */
public class PetStore {
    
    //工厂类
    public Animal getAnimal(String petName){
    
    
        if ("猫".equals(petName)){
    
    
            return new Cat();
        }else if ("狗".equals(petName)){
    
    
            return new Dog();
        }else{
    
    
            return null;
        }
    }

    public static Animal getAnimal2(String petName){
    
    
        if ("猫".equals(petName)){
    
    
            return new Cat();
        }else if ("狗".equals(petName)){
    
    
            return new Dog();
        }else{
    
    
            return null;
        }
    }
}

test:

package com.msb.factory;

/**
 * @Author: zhaoss
 */
public class Test {
    
    
    public static void main(String[] args) {
    
    
        // 从工厂中获取动物:
        PetStore ps = new PetStore();
        // 调用工厂中普通方法:
        Animal an = ps.getAnimal("猫");
        Animal an2 = ps.getAnimal("狗");

        // 调用工厂中静态方法:不需要构建工厂对象
        Animal an3 = PetStore.getAnimal2("猫");
    }
}

Introduction to factory instantiation

Spring also provides simplification of factory instantiation, but you must be clear about what simplification is. It does not replace the factory, the factory is still the original factory, it has no effect on the factory, it just simplifies the process of calling the factory.

When we specify Spring to use the factory method to create a Bean instance, Spring will first parse the configuration file, and according to the information specified in the configuration file, call the factory method of the factory class through reflection, and use the return value of the factory method as the Bean instance. In this process, Spring is no longer responsible for creating Bean instances, and Bean instances are provided by factory methods provided by users.

Method 2: instantiate factory instantiation

Instantiate factory instantiation:

  • Factory methods are non-static methods
  • Need to configure the factory bean, and configure the factory-bean, factory-method attributes in the business bean
  1. factory class

Just use the factory in the factory mode

  1. Set the configuration file applicationContext.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">

    <!--
		实例化工厂
			1.定义实例化工厂bean
    		 2.业务bean中引用工厂bean,指定工厂创建方法(方法为非静态)
	-->
    <!--帮助我们完成PetStore的实例化:替代PetStore ps = new PetStore()-->
    <bean id="factory" class="com.msb.factory.PetStore"></bean>
    <!--替代: Animal an = ps.getAnimal("猫"); -->
    <bean id="a" factory-bean="factory" factory-method="getAnimal">
    	<constructor-arg name="petName" value=""></constructor-arg>
    </bean>

</beans>
  1. Get instantiated object
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
Animal an = (Animal) ac.getBean("a");  

PS: Maybe you think this configuration is more troublesome than using the factory by ourselves. That is because the current factory is written by yourself, and the actual factory is provided by others. Spring provides this configuration for calling the factory.

Method 3: Static factory instantiation

static factory instantiation

  • There must be the factory class and factory method
  • The factory method is static
  1. factory class

    Just use the factory in the factory mode

  2. Set configuration file spring.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">
    
        <!--静态工厂替代:Animal an3 = PetStore.getAnimal2("猫");-->
        <bean id="a2" class="com.msb.factory.PetStore" factory-method="getAnimal2">
        	<constructor-arg name="petName" value=""></constructor-arg>
        </bean>
    
    </beans>
    
  3. Get instantiated object

    ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
    Animal an = (Animal) ac.getBean("a2");  
    

Project development basically adopts the first method to instantiate beans, hand them over to Spring for hosting, and use them directly when using them. Two other understandings

Spring IoC/DI - Property Injection

The Bean object instantiation explains how to instantiate a Bean. The following explains how to assign values ​​​​to the properties of the Bean object.

Assigning values ​​to Bean object properties in Spring is also called injection. There are two ways:

  • Constructor-based Dependency Injection: Assign values ​​to bean properties through the construction method. Therefore, it is required that the bean class must provide a constructor with corresponding parameters. It is equivalent to new Person(18, "Lili");
  • Set value injection, also known as setter injection (Setter-based Dependency Injection): Assign values ​​through the Bean's setter method. Therefore, it is required that the properties in the Bean must provide a setter method. Equivalent to the previous: Person p = new Person(); p.setAge(18); p.setName("Lili");

constructor injection

Construction injection requires that a parameterized construction method must be provided in the bean (it is best to provide no parameters, this position is not used. But if other positions are not injected through construction, the default is to call no parameter construction).

Define a Bean class and a parameterized constructor

class class:

package com.msb.pojo;

/**
 * @Author: zhaoss
 * 班级类
 */
public class Clazz {
    
    
    // 属性:
    private int cid;
    private String cname;
    /* 在本次案例中,省去setter、getter方法,因为我们练习的是构造注入,需要有参构造器
    * 但是为了防止代码出错,一般会加入setter、getter方法*/

    public Clazz(int cid, String cname) {
    
    
        System.out.println("Clazz的有参构造器1");
        this.cid = cid;
        this.cname = cname;
    }

    /*当前构造注入的时候,不需要使用空构造器,但是为了防止代码出错,一般我们会加入空构造器*/
    public Clazz() {
    
    
    }

    @Override
    public String toString() {
    
    
        return "Clazz{" +
                "cid=" + cid +
                ", cname='" + cname + '\'' +
                '}';
    }
}

Student class:

package com.msb.pojo;

/**
 * @Author: zhaoss
 */
public class Student {
    
    
    private int age;
    private String name;
    private Clazz clazz;
    
	/* 在本次案例中,省去setter、getter方法,因为我们练习的是构造注入,需要有参构造器
    * 但是为了防止代码出错,一般会加入setter、getter方法*/
    
    
    public Student(int age, String name, Clazz clazz) {
    
    
        this.age = age;
        this.name = name;
        this.clazz = clazz;
    }


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

configuration bean

In the configuration file applicationContext.xml, the value of a parameter in the construction method can be set through <bean>the sub-tag .<constructor-arg>

explain:

There are 5 attributes in constructor-arg, which are divided into 2 categories.

(1) Used to determine which attribute to assign

​ name: parameter name

​ index: parameter index. Counting starts from 0.

​ type: parameter type. 8 basic data types can directly write keywords. Other types require the fully qualified path to the write type.

If you only need to use one of these three attributes, you can accurately tell Spring which constructor parameter to set, and you can use one. If you can't be precise to a certain constructor parameter, you can use multiple together.

(2) Set the value of the attribute

​ value: Simple data types (String, basic data types) are directly set. Spring does the type conversion automatically.

ref: The id of another bean needs to be referenced. That is to say, this parameter is a class type, and the object of this class is also managed by the Spring container.

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

    <!--利用这种方式,底层会去寻找空构造器-->
    <bean id="c1" class="com.msb.pojo.Clazz"></bean>
    <!--利用构造注入的方式,对属性进行初始化操作-->
    <!--通过name属性,通过参数的名字进行赋值-->
    <bean id="c2" class="com.msb.pojo.Clazz">
        <constructor-arg name="cid" value="1"></constructor-arg>
        <constructor-arg name="cname" value="java506班"></constructor-arg>
    </bean>
    <!--通过index属性,通过参数的索引进行赋值-->
    <bean id="c3" class="com.msb.pojo.Clazz">
        <constructor-arg index="0" value="2"></constructor-arg>
        <constructor-arg index="1" value="java302班"></constructor-arg>
    </bean>
    <!--通过type属性,通过参数的类型进行赋值-->
    <bean id="c4" class="com.msb.pojo.Clazz">
        <constructor-arg type="int" value="3"></constructor-arg>
        <constructor-arg type="java.lang.String" value="java816班"></constructor-arg>
    </bean>
    <!--name属性用的最多,index、type用的少-->
    <!--name\type\index属性可以单独使用,也可以配合使用-->
    <bean id="c5" class="com.msb.pojo.Clazz">
        <constructor-arg type="int" index="0" name="cid" value="4"></constructor-arg>
        <constructor-arg type="java.lang.String" index="1" name="cname" value="java999班"></constructor-arg>
    </bean>

    <!--构建Student对象
	ref:需要引用另一个bean的id。也就是说这个参数是一个类类型,且这个类的对象也被Spring容器管理。
	-->
    
    <bean id="stu" class="com.msb.pojo.Student">
        <constructor-arg name="age" value="18"></constructor-arg>
        <constructor-arg name="name" value="露露"></constructor-arg>
        <constructor-arg name="clazz" ref="c5"></constructor-arg>
    </bean>
</beans>

Write a test class and observe the console running results

package com.msb;

import com.msb.pojo.Clazz;
import com.msb.pojo.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Hello world!
 *
 */
public class App 
{
    
    
    public static void main( String[] args )
    {
    
    
        // 解析xml
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 获取对象:
        Clazz c1 = ac.getBean("c1", Clazz.class);
        System.out.println(c1);
        Clazz c2 = ac.getBean("c2", Clazz.class);
        System.out.println(c2);
        Clazz c3 = ac.getBean("c3", Clazz.class);
        System.out.println(c3);
        Clazz c4 = ac.getBean("c4", Clazz.class);
        System.out.println(c4);

        Student stu = ac.getBean("stu", Student.class);
        System.out.println(stu);
    }
}

result:

Set value injection (setter injection)

Define Bean class and Setter method

class class:

package com.msb.pojo;

/**
 * @Author: zhaoss
 */
public class Clazz {
    
    
    private int cid;
    private String cname;
    /*当前案例,是设置注入,与构造器无关,所以不加入构造*/
    /*当前案例,是设置注入,所以我们只增加setter方法*/

    public void setCid(int cid) {
    
    
        this.cid = cid;
    }

    public void setCname(String cname) {
    
    
        this.cname = cname;
    }

    @Override
    public String toString() {
    
    
        return "Clazz{" +
                "cid=" + cid +
                ", cname='" + cname + '\'' +
                '}';
    }
}

Student class:

package com.msb.pojo;

/**
 * @Author: zhaoss
 */
public class Student {
    
    
    private int age;
    private String name;
    private Clazz clazz;

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

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

    public void setClazz(Clazz clazz) {
    
    
        this.clazz = clazz;
    }

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

configuration beans

In the configuration file applicationContext.xml, the setter method of the class can be called through <bean>the subtag tag.<property>

  • name: attribute name. If the name value is a, then it will go to the setA method. It must be noted that the value of name does not correspond to the attribute, but corresponds to the name of the set method.
  • value: attribute value.
  • ref: Refers to the id attribute of another bean tag.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--创建班级对象-->
    <bean id="c" class="com.msb.pojo.Clazz">
        <property name="cid" value="1"></property>
        <property name="cname" value="java302班"></property>
    </bean>
    <!--创建学生对象-->
    <bean id="stu" class="com.msb.pojo.Student">
        <!--name属性的值与set方法的名字有关,与类的属性名字无关-->
        <property name="age" value="18"></property>
        <property name="name" value="露露"></property>
        <property name="clazz" ref="c"></property>
    </bean>
</beans>

Write a test class and observe the console results

Obtain the bean object in the test class and output it to the console to check whether it contains the set value.

package com.msb;

import com.msb.pojo.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Hello world!
 *
 */
public class App 
{
    
    
    public static void main( String[] args )
    {
    
    
        // 解析xml:
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 获取对象:
        Student s = ac.getBean("stu", Student.class);
        System.out.println(s);
    }
}

result:

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-qu8pqPiH-1682532373377)(01-Spring IOC.assets/Spring-37.png)]

Note: In the future, there will be more ways to use set value injection, which will be more flexible. The construction injection method is not flexible enough, the parameters of the constructor need to be specified, and you need to match when calling the constructor.

Choice of injection method

​The first choice for set injection in development

​Using construction injection can complete the establishment of dependencies while constructing objects. Once the object is established, everything will be ready. However, if there are many object relationships to be established, using constructor injection will leave a gap on the construction function. The next long list of parameters is not easy to remember. At this time, using Set injection will be a good choice.
  Using Set injection can have a clear name, and you can know what the injected object will be. A name like setXXX() will be better than remembering the position of a parameter on the Constructor to represent an object.

Use of the p namespace

After spring 2.5, in order to simplify the property injection of the setter method, refer to the concept of the p namespace, and simplify the sub-elements to element property configuration.

​ Introduce the p namespace in the configuration file spring.xml

xmlns:p="http://www.springframework.org/schema/p"
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--
		p:属性名:="xxx"		引入简单类型属性值
		p:属性名-ref:="xxx"	引入其他Bean对象的id属性值
	-->
    
    <!--创建班级对象-->
    <bean id="c" class="com.msb.pojo.Clazz" p:cid="1" p:cname="java302班" >
    </bean>
    <!--创建学生对象-->
    
    <bean id="stu" class="com.msb.pojo.Student" p:age="18" p:name="露露"  p:clazz-ref="c" / >
  
</beans>

The corresponding writing method of different attribute types injection

Whether it is construction injection or set value injection, value and ref are provided to set the value. These two attributes can only assign simple data types or other bean references to attributes. If the attribute of the class is an array, a collection, etc., it needs to be set in the following way.

These tags are all subtags of <property>or .<constructor-args>

Once the following sub-tag method is used, the value attribute or ref attribute cannot be set <property>or <constructor-args>set. And it is necessary to provide the corresponding name and attribute of the corresponding type in the People class.

Case: The People class provides the code for the corresponding type and name attribute.

Define the People class and setter methods

package com.msb.pojo;

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

/**
 * @Author: zhaoss
 */
public class Person {
    
    
    // 属性:
    private String[] arr;
    private List<String> list;
    private Set<String> set;
    private Map<Integer,String> map;

    public void setArr(String[] arr) {
    
    
        this.arr = arr;
    }

    public void setList(List<String> list) {
    
    
        this.list = list;
    }

    public void setSet(Set<String> set) {
    
    
        this.set = set;
    }

    public void setMap(Map<Integer, String> map) {
    
    
        this.map = map;
    }

    @Override
    public String toString() {
    
    
        return "Person{" +
                "arr=" + Arrays.toString(arr) +
                ", list=" + list +
                ", set=" + set +
                ", map=" + map +
                '}';
    }
}

configuration bean

Array type\List type\Set type\Map type\Null value type

<?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">
    <!--构建Person对象,对不同类型的属性进行赋值,进行属性注入,利用设置注入的方式-->
    <bean id="p" class="com.msb.pojo.Person">
        <!--可以利用设置注入,也可以利用构造注入,只是我当前的案例是利用设置注入-->
        <!--对数组类型进行注入-->
        <property name="arr" >
            <array>
                <value>aaa</value>
                <value>bbb</value>
                <value>ccc</value>
            </array>
        </property>

        <!--List集合赋值:-->
        <property name="list">
            <list>
                <value>aaa</value>
                <value>bbb</value>
                <value>ccc</value>
            </list>
        </property>
        <!--Set集合赋值:-->
        <property name="set">
            <set>
                <value>aaa</value>
                <value>bbb</value>
                <value>ccc</value>
            </set>
        </property>
        <!--Map集合赋值:-->
        <!--<property name="map">
            <map>
                <entry>
                    &lt;!&ndash;key标签中不可以直接加入属性值,而是必须再套用value标签&ndash;&gt;
                    <key><value>18</value></key>
                    <value>露露</value>
                </entry>
                <entry>
                    &lt;!&ndash;key标签中不可以直接加入属性值,而是必须再套用value标签&ndash;&gt;
                    <key><value>21</value></key>
                    <value>菲菲</value>
                </entry>
                &lt;!&ndash;也可以利用entry的属性赋值&ndash;&gt;
                <entry key="22" value="小明" ></entry>
            </map>
        </property>-->

        <!--Map集合赋空值-->
        <property name="map">
            <null></null>
        </property>
    </bean>

</beans>

test

public class App2 {
    
    
    public static void main(String[] args) {
    
    
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext02.xml");
        Person p = ac.getBean("p", Person.class);
        System.out.println(p);
    }
}

operation result:

circular dependency

Sometimes the following scenarios are encountered:

code:

Class A:

package com.msb.pojo;

/**
 * @Author: zhaoss
 */
public class A {
    
    
    // 属性:
    private B b;
    // 构造器:

    public A(B b) {
    
    
        this.b = b;
    }
   
}

Class B:

package com.msb.pojo;

/**
 * @Author: zhaoss
 */
public class B {
    
    
    // 属性:
    private A a;
    // 构造器:

    public B(A a) {
    
    
        this.a = a;
    }

    
}

Configuration beans:

<?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">
    <!--创建A对象-->
    <bean id="a" class="com.msb.pojo.A" scope="singleton">
        <constructor-arg name="b" ref="b"></constructor-arg>
    </bean>
    <!--创建B对象-->
    <bean id="b" class="com.msb.pojo.B">
        <constructor-arg name="a" ref="a"></constructor-arg>
    </bean>
</beans>

test:

public class App3 {
    
    
    public static void main(String[] args) {
    
    
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext03.xml");
    }
}

The running result reports an error:

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-hdvT5ijs-1682532373378)(01-Spring IOC.assets/Spring-40.png)]

Error reason:

Circular dependency problem, when both classes are injected by construction, another class needs to be injected before the current class is instantiated, and the other class needs to be injected into the current class before the instantiation is complete, so this situation cannot be solved cyclic injection problem. A BeanCurrentlyInCreationException will appear.

Solution:

Use the setter method to inject, and the default attribute of the bean tag is omitted: scope="singleton", singleton: the default value, which means that the bean is a singleton, and the bean is the same object every time it is obtained. Because the singleton has a three-level cache (DefaultSingletonBeanRegistry) by default, it can temporarily cache beans that have not been instantiated. The third-level cache is only available in the setter mode, because there is no object that needs to be cached when constructing injection, so there is no need to use the third-level cache.

Level 3 cache: Temporarily store uncreated objects. For example, in the current case, A wants to inject b, but b has not been created. Put b into the cache. After b is created, take b from the cache. Just come out and inject A.

code:

Class A:

package com.msb.pojo;

/**
 * @Author: zhaoss
 */
public class A {
    
    
    // 属性:
    private B b;
    // 构造器:

    public A(B b) {
    
    
        this.b = b;
    }

    // 加入setter方法:

    public void setB(B b) {
    
    
        this.b = b;
    }

    // 加入空构造器:

    public A() {
    
    
    }
}

Class B:

package com.msb.pojo;

/**
 * @Author: zhaoss
 */
public class B {
    
    
    // 属性:
    private A a;
    // 构造器:

    public B(A a) {
    
    
        this.a = a;
    }

    // 加入setter方法:

    public void setA(A a) {
    
    
        this.a = a;
    }

    // 加入空构造器:

    public B() {
    
    
    }
}

Configuration beans:

<?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">
    <!--创建A对象-->
    <bean id="a" class="com.msb.pojo.A" scope="singleton">
        <!--<constructor-arg name="b" ref="b"></constructor-arg>-->
        <property name="b" ref="b"></property>
    </bean>
    <!--创建B对象-->
    <bean id="b" class="com.msb.pojo.B">
        <!--<constructor-arg name="a" ref="a"></constructor-arg>-->
        <property name="a" ref="a"></property>
    </bean>
</beans>

test:

public class App3 {
    
    
    public static void main(String[] args) {
    
    
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext03.xml");
        A a = ac.getBean("a", A.class);
        B b = ac.getBean("b", B.class);

    }
}

automatic injection

In Spring, automatic injection of beans is allowed. There are two ways to configure: default-autowire and autowire, and the bottom layer is also based on construction injection or setting injection.

  • Configure the autowire attribute in the root tag <bean>, which represents the automatic injection strategy in the entire Spring. There are 5 values ​​for the autowire attribute.

    default: default value. Not automatically injected.

    no: Do ​​not inject automatically.

    byName: Automatic injection by name. It will automatically find the bean whose id name in the container is the same as the current property name for injection. (The underlying call is the setter method)

    byType: Automatic injection by type. It will automatically find the bean whose type matches the current bean type in the container for injection. An exception will occur if multiple beans of the same type are injected. (The underlying call is the setter method)

    constructor: Injection through the construction method. Look for a suitable constructor in the bean's constructor. If it is automatically injected into it. The type is first byType and then byName. If it is not found, it will not be injected. Note: The constructor type is the same as other Bean types. (The underlying call is the constructor)

byName case:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd"
       
    <bean id="s" class="com.msbt.pojo.Student" autowire="byName" ></bean>
</beans>
package com.msb.pojo;

/**
 * @Author: zhaoss
 */
public class Clazz {
    
    
    private String cname;

    public String getCname() {
    
    
        return cname;
    }

    public void setCname(String cname) {
    
    
        this.cname = cname;
    }

    public Clazz(String cname) {
    
    
        this.cname = cname;
    }

    public Clazz() {
    
    
    }

    @Override
    public String toString() {
    
    
        return "Clazz{" +
                "cname='" + cname + '\'' +
                '}';
    }
}

package com.msb.pojo;

/**
 * @Author: zhaoss
 */
public class Student {
    
    
    private Clazz clazz;

    public Clazz getClazz() {
    
    
        return clazz;
    }

    public void setClazz(Clazz clazz) {
    
    
        this.clazz = clazz;
    }

    public Student() {
    
    
    }

    public Student(Clazz clazz) {
    
    
        this.clazz = clazz;
    }

    @Override
    public String toString() {
    
    
        return "Student{" +
                "clazz=" + clazz +
                '}';
    }
}

test:

public class App 
{
    
    
    public static void main( String[] args )
    {
    
    
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        Student s = ac.getBean("s", Student.class);
        System.out.println(s);
    }
}

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-Obee2gmw-1682532373378)(01-Spring IOC.assets/Spring-41.png)]

byType case:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="s" class="com.msbt.pojo.Student" autowire="byType" ></bean>
</beans>

[External link picture transfer failed, the source site may have an anti-theft link mechanism, it is recommended to save the picture and upload it directly (img-10DzcZcm-1682532373379)(01-Spring IOC.assets/Spring-42.png)]

constructor case:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="s" class="com.msbt.pojo.Student" autowire="constructor" ></bean>
</beans>

[External link picture transfer failed, the source site may have an anti-theft link mechanism, it is recommended to save the picture and upload it directly (img-qCB4ACkp-1682532373379)(01-Spring IOC.assets/Spring-43.png)]

  • <beans>Configure the default-autowire attribute in the tag . Same value as autowire. The only thing to note is that default represents the value of the global default-autowire. If both autowire and default-autowire exist, autowire takes effect.
<bean id="s" class="com.msbt.pojo.Student" autowire="byType"></bean>
<?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"
       default-autowire="byType">
    <bean id="s" class="com.msbt.pojo.Student" ></bean>
</beans>

Spring IoC/DI - scope attribute of bean tag

The scope in Spring <bean>controls the effective scope of the Bean.

There are a total of 6 possible values, the official screenshot is as follows:

The singleton and prototype inside can be used in the most basic environment of Spring, and do not need a web environment.

But the request, session, application, and websocket inside can only be used in the web environment.

Our cases here are all ordinary java projects, so we focus on explaining singleton and prototype. The configuration methods of request, session, application, and websocket are the same as singleton and prototype, but must have web environment support, and configure corresponding container listeners or Interceptors can apply these scopes. At present, you should be familiar with the concept first, and then explain the specific use when integrating the web later. You only need to know that there are these scopes.

case:

package com.msb.pojo;

/**
 * @Author: zhaoss
 */
public class Person {
    
    
    private String name;

    public Person() {
    
    
        System.out.println("这是一个Person的空构造器");
    }
}
<?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"
>

    <!--构建Person对象:
    lazy-init="true" 懒加载:改变创建对象的时机 ,如果没有设置为true那么解析xml的时候就会构建bean对象
    但是现在设置了懒加载,就会在第一次getBean的时候进行桂香的构建。

    scope="singleton" 单例  构建对象的时候,对象只会创建一次,每次取出都是同一个对象
    scope="prototype" 多例  每次向Spring容器请求获取Bean都返回一个全新的Bean,每次getBean的时候都会帮我们构建对象,每次取出的都是不同的对象。
    -->
    <!--<bean id="p" class="com.msb.pojo.Person" scope="singleton" lazy-init="true">
    </bean>-->
    <bean id="p" class="com.msb.pojo.Person" scope="prototype" lazy-init="true">
    </bean>

</beans>
public class App02
{
    
    
    public static void main( String[] args )
    {
    
    
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext02.xml");
        Person s1 = ac.getBean("p", Person.class);
        Person s2 = ac.getBean("p", Person.class);
        System.out.println(s1 == s2);
    }
}

Additional details:

(1) If the lazy-init attribute (lazy loading)
is false, the bean object will be instantiated when the IOC container starts. The default is false
. If it is true, the bean object will not be instantiated when the IOC container starts. When using the bean object will be instantiated when

(2) What are the benefits of setting lazy-init to false?
1) Potential configuration problems can be found in advance
2) The Bean object exists in the cache, and there is no need to instantiate the bean when using it, which speeds up the efficiency of the program

(3) Are beans thread-safe in Spring ?

​ If the scope of the bean is a singleton, the bean is not thread-safe.

​ If the scope of the bean is prototype, the bean is thread-safe.

(4) What object is suitable as a singleton object?
Generally speaking, the singleton mode is suitable for stateless or immutable objects. (There is no member variable that will change the state of the object)
For example: controller layer, service layer, dao layer

(5) What is a stateless or immutable object?

​ In fact, changes in object status are often caused by changes in attribute values. For example, the name attribute of the user class will change, and changes in the attribute name will generally cause changes in the state of the user object. For our program, the stateless object has no instance variables, which ensures the safety of the thread, and the service layer business object is a stateless object. thread safe.

Spring IoC/DI - Bean life cycle

​ The bean managed by the Spring container also has the concept of life cycle. In Spring, the bean life cycle includes four stages: bean definition, initialization, use and destruction.

Bean initialization

​ By default, the object is instantiated when the IOC container is loaded.

There are two ways of Spring bean initialization:

​ **Method 1:** Complete by specifying the init-method attribute in the configuration document.

public class Person {
    
    
    // 定义初始化时需要被调用的方法
    public void init() {
    
    
        System.out.println("Person init...");
    }
}
<!-- 通过init-method属性指定方法 -->
<bean id="p" class="com.msb.pojo.Person" init-method="init"></bean>

​Method 2: Implement the org.springframework.beans.factory.InitializingBean interface.

public class Person implements InitializingBean {
    
    

    @Override
    public void afterPropertiesSet() throws Exception {
    
    
        System.out.println("Person init...");
    }
}
<bean id="p" class="com.msb.pojo.Person" ></bean>

​ The bean object instantiation process is instantiated when the Spring container is initialized, but it is not immutable. You can delay the initialization of the bean object through the lazy-init="true" attribute, and then call the getBean method. Perform bean initialization operations

Bean use

// 得到Spring的上下文环境
BeanFactory factory = new ClassPathXmlApplicationContext("spring.xml");
Person p = (Person) factory.getBean("Person");

Bean destruction

​ Implement the destruction method (the Spring container will maintain the management of the bean object, and you can specify the method to be executed for the destruction of the bean object).

​ Define the destroy method:

public class Person {
    
    

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

​ Implement the destruction method (the Spring container will maintain the management of the bean object, and you can specify the method to be executed for the destruction of the bean object)

<bean id="roleService" class="com.yjxxt.service.RoleService" destroy-method="destroy"></bean>

​ Through the AbstractApplicationContext object, call its close method to realize the bean destruction process

AbstractApplicationContext ctx=new ClassPathXmlApplicationContext("spring.xml");
ctx.close();

Spring integrates MyBatis

Case: Spring integrates MyBatis to complete the login function.

Focus: learn to integrate.

database creation table

Create User table, define fields username, password

build web project

There are pages, you need to use servlets, and you need to create web projects.

Add dependent coordinates, plugins

[1] mybatis dependency

[2] Dependency to connect to mysql

[3] log4j dependency

【4】Servlet dependency

【5】spring dependency

[6] springjdbc dependency: use this dependency to manage the database

[7] Spring integrates mybatis dependencies: version 3.0+ is required: https://mybatis.org/spring/index.html

【8】Add tomcat plugin

[9] Add resource copy plug-in

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.msb</groupId>
        <artifactId>Spring6</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>SMDemo</artifactId>
    <packaging>war</packaging>
    <name>SMDemo Maven Webapp</name>
    <url>http://maven.apache.org</url>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
        <!--  【1】mybatis的依赖  -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.9</version>
        </dependency>
        <!--  【2】连接mysql的依赖  -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</version>
        </dependency>
        <!--  【3】log4j的依赖  -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        <!--  【4】servlet的依赖  -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>
        <!--  【5】spring的依赖  -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>6.0.5</version>
        </dependency>
        <!--  【6】springjdbc依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>6.0.5</version>
        </dependency>
        <!--  【7】spring整合mybatis的依赖  -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>3.0.1</version>
        </dependency>
    </dependencies>
    <build>
        <finalName>SMDemo</finalName>
        <plugins>
            <!-- tomcat7插件 -->
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.2</version>
                <configuration>
                    <path>/testssm</path>
                    <port>8888</port>
                </configuration>
            </plugin>
        </plugins>
        <!-- 加入资源拷贝插件 -->
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.txt</include>
                    <include>**/*.xml</include>
                    <include>**/*.properties</include>
                </includes>
            </resource>
        </resources>
    </build>
</project>

Complete the java directory and add the package structure

Create a User entity class

Build entity classes under the com.msb.pojo package:

package com.msb.pojo;

/**
 * @Author: zhaoss
 */
public class User {
    
    
    private int id;
    private String username;
    private String password;

    public int getId() {
    
    
        return id;
    }

    public void setId(int id) {
    
    
        this.id = id;
    }

    public String getUsername() {
    
    
        return username;
    }

    public void setUsername(String username) {
    
    
        this.username = username;
    }

    public String getPassword() {
    
    
        return password;
    }

    public void setPassword(String password) {
    
    
        this.password = password;
    }

    public User() {
    
    
    }

    public User(int id, String username, String password) {
    
    
        this.id = id;
        this.username = username;
        this.password = password;
    }

    @Override
    public String toString() {
    
    
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

Mapper layer processing

Build the UserMapper interface:

package com.msb.mapper;

import com.msb.pojo.User;

/**
 * @Author: zhaoss
 */
public interface UserMapper {
    
    
    public abstract User selectOneUser(String uname, String pwd);
}

Create a mapping file UserMapper.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.msb.mapper.UserMapper">
    <select id="selectOneUser" resultType="user">
        select * from t_user where username=#{param1} and password=#{param2}
    </select>
</mapper>

Integrate the processing of mybatis

When using mybatis before, you need to add the mybatis configuration file in the resources directory: mybatis.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<!-- 别名处理 -->
    <typeAliases>
        <!-- 指定包 -->
        <package name="com.msb.pojo"/>
    </typeAliases>

    <environments default="mysql">
        <environment id="mysql">
            <!--配置事务管理器 -->
            <transactionManager type="JDBC"></transactionManager>
            <!-- 配置数据源-->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/springmybatis?useUnicode=true&amp;characterEncoding=utf-8&amp;useSSL=false&amp;serverTimezone=GMT%2B8&amp;allowPublicKeyRetrieval=true"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <!-- 解析UserMapper.xml  -->
    <mappers>
        <mapper resource="mapper/UserMapper.xml"/>
    </mappers>
</configuration>

After spring integrates mybatis, this file will undergo earth-shaking changes. Now it is managed by spring, and this set of configurations has changed. But even if it changes again, the previous parts still exist.

Previous database connection part test class:

package com.msb.test;

import com.msb.mapper.BookMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class Test {
    
    
    public static void main(String[] args) throws IOException {
    
    
        String resource = "mybatis.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();

        /*
         getMapper方法采用了动态代理模式,根据你传入的接口,动态产生实现类,
         那么你想:要想产生实现类肯定是匹配到了对应的映射文件了。这些Mybatis框架都自动帮我们做了,
         而我们要做的就是要将底层该配置的配置好,否则mybatis找不到东西也完成不了效果了。
         这里其实就相当于以前的:BookMapper b = new BookMapperImpl(); --》多态

         */
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        //看上去用接口在调用selectAllBooks,实际走的肯定是实现类的selectAllBooks,也就是映射文件中对应的方法。
        User user = mapper.selectOneUser("lili","123123");


        sqlSession.close();

    }
}

What to do now?

Add the spring configuration file applicationContext.xml in the resources directory:

<?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">
    <!--【1】通过配置bean对象,给对象属性注入值来配置连接数据库数据源
    DriverManagerDataSource属于spring-jdbc包-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <!--这个name属性都可以在DriverManagerDataSource中找到对应的setter方法-->
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url"
                  value="jdbc:mysql://localhost:3306/springmybatis?useUnicode=true&amp;characterEncoding=utf-8&amp;useSSL=false&amp;serverTimezone=GMT%2B8&amp;allowPublicKeyRetrieval=true"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean>


    <!--【2】配置SqlSessionFactory对象
    SqlSessionFactoryBean属于mybatis-spring包-->
    <bean id="factory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--工厂依赖数据源,需要注入数据源对应的对象-->
        <property name="dataSource" ref="dataSource"/>
        <property name="typeAliasesPackage" value="com.msb.pojo"></property>
    </bean>

    <!--【3】扫描UserMapper文件-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!--需要注入工厂,因为以前都是:sqlSession.getMapper()-->
        <property name="sqlSessionFactoryBeanName" value="factory"></property>
        <!--扫描的文件-->
        <property name="basePackage" value="com.msb.mapper"></property>
    </bean>
</beans>

Business layer implementation

interface layer:

public interface UserService {
    
    
    public abstract User selectOneUser(String uname, String pwd);
}

Implementation class:

package com.msb.service.impl;

import com.msb.mapper.UserMapper;
import com.msb.pojo.User;
import com.msb.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @Author: zhaoss
 */
public class UserServiceImpl implements UserService {
    
    
    @Override
    public User selectOneUser(String uname, String pwd) {
    
    
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserMapper userMapper = (UserMapper)ac.getBean("userMapper");
        return userMapper.selectOneUser(uname,pwd);
    }

    /**
     * 创建测试方法,看看spring到底帮我们构建多少对象:
     * @param args
     */
    public static void main(String[] args) {
    
    
   
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        //
        String[] beanDefinitionNames = ac.getBeanDefinitionNames();
        for (String name : beanDefinitionNames) {
    
    
            System.out.println(name);
        }
    }
}

main method result:

We configured in applicationContext.xml

<property name="basePackage" value="com.msb.mapper"></property>

After scanning this package, spring will help us to automatically build the implementation class object corresponding to the interface under this package: userMapper object, so that you can directly use userMapper in the business layer. (The object name is the first letter of the interface name in lowercase)

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-JjgprMkl-1682532373381) (01-Spring integrates MyBatis.assets/sm-03.png)]

Control layer implementation

package com.msb.controller;

import com.msb.pojo.User;
import com.msb.service.UserService;
import com.msb.service.impl.UserServiceImpl;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @Author: zhaoss
 */
@WebServlet("/loginServlet")
public class UserServlet extends HttpServlet {
    
    
    UserService userService = new UserServiceImpl();
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        // 解决乱码问题:
        // 设置请求信息的解码格式:
        req.setCharacterEncoding("UTF-8");
        // 设置响应信息的编码格式:
        resp.setCharacterEncoding("UTF-8");
        // 设置浏览器的编码格式:
        resp.setContentType("text/html;charset=UTF-8");
        // 获取前台参数:
        String uname = req.getParameter("uname");
        String pwd = req.getParameter("pwd");
        User user = userService.selectOneUser(uname, pwd);
        // 对参数处理:
        if (user != null){
    
    
            req.getRequestDispatcher("index.jsp").forward(req,resp);
        }else{
    
    
            resp.getWriter().write("登录失败");
        }
    }
}

index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body>
<h2>Hello World!项目首页</h2>
</body>
</html>

login.jsp

<%--
  Created by IntelliJ IDEA.
  User: zhaoss-msb
  Date: 2023/3/2
  Time: 21:28
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
  <%--定义表单--%>
  <form action="loginServlet" method="post">
    用户名:<input type="text" name="uname"> <br>
    密码:<input type="password" name="pwd"> <br>
    <input type="submit" value="登录">
  </form>
</body>
</html>

Visit: http://localhost:8888/testssm/login.jsp

Log in:

login successful:

Login failed:

Fix project defects

In the current business layer:

public class UserServiceImpl implements UserService {
    
    
    @Override
    public User selectOneUser(String uname, String pwd) {
    
    
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserMapper userMapper = (UserMapper)ac.getBean("userMapper");
        return userMapper.selectOneUser(uname,pwd);
    }
}

Does every method of the business layer have to parse xml and then getBean? That's too troublesome, let's learn spring to help us manage objects!

solve:

Modify the business layer:

package com.msb.service.impl;

import com.msb.mapper.UserMapper;
import com.msb.pojo.User;
import com.msb.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @Author: zhaoss
 */
public class UserServiceImpl implements UserService {
    
    
    private UserMapper userMapper;

    public void setUserMapper(UserMapper userMapper) {
    
    
        this.userMapper = userMapper;
    }

    @Override
    public User selectOneUser(String uname, String pwd) {
    
    
        return userMapper.selectOneUser(uname,pwd);
    } 
}

userMapper uses spring to create a UserServiceImpl object, and then uses setter injection to inject the userMapper object, adding in applicationContext.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">

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" >
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/sm?useUnicode=true&amp;characterEncoding=utf-8&amp;useSSL=false&amp;serverTimezone=GMT%2B8&amp;allowPublicKeyRetrieval=true"></property>
        <property name="username" value="root"></property>
        <property name="password" value="root"></property>
    </bean>


    <bean id="factory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <property name="typeAliasesPackage" value="com.msb.pojo"></property>
    </bean>


    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="factory"></property>
        <property name="basePackage" value="com.msb.mapper"></property>
    </bean>

    <!--加入UserServiceImpl构建对象-->
    <bean id="userServiceImpl" class="com.msb.service.impl.UserServiceImpl" >
        <property name="userMapper" ref="userMapper"></property>
    </bean>
</beans>

Now that the UserServiceImpl object is constructed, the control layer can also be simplified as:

package com.msb.controller;

import com.msb.pojo.User;
import com.msb.service.UserService;
import com.msb.service.impl.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @Author: zhaoss
 */
@WebServlet("/loginServlet")
public class UserServlet extends HttpServlet {
    
    
    private UserService us;

    @Override
    public void init() throws ServletException {
    
    
        // 解析applicationContext.xml:
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 获取UserServiceImpl对象:
        us = (UserServiceImpl)ac.getBean("userServiceImpl");
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        // 处理乱码:
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        // 接收前台参数:
        String uname = req.getParameter("uname");
        String pwd = req.getParameter("pwd");
        System.out.println(uname);
        System.out.println(pwd);
        // 调用service层
        User user = us.selectOneUser(uname, pwd);
        // 对user判断:
        if (user != null){
    
    // 数据查询到了
            // 跳转到首页:
            req.getRequestDispatcher("index.jsp").forward(req,resp);
        }else{
    
    
            resp.getWriter().write("登录失败!");
        }
    }
}

log processing

At present, the project does not have log output, so it is necessary to add log processing, there are two ways

Method 1: keep mybatis.xml

(1) Add log4j.properties to the resources directory

# log4j中定义的级别:fatal(致命错误) > error(错误) >warn(警告) >info(普通信息) >debug(调试信息)>trace(跟踪信息)
log4j.rootLogger = DEBUG , console , D 

### console ###
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern = [%p] [%-d{yyyy-MM-dd HH\:mm\:ss}] %C.%M(%L) | %m%n

(2) Create the Mybatis configuration file mybatis.xml in the resources directory, and write the enable log in the file.

<?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>
    <settings>
        <setting name="logImpl" value="LOG4J"/>
    </settings>
</configuration>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" >
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/sm?useUnicode=true&amp;characterEncoding=utf-8&amp;useSSL=false&amp;serverTimezone=GMT%2B8&amp;allowPublicKeyRetrieval=true"></property>
        <property name="username" value="root"></property>
        <property name="password" value="root"></property>
    </bean>


    <bean id="factory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <property name="typeAliasesPackage" value="com.msb.pojo"></property>
        <!--加入配置,解析mybatis.xml-->
        <property name="configLocation" value="classpath:mybatis.xml"></property>
    </bean>



    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="factory"></property>
        <property name="basePackage" value="com.msb.mapper"></property>
    </bean>

    <bean id="userServiceImpl" class="com.msb.service.impl.UserServiceImpl" >
        <property name="userMapper" ref="userMapper"></property>
    </bean>
</beans>

The advantage of this method: mybatis secondary cache and hump conversion need to be configured in mybatis.xml, which is not provided in spring, so this kind of mybatis.xml file can be retained.

Method 2: Change the log type to slf4j

At this time, the mybatis.xml file is not needed, and the upgrade log type is slf4j

Add two dependencies: slf4j and slf4j-log4j

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.1</version>
</dependency>

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.2</version>
</dependency>

Spring IoC/DI - Annotation support

This part mainly explains the annotations about IoC/DI. The function of annotations simplifies the configuration of xml.

Spring existing code problem analysis and solution

In the previously integrated code, if it is layered, in order to create a UserServiceImpl object, you need to configure the bean tag in applicationContext.xml:

	<!--加入UserServiceImpl构建对象-->
    <bean id="userServiceImpl" class="com.msb.service.impl.UserServiceImpl" >
        <property name="userMapper" ref="userMapper"></property>
    </bean>

For the above writing method, you can use the annotation @Component to simplify it.

Using the previously integrated case, modify:

Now to build the UserServiceImpl object, add the @Component annotation to the UserServiceImpl class:

When @Component annotations and sub-annotations are used, if the name of the bean is not specified explicitly, the default name is the first letter of the class name becomes lowercase

/**
 * @Author: zhaoss
 * @Component注解的作用:简化了applicationContext.xml中对这个创建对象的配置 ,而创建对象这件事还是spring来管理。
 * 帮我们构建对象,默认的名字就是类名的首字母小写: UserServiceImpl  ---》 userServiceImpl
 * 我们也可以指定对象的名字:通过传入参数的形式:@Component("usi")
 */
@Component
public class UserServiceImpl implements UserService {
    
    
    private UserMapper userMapper;

    public void setUserMapper(UserMapper userMapper) {
    
    
        this.userMapper = userMapper;
    }

    @Override
    public User selectOneUser(String uname, String pwd) {
    
    
        return userMapper.selectOneUser(uname,pwd);
    }

}

After adding @Component, there is no need to specify bean tags in applicationContext.xml , and you can help us build objects. The name of the object you build for us is: the first letter of the class name becomes lowercase. Of course, if you want to specify the name yourself as usi It's also okay:


@Component("usi")
public class UserServiceImpl implements UserService {
    
    
    private UserMapper userMapper;

    public void setUserMapper(UserMapper userMapper) {
    
    
        this.userMapper = userMapper;
    }

    @Override
    public User selectOneUser(String uname, String pwd) {
    
    
        return userMapper.selectOneUser(uname,pwd);
    }

}

It should be noted that for any annotation to take effect, the annotation must be scanned:

Which package is the annotation in? To find these annotations, you need to scan the package where the annotation is located: set the package to be scanned, if you need to scan multiple packages, use commas to separate the package paths. And need to add context namespace in applicationContext.xml (each namespace needs to add three lines). The order can not be disordered, and there can be no gaps in the middle. The context namespace is found in the spring document, just paste one and change it

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-GRduZuoG-1682532373382)(01-Spring IOC.assets/Spring-45.png)]

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

    <!-- 多个包使用逗号分隔,下面也可以只写com.msb -->
    <context:component-scan base-package="com.msb.service,com.msb.mapper"></context:component-scan>

</beans>

Sub-annotation of @Component annotation

The following @Repository, @Service, @Controller, and @Configuration are all sub-annotations of the @Component annotation, which have the same function: create objects. The main difference is the difference in semantics, and different annotations are placed in classes of different layers. But if you don’t follow the semantics, it’s also effective if you don’t use @Service in the persistence layer. But this is not standardized.

Annotation name explain
@Component To instantiate a bean, the default name is the class name with lowercase letters. Support for custom names
@Repository @Component subtag. The effect is the same as @Component. used in the persistence layer
@Service @Component subtag. The effect is the same as @Component. used in the business layer
@Controller @Component subtag. The effect is the same as @Component. used in the controller layer
@Configuration @Component subtag. The effect is the same as @Component. It is used in the configuration class and will be used in conjunction with SpringBoot in the future.

In our case of integrating mybatis with spring, which annotation can we use?

The mapper layer does not require us to build objects and spring to manage them, so this layer does not need to annotate @Repository for the time being.

In the controller layer, we use servlet and tomcat management, so this layer does not need to annotate @Controller for the time being.

At present, the business layer can replace @Component with @Service.


@Service
public class UserServiceImpl implements UserService {
    
    
    private UserMapper userMapper;

    public void setUserMapper(UserMapper userMapper) {
    
    
        this.userMapper = userMapper;
    }

    @Override
    public User selectOneUser(String uname, String pwd) {
    
    
        return userMapper.selectOneUser(uname,pwd);
    }

}

Annotations related to attribute injection

In the last lesson, we have simplified the configuration in xml with the @Component annotation, and used the case of mybatis and spring integration again to start the server to test the login effect:

It is found that clicking the login button requests an error in the background:

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-ZgK9SqyU-1682532373382)(01-Spring IOC.assets/Spring-47.png)]

It is found that the userMapper object is empty, which means that we just created the UserMapperImpl object but the properties are not injected, which means that the @Component annotation only simplifies the xml configuration for creating objects, but the configuration of property injection does not help us. At this time, we need to use property injection Related notes:

Annotation name explain
@Autowired Automatic injection. The default is byType, if there are multiple beans of the same type, use byName. Spring annotations.
@Resource Not Spring annotations. Default byName, if not found, use byType. The annotations of the javax package in JDK are generally not used, and spring annotations are used
@Value Assign values ​​to attributes of common data types (eight basic data types + String). Spring annotations.

Highlights: @Autowired.

@Autowired annotation: It will go to the container to find the corresponding object according to the type. The default is byType. If there are multiple beans of the same type, use byName to assign a value to the current property after finding it, and it does not need to rely on the set method. The property type can be an interface . Automatically match the corresponding implementation class object, for example, you write: private UserMapper userMapper; there is no problem with using the interface.

So the question is, what if there are multiple implementation classes of the UserMapper interface in the container? That is to say, multiple implementation class objects are matched according to the type, for example, there are two implementation classes: UserMapperImplA, UserMapperImplB, then another annotation @Qualifier(value="bean name") is needed to execute the Bean name that needs to be injected : In this way, the object in the container will be found according to the name: value= can be omitted.

package com.msb.service.impl;

import com.msb.mapper.UserMapper;
import com.msb.pojo.User;
import com.msb.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

@Service("usi")
public class UserServiceImpl implements UserService {
    
    
    /*
    * 加入@Autowired注解的作用:帮我们在创建对象以后完成属性的注入,此时我们不需要提供setter方法
    * 注入形式:先按照类型从spring容器中去找匹配的对象注入进来。
    * 如果容器中存在多个相同类型的对象,那么就按照名字去找。
    * 比如容器中UserMapper实现类对象1 :um1   还有UserMapper实现类对象2:um2
    * 此时就需要搭配另一个注解:@Qualifier("um1")  来指定你需要的那个对象
    * 使用了 @Qualifier("um1")注解后@Autowired是不能省略的,因为@Autowired帮我们完成属性注入,
    * @Qualifier只是定位到你需要注入的对象,必须搭配使用
    * */
    @Autowired
    /*@Qualifier("um1")*/
    private UserMapper userMapper;
    /*加入@Autowired注解以后,底层会自动帮我们定义setter方法,无需我们自己创建这个方法*/
    /*public void setUserMapper(UserMapper userMapper) {
        this.userMapper = userMapper;
    }*/

    @Override
    public User selectOneUser(String uname, String pwd) {
    
    
        return userMapper.selectOneUser(uname,pwd);
    }

}

Assignment of attributes of common data types @Value annotation

In Section 11.3 above, attribute injection is performed on class objects, so how to inject and assign values ​​to ordinary types of attributes?

Define the class: use @Component and @Value

package com.msb.test;

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

/**
 * @Author: zhaoss
 */
@Component
public class Person {
    
    
    @Value("18")
    private int age;
    @Value("lili")
    private String name;

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

Configure the package where the scanning annotation is located in applicationContext.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"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd" >

    <!--加入扫描注解所在的包:多个包用逗号分隔开-->
    <context:component-scan base-package="com.msb.test"></context:component-scan>
    
</beans>

test:

public class Test {
    
    
    public static void main(String[] args) {
    
    
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        Person person = ac.getBean("person", Person.class);
        System.out.println(person);
    }
}

However, the above method writes the attribute value to death. We generally don’t use it like this. We use it in conjunction with the attribute file. The @Valuebiggest function is to read the configuration file, and then use it with the configuration center (such as Nacos). Learn now Just use it.

Define the a.properties property file in the resources directory:

age=19
name=feifei

Scan the property file, add the configuration of scanning properties in applicationContext.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"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd" >
   

    <!--加入扫描注解所在的包:多个包用逗号分隔开-->
    <context:component-scan base-package="com.msb.service,com.msb.mapper,com.msb.test"></context:component-scan>
    <!--加入properties文件的扫描,扫描以后,spring容器中就会有一处专门存放a.properties中的键值对-->
    <context:property-placeholder location="classpath:a.properties"></context:property-placeholder>
</beans>

In this way, when the container is scanned, the content in a.properties will be read, and there will be a special place in the container to store the key-value pairs of a.properties. How to assign the key-value pairs to the properties? You can use expressions like ${} to get the variable values ​​of the system or the values ​​in the .properties attribute configuration file

package com.msb.test;

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

/**
 * @Author: zhaoss
 */
@Component
public class Person {
    
    
    @Value("${age}")
    private int age;
    @Value("${name}")
    private String name;

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




###  普通数据类型的属性的赋值 @Value注解

上面11.3节中是给类对象进行属性注入,那么普通类型的属性如何注入赋值呢?

定义类:使用@Component和 @Value

```java
package com.msb.test;

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

/**
 * @Author: zhaoss
 */
@Component
public class Person {
    @Value("18")
    private int age;
    @Value("lili")
    private String name;

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

Configure the package where the scanning annotation is located in applicationContext.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"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd" >

    <!--加入扫描注解所在的包:多个包用逗号分隔开-->
    <context:component-scan base-package="com.msb.test"></context:component-scan>
    
</beans>

test:

public class Test {
    
    
    public static void main(String[] args) {
    
    
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        Person person = ac.getBean("person", Person.class);
        System.out.println(person);
    }
}

However, the above method writes the attribute value to death. We generally don’t use it like this. We use it in conjunction with the attribute file. The @Valuebiggest function is to read the configuration file, and then use it with the configuration center (such as Nacos). Learn now Just use it.

Define the a.properties property file in the resources directory:

age=19
name=feifei

Scan the property file, add the configuration of scanning properties in applicationContext.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"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd" >
   

    <!--加入扫描注解所在的包:多个包用逗号分隔开-->
    <context:component-scan base-package="com.msb.service,com.msb.mapper,com.msb.test"></context:component-scan>
    <!--加入properties文件的扫描,扫描以后,spring容器中就会有一处专门存放a.properties中的键值对-->
    <context:property-placeholder location="classpath:a.properties"></context:property-placeholder>
</beans>

In this way, when the container is scanned, the content in a.properties will be read, and there will be a special place in the container to store the key-value pairs of a.properties. How to assign the key-value pairs to the properties? You can use expressions like ${} to get the variable values ​​of the system or the values ​​in the .properties attribute configuration file

package com.msb.test;

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

/**
 * @Author: zhaoss
 */
@Component
public class Person {
    
    
    @Value("${age}")
    private int age;
    @Value("${name}")
    private String name;

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

Guess you like

Origin blog.csdn.net/qq_27566167/article/details/130405368