Study Notes: Basics of Spring 6 in Shang Silicon Valley

Spring6 chapter

  1. Study notes: Spring 6 basics_ljtxy.love’s blog-CSDN blog
  2. Study Notes: Spring 6 Advanced Chapter_ljtxy.love’s Blog-CSDN Blog

Article directory

1 Overview

Summary of notes:

  1. Meaning: Spring is a mainstream Java EE lightweight open source framework , including Spring MVC, Spring Boot, Spring Cloud, etc.
  2. Function: Simplify the development difficulty and development cycle of Java enterprise-level applications , and provide the ability to integrate other technologies and frameworks
  3. Introduction: The core functions are Inversion of Control (IoC) and Aspect Orientation (AOP)
  4. composition:
    • Spring Core (core container)
    • Spring AOP (Aspect Oriented Programming)
    • Spring **Data Access (**data access)
    • Spring Web (application)
    • Spring Message (message passing)
    • Spring test (test)
  5. Spring Framework
    1. Overview: Spring Framework is the core framework of the Spring project
    2. Role: Spring Framework implements functional modules of IOC container and AOP technology
    3. Features:
      • Non-invasive
      • Inversion of control
      • Aspect Oriented Programming
      • container
      • Componentization
  6. Features:
    • Light: The framework is lightweight and does not rely on other Spring objects.
    • Inversion of Control (IOC): achieves loose coupling between objects
    • Aspect-oriented (AOP): Separating application business logic and system-level services
    • Container: Spring contains and manages the configuration and life cycle of application objects

1.1 Definition

Spring is a mainstream Java EE lightweight open source framework . Due to its portability, ease of use and efficiency, it is widely used in enterprise-level Java application development.

​ Spring contains many sub-frameworks and extensions, such as Spring MVC, Spring Boot, Spring Cloud, etc.

The main features of Spring are IOC containers and AOP technology, which make the development and management of Java applications simpler and more efficient.

1.2 Function

The purpose of Spring is to simplify the development difficulty and development cycle of Java enterprise-level applications. In addition to providing its own functions, the Spring framework also provides the ability to integrate other technologies and frameworks

1.3 Introduction

Since the official release of Spring 1.0 in April 2004, Spring has entered its sixth major version, which is Spring 6.

Insert image description here

illustrate:

​ Reference link: Spring Framework

  • Spring is a lightweight Inversion of Control (IoC) and Aspect-Oriented (AOP) container framework.
  • Spring originally appeared to solve the problems of EJB's bloated design and difficulty in testing.
  • Spring was born to simplify development, allowing programmers to only focus on the implementation of core business and no longer pay attention to non-business logic code (transaction control, security logs, etc.) as much as possible.

1.4 Narrow sense and broad sense

  • Spring in a broad sense: Spring technology stack

​Spring in a broad sense refers to the Spring technology stack with Spring Framework as the core.

After more than ten years of development, Spring is no longer a simple application framework, but has gradually developed into a mature technology composed of multiple different sub-projects (modules), such as Spring Framework, Spring MVC, SpringBoot, Spring Cloud , Spring Data, Spring Security, etc., among which Spring Framework is the basis for other sub-projects.

​ These sub-projects cover everything from enterprise-level application development to cloud computing. They can help developers solve various practical problems that constantly arise during the software development process, and bring developers a better development experience.

  • Spring in a narrow sense: Spring Framework

​ Spring in a narrow sense refers specifically to the Spring Framework, which we usually refer to as the Spring framework.

The Spring Framework is a one-stop lightweight solution for layered, aspect-oriented Java applications. It is the core and foundation of the Spring technology stack and was created to solve the complexity of enterprise-level application development.

Spring has two core modules: IoC and AOP.

  • IoC : Short for Inverse of Control, translated as "inversion of control", which refers to handing over the process of creating objects to Spring for management.
  • AOP : The abbreviation of Aspect Oriented Programming, translated as "aspect-oriented programming". AOP is used to encapsulate the public behaviors of multiple classes and encapsulate the logic that has nothing to do with the business but is commonly called by the business modules, reducing the duplication of code in the system and reducing the coupling between modules. In addition, AOP also solves some system-level problems, such as logs, transactions, permissions, etc.

1.5 Module composition

Insert image description here

illustrate:

The above figure contains all modules of the Spring framework. These modules can meet the needs of all enterprise-level application development. During the development process, the required modules can be selectively used according to needs. The following is a brief introduction to the functions of these modules.

1.5.1 Spring Core (core container)

Spring core provides core implementation of IOC, DI, and Bean configuration loading and creation. Core concepts: Beans, BeanFactory, BeanDefinitions, ApplicationContext.

  • spring-core: basic implementation of IOC and DI

  • spring-beans: BeanFactory and Bean assembly management (BeanFactory)

  • spring-context: Spring context, i.e. IOC container (AppliactionContext)

  • spring-expression: spring expression language

1.5.2Spring AOP (aspect-oriented programming)

  • spring-aop: Aspect programming-oriented application module, integrating ASM, CGLib, JDK Proxy
  • spring-aspects: Integrate AspectJ, AOP application framework
  • spring-instrument: dynamic Class Loading module

1.5.3Spring Data Access (data access)

  • spring-jdbc: spring's encapsulation of JDBC to simplify jdbc operations
  • spring-orm: mapping framework for java objects and database data
  • spring-oxm: a mapping framework for objects and xml files
  • spring-jms: Spring's encapsulation of Java Message Service (java message service), used for mutual communication between services
  • spring-tx: spring jdbc transaction management

1.5.4Spring Web (Application)

  • spring-web: The most basic web support, built on spring-context, initializes the IOC container through servlet or listener
  • spring-webmvc: implement web mvc
  • spring-websocket: full-duplex communication protocol with the front-end
  • spring-webflux: provided by Spring 5.0 to replace traditional java servlets, non-blocking Reactive Web framework, asynchronous, non-blocking, event-driven services

1.5.5Spring Message (message passing)

  • Spring-messaging: provided by spring 4.0, integrating some basic messaging services for Spring

1.5.6Spring test (test)

  • spring-test: Integration testing support, mainly encapsulation of junit

1.6Spring Framework (framework)

1.6.1 Overview

​ Spring Framework is the core framework of the Spring project, and Spring is the general name of the entire Spring project, including Spring Framework and other related sub-projects and extensions

Insert image description here

1.6.2 Function

​ Spring Framework implements functional modules of IOC container and AOP technology

​ Spring Framework contains many modules, such as Core module, Beans module, Context module, AOP module, Web module, etc. Each module provides different functions and can be flexibly selected for use. The goal of Spring Framework is to simplify enterprise-level Java development and improve development efficiency and quality.

1.6.3 Features

  • Non-intrusive : When developing an application using the Spring Framework, Spring has very little impact on the structure of the application itself. Zero pollution can be achieved to the domain model; only a few simple annotations are required to mark the functional components , which will not destroy the original structure at all , but can further simplify the component structure. This makes the structure of developing applications based on the Spring Framework clear, concise and elegant.

  • Inversion of Control : IoC - Inversion of Control, flipping the direction of resource acquisition. We turn creating resources by ourselves and requesting resources from the environment into the environment preparing resources, and we enjoy the injection of resources .

  • Aspect Oriented Programming : AOP - Aspect Oriented Programming, which enhances code functions without modifying the source code .

  • Container : Spring IoC is a container because it contains and manages the life cycle of component objects . Components enjoy containerized management, which shields programmers from a large number of details in the component creation process, greatly lowers the threshold for use, and greatly improves development efficiency.

  • Componentization : Spring enables the use of simple component configurations to combine into a complex application. These objects can be combined in Spring using XML and Java annotations. This allows us to build very large and complex application systems in an orderly manner based on components with clear functions and clear boundaries.

  • One-stop : Based on IoC and AOP, it can integrate open source frameworks and excellent third-party libraries for various enterprise applications . Moreover, Spring's projects have covered a wide range of fields, and many functional requirements can be realized using Spring on the basis of the Spring Framework.

1.7 Features

  1. light
    • Spring is lightweight in terms of both size and overhead . The complete Spring framework can be distributed in a JAR file with a size of just over 1MB. And the processing overhead required by Spring is negligible.
    • Spring is non-intrusive: objects in a Spring application do not depend on Spring-specific classes.
  2. Inversion of control
    • Spring facilitates loose coupling through a technique called Inversion of Control (IoC) . When IoC is applied, other objects that an object depends on are passed in passively, instead of the object itself creating or finding dependent objects. You can think of IoC as the opposite of JNDI - instead of the object looking for dependencies from the container, the container actively passes the dependencies to the object when it is initialized without waiting for the object to request it.
  3. Aspect-oriented
    • Spring provides rich support for aspect-oriented programming, allowing cohesive development by separating application business logic from system-level services such as auditing and transaction management. Application objects only implement what they are supposed to do - complete business logic - nothing more. They are not responsible for (or even aware of) other system-level concerns, such as logging or transaction support.
  4. container
    • Spring contains and manages the configuration and life cycle of application objects . In this sense it is a container and you can configure how each of your beans is created - based on a configurable prototype (prototype), your beans can create a Separate instances or spawning a new instance every time it is needed - and how they are related to each other. However, Spring should not be confused with traditional heavyweight EJB containers, which are often large, cumbersome, and difficult to use.
  5. frame
    • Spring can configure and combine simple components into complex applications . In Spring, application objects are composed declaratively, typically in an XML file. Spring also provides many basic functions (transaction management, persistence framework integration, etc.), leaving the development of application logic to you.

illustrate:

All of these Spring features enable you to write code that is cleaner, more manageable, and easier to test. They also provide basic support for various modules in Spring.

  • Spring6 requires the minimum JDK version to be JDK17

image-20230507141836940

2. Basic use cases - basic use of Spring framework

illustrate:

​ This basic use case demonstrates the automatic injection of beans through XML.

Supplement: environment

  • JDK: Java17+ (Spring6 requires the minimum JDK version to be Java17)

  • Maven:3.6+

  • Spring:6.0.2

Step 1: Building modules

  • Through the Idea development tool, create an empty project and then create a submodule

image-20230507145548414

illustrate:

​ In an empty project, create submodules

Step 2: Import dependencies

  • Modify module pom.xmlfiles
<dependencies>
    <!--spring context依赖-->
    <!--当你引入Spring Context依赖之后,表示将Spring的基础依赖引入了-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>6.0.2</version>
    </dependency>

    <!--junit5测试-->
    <!--此依赖可选,主要便于junit进行测试使用-->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <version>5.3.1</version>
    </dependency>
</dependencies>

illustrate:

​ In the pom.xml file, add the above dependencies

Replenish:

  • After the addition is completed, you can click on the far right side of the IDEA tool Mavento view it.

Insert image description here

Step 3: Create entities

package org.example.entity;

public class User {
    
    
    public void add() {
    
    
        System.out.println("add……");
    }
}

illustrate:

​ Create a User entity under the org.example.entity package

Step 4: Create configuration file

  • resourcesCreate beans.xmla file in the module's directory

illustrate:

​Creating beans.xmlfiles is to complete the automatic injection of dependenciesxml through

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

    <!--id是该bean的唯一标识符,在整个应用程序上下文中用于获取该bean实例-->
    <!--class是该bean所属的Java类的全限定名(包括包名),它告诉Spring需要实例化哪个类-->
    <bean id="user" class="org.example.entity.User"/>
</beans>

illustrate:

  • In the beans, xml file, there is the bean tag
  • In beans and xml files, bean tags have Id attributes and class attributes.

Step 5: Demonstrate

  • Under the package in the module test.java, create UserTestthe class
public class UserTest {
    
    
    @Test
    void newTest() {
    
    
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
        User user = (User) applicationContext.getBean("user");
        user.add(); // add……
    }
}

Replenish:

@TestIt is an annotation in the JUnit framework, indicating that the method is a test method and will be executed by the JUnit framework.

3.Principle

Summary of notes: Basic use case principles for automatic injection of beans through XML

  1. When creating an object, the parameterless constructor is called
  2. Spring creates objects by calling the parameterless constructor through the reflection mechanism.
  3. Objects (Bean objects) created by Spring are eventually stored in the Spring container

1. When creating an object, the no-argument constructor will be called

public class HelloWorld {
    
    
    public HelloWorld() {
    
    
        System.out.println("无参数构造方法执行");
    }
    public void sayHello(){
    
    
        System.out.println("helloworld");
    }
}

illustrate:

Insert image description here

2. Spring creates objects by calling the parameterless constructor through the reflection mechanism.

// dom4j解析beans.xml文件,从中获取class属性值,类的全类名
// 通过反射机制调用无参数构造方法创建对象
Class clazz = Class.forName("com.atguigu.spring6.bean.HelloWorld");
//Object obj = clazz.newInstance();
Object object = clazz.getDeclaredConstructor().newInstance();

3. The object (Bean object) created by Spring is finally stored in the Spring container

private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

illustrate:

  • The bottom layer of the Spring container is a map collection
  • The map of stored beans is in the DefaultListableBeanFactory class
  • When the Spring container loads the Bean class, it will store the description information of the class in the beanDefinitionMap in the form of the package name plus the class name
  • Map<String,BeanDefinition> , where String is the Key, and the first letter of the class name is lowercase by default . BeanDefinition stores the definition ( descriptive information) of the class . We usually call the BeanDefinition interface as: the bean definition object .image-20230507193753242

4. Enable logging framework

Summary of notes:

  1. Overview: Log4j2 is an open source Java logging framework that helps Java developers implement flexible and configurable logging in their applications

  2. composition:

    • Priority of log information: TRACE < DEBUG < INFO < WARN < ERROR < FATAL
    • Output destination of log information : console or local file
    • Output format of log information : display content of log information
  3. Basic use case:

    1. Import dependencies:
    <!--log4j2的依赖-->
    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-core</artifactId>
      <version>2.19.0</version>
    </dependency>
    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-slf4j2-impl</artifactId>
      <version>2.19.0</version>
    </dependency>
    
    1. Create a log configuration file: It is recommended to copy and modify it according to needs

    2. Usage log

    private Logger logger = LoggerFactory.getLogger(HelloWorldTest.class);
    ……
    logger.info("执行成功");
    
    1. result:

      image-20230814214839493

4.1 Overview

Log4j2是一个开源的Java日志框架,是Log4j的升级版。它可以帮助Java开发人员在应用程序中实现灵活和可配置的日志记录,支持异步日志记录、多线程安全等特性

4.2组成

  1. 日志信息的优先级,日志信息的优先级从高到低有TRACE < DEBUG < INFO < WARN < ERROR < FATAL

    说明:

    1. TRACE:追踪,是最低的日志级别,相当于追踪程序的执行
    2. DEBUG:调试,一般在开发中,都将其设置为最低的日志级别
    3. INFO:信息,输出重要的信息,使用较多
    4. WARN:警告,输出警告的信息
    5. ERROR:错误,输出错误信息
    6. FATAL:严重错误
  2. 日志信息的输出目的地,日志信息的输出目的地指定了日志将打印到控制台还是文件中

  3. 日志信息的输出格式,而输出格式则控制了日志信息的显示内容。

4.3基本用例-Log4j2基本使用

步骤一:引入Log4j2依赖

  • 修改模块中的pom.xml文件
<!--log4j2的依赖-->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.19.0</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j2-impl</artifactId>
    <version>2.19.0</version>
</dependency>

说明:

​ log4j的Maven使用光有核心core依赖不够,还需要有实现impl依赖

步骤二:创建日志配置文件

  • 在模块文件路径在resource的根路径下,配置文件名为log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <loggers>
        <!--
            level指定日志级别,从低到高的优先级:
                TRACE < DEBUG < INFO < WARN < ERROR < FATAL
                trace:追踪,是最低的日志级别,相当于追踪程序的执行
                debug:调试,一般在开发中,都将其设置为最低的日志级别
                info:信息,输出重要的信息,使用较多
                warn:警告,输出警告的信息
                error:错误,输出错误信息
                fatal:严重错误
        -->
        <root level="DEBUG">
            <appender-ref ref="spring6log"/>
            <appender-ref ref="RollingFile"/>
            <appender-ref ref="log"/>
        </root>
    </loggers>

    <appenders>
        <!--输出日志信息到控制台-->
        <console name="spring6log" target="SYSTEM_OUT">
            <!--控制日志输出的格式-->
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss SSS} [%t] %-3level %logger{1024} - %msg%n"/>
        </console>

        <!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,适合临时测试用-->
        <File name="log" fileName="d:/spring6_log/test.log" append="false">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
        </File>

        <!-- 这个会打印出所有的信息,
            每次大小超过size,
            则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,
            作为存档-->
        <RollingFile name="RollingFile" fileName="d:/spring6_log/app.log"
                     filePattern="log/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz">
            <PatternLayout pattern="%d{yyyy-MM-dd 'at' HH:mm:ss z} %-5level %class{36} %L %M - %msg%xEx%n"/>
            <SizeBasedTriggeringPolicy size="50MB"/>
            <!-- DefaultRolloverStrategy属性如不设置,
            则默认为最多同一文件夹下7个文件,这里设置了20 -->
            <DefaultRolloverStrategy max="20"/>
        </RollingFile>
    </appenders>
</configuration>

步骤三:日常使用

  • 在日常中,只用log4j2,此处创建HelloWorldTest使用
public class HelloWorldTest {
    
    

    // 1.通过日志工程获取日志对象记录器
    private Logger logger = LoggerFactory.getLogger(HelloWorldTest.class);
 
    @Test
    public void testHelloWorld(){
    
    
        ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
        HelloWorld helloworld = (HelloWorld) ac.getBean("helloWorld");
        helloworld.sayHello();
        // 2.记录日志
        logger.info("执行成功");
    }
}

说明:

​ 创建日志记录器

步骤四:演示

image-20230507195508176

说明:

​ 当完成以上步骤后,运行,日志就会输出在控制台

5.容器:IoC(重点)

笔记小结:见各个小节

5.1概述

笔记小结:

  1. Definition: IoC (Inversion of Control), that is, inversion of control, is a design pattern or design idea
  2. Introduction: Spring manages the instantiation and initialization of all Java objects through the IoC container , and controls the dependencies between objects.
  3. Function: The container is used to manage object creation , destruction, dependency injection and other operations, and the application itself only needs to use these objects.
  4. Dependency injection:
    • Meaning: To decouple dependencies between objects
    • Function: Spring completes Bean management through dependency injection. In other words, dependency injection implements the idea of ​​inversion of control
    • Implementation method (key points):
      1. setter injection
      2. constructor injection
  5. Implement interfaces and common classes:
    • BeanFactory interface: oriented to Spring itself and not provided to developers.
    • ApplicationContext interface: For Spring users, applicable to almost all occasions (creating and managing Bean instances, supporting internationalization, resource access, and message passing)
    • Common categories:
      • FileSystemXmlApplicationContext : Read the XML format configuration file through the file system path to create the IOC container object
      • ClassPathXmlApplicationContext : Create an IOC container object by reading the configuration file in XML format under the class path

5.1.1 Definition

IoC (Inversion of Control) is a design pattern or design idea . It is a concept in object-oriented programming. It is used to describe the dependencies between objects and guide us how to design loose objects. Coupled, better programs.

5.1.2 Introduction

​ Spring manages the instantiation and initialization of all Java objects through the IoC container, and controls the dependencies between objects. We call the Java objects managed by the IoC container Spring Beans, and there is no difference between them and the Java objects created using the keyword new.

5.1.3 Function

​ In the IoC model, control is transferred from the program code to the container , that is, the container is used to manage the creation, destruction, dependency injection and other operations of objects, and the application itself only needs to use these objects. In this way, the application does not need to manage the dependencies between objects by itself , but is managed by the container, thereby achieving code decoupling and better maintainability , and improving program scalability.

illustrate:

  • Hand over the creation rights of objects to third-party containers.
  • Hand over the maintenance rights of objects and relationships between objects to third-party containers.

5.1.4 Dependency injection

5.1.4.1Definition

Dependency Injection (DI) is a design pattern . Its main idea is to dynamically inject dependent objects into the program through an external container (such as Spring container) during the running of the program to decouple the objects. dependencies, thereby improving the flexibility, maintainability and testability of the program.

5.1.4.2 Function

​ **Spring completes Bean management through dependency injection. **In other words, dependency injection implements the idea of ​​inversion of control. Dependency refers to the relationship between objects and objects. Injection refers to a data transfer behavior, which creates a relationship between objects and objects through injection behavior.

Replenish:

Bean management refers to the creation of Bean objects and the assignment of attributes in Bean objects (or the maintenance of relationships between Bean objects).

5.1.4.3 Implementation method

  • The first type: set injection
  • The second type: constructor injection

5.1.5 Implementation

In the Spring framework, the IoC container is implemented through the BeanFactory and ApplicationContext interfaces. The BeanFactory interface is the lowest interface of the Spring framework, providing basic IoC functions; the ApplicationContext interface is a sub-interface of the BeanFactory interface, providing more advanced features and functions, such as AOP, internationalization, event-driven, etc. Among them, the most important method of the BeanFactory interface is the getBean() method, which is used to obtain objects from the container.

​ Spring's IoC container is a practical product implementation of IoC ideas. The components managed in the IoC container are also called beans. Before creating the bean, you first need to create the IoC container. Spring provides two implementations of IoC containers:

  • BeanFactory: This is the basic implementation of the IoC container and the interface used internally by Spring. For Spring itself, not for developers.
  • ApplicationContext: A sub-interface of BeanFactory that provides more advanced features. For Spring users, ApplicationContext is used in almost all situations instead of the underlying BeanFactory.

The main implementation classes of ApplicationContext :

Type name Introduction
ClassPathXmlApplicationContext Create an IOC container object by reading a configuration file in XML format under the classpath
FileSystemXmlApplicationContext Create an IOC container object by reading a configuration file in XML format through a file system path
ConfigurableApplicationContext The sub-interface of ApplicationContext contains some extension methods refresh() and close(), so that ApplicationContext has the ability to start, close and refresh the context.
WebApplicationContext Specially prepared for Web applications, create IOC container objects based on the Web environment, and import and store the objects into the ServletContext domain.

image-20230507205115192

illustrate:

ApplicationContext has many implementation classes, the most commonly used of which are ClassPathXmlApplicationContext and FileSystemXmlApplicationContext implementation classes

5.2 Managing Beans based on XML (understanding)

Summary of notes:

  1. How to get Bean:

    • According to ID :

      User user = (User) applicationContext.getBean("user");
      
    • According to type :

       User user = (User) applicationContext.getBean(User.class);
      
    • According to Id and type :

      User user = (User) applicationContext.getBean("user", User.class);
      
  2. dependency injection

    • Inject according to Setter :<property/>
    • Inject according to constructor :<constructor-arg/>
  3. Special value handling

    • Literal assignment<property>
    • Null value<null>
    • Xml entity : attribute valuevalue="a &lt; b"
    • CDATA section : tag content<![CDATA[a < b]]>
  4. Inject object type attribute value

    1. Reference to external bean : propertiesref
    2. Reference to internal beans : bean nesting
    3. Cascade attribute assignment : After introducing the object, cascade assignmentname="clazz.clazzId"
  5. Inject array type attribute value:<array></array>

  6. Inject collection type attribute values:

    1. Inject List collection type attribute value: <list> </list>
    2. Inject Map collection type attribute value:<map><entry><<key>/key><value></value></entry></map>
    3. Inject reference collection type attribute value:<util></util>
      • Note: Before use, you need to introduce the util namespace
  7. Introduce P namespace attribute value: attributep:

    • Note: Before use, you need to introduce the p namespace
  8. Introduce external properties file:<context:property-placeholder location="classpath:jdbc.properties"/>

  9. Introducing the scope of Bean : attribute scopeattribute valueprototype(多例)、singleton(单例)

  10. Bean life cycle:

    1. Bean object creation (calling the parameterless constructor)

    2. bean object setting properties

    3. bean postprocessor (before initialization)

    4. Bean object initialization (need to specify the initialization method when configuring the bean)

    5. Bean postprocessor (after initialization)

    6. The bean object is ready for use

    7. Bean object destruction (need to specify the destruction method when configuring the bean)

    8. IOC container closed

  11. Introducing FactoryBean attribute values: implementing FactoryBean<T>the interface

  12. Introducing autowiring : attribute value autowireattribute valuebyType、byName

5.2.1 How to obtain Bean

5.2.1.1 Obtain Bean based on ID

public class UserTest {
    
    
    @Test
    void newTest() {
    
    
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
        User user = (User) applicationContext.getBean("user");
        user.add(); // add……
    }
}

illustrate:

​ This acquisition method needs to be viewed based on the basic use case in Section 2.

5.2.1.2 Obtain Bean according to type

public class UserTest {
    
    
    @Test
    void newTest() {
    
    
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
        User user = (User) applicationContext.getBean(User.class);
        user.add(); // add……
    }
}

Notice:

  • When obtaining a bean based on its type, it is required that there be only one bean of the specified type in the IOC container.

  • org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.atguigu.spring6.bean.HelloWorld' available: expected single matching bean but found 2: helloworldOne,helloworldTwo
    

illustrate:

​ This acquisition method needs to be viewed based on the basic use case in Section 2.

5.2.1.3 Obtain Bean based on Id and type

public class UserTest {
    
    
    @Test
    void newTest() {
    
    
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
        User user = (User) applicationContext.getBean("user", User.class);
        user.add(); // add……
    }
}

Replenish:

​ If the component class implements an interface, you can obtain the Bean based on the interface type, but the premise is that the Bean is unique

illustrate:

​ This acquisition method needs to be viewed based on the basic use case in Section 2.

5.2.2 Dependency injection

5.2.2.1 Injection based on setter

Step 1: Create the student class Student

package com.atguigu.spring6.bean;

public class Student {
    
    

    private Integer id;

    private String name;

    private Integer age;

    private String sex;

    public Student() {
    
    
    }

    public Integer getId() {
    
    
        return id;
    }

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

    public String getName() {
    
    
        return name;
    }

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

    public Integer getAge() {
    
    
        return age;
    }

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

    public String getSex() {
    
    
        return sex;
    }

    public void setSex(String sex) {
    
    
        this.sex = sex;
    }

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

}

Step 2: Assign values ​​to properties when configuring the bean

<bean id="studentOne" class="com.atguigu.spring6.bean.Student">
    <!-- property标签:通过组件类的setXxx()方法给组件对象设置属性 -->
    <!-- name属性:指定属性名(这个属性名是getXxx()、setXxx()方法定义的,和成员变量无关) -->
    <!-- value属性:指定属性值 -->
    <property name="id" value="1001"></property>
    <property name="name" value="张三"></property>
    <property name="age" value="23"></property>
    <property name="sex" value=""></property>
</bean>

illustrate:

​ When using label tags to complete object attribute creation, the name needs to have the same name as the member variable in the object.

Step 3: Demo

@Test
public void testDIBySet(){
    
    
    ApplicationContext ac = new ClassPathXmlApplicationContext("spring-di.xml");
    Student studentOne = ac.getBean("studentOne", Student.class);
    System.out.println(studentOne);
}

illustrate:

​ When printing the output, since the object is created based on XML and Setter injection, the output can obtain the content of the member method tostring.

5.2.2.2 Injection based on constructor

Step 1: Based on setter injection, add a parameterized construct to the Student class

public Student(Integer id, String name, Integer age, String sex) {
    
    
    this.id = id;
    this.name = name;
    this.age = age;
    this.sex = sex;
}

Step 2: Configure beans

<bean id="studentTwo" class="com.atguigu.spring6.bean.Student">
    <constructor-arg name="id" value="1002"></constructor-arg>
    <constructor-arg name="name" value="李四"></constructor-arg>
    <constructor-arg name="age"value="33"></constructor-arg>
    <constructor-arg name="sex" value=""></constructor-arg>
</bean>

illustrate:

  • The constructor-arg tag attribute describes the constructor parameters:
    • Index attribute: Specifies the index of the parameter location (starting from 0)
    • name attribute: Specify the parameter name. The name must have the same name as the member variable in the object.

Step 3: Demo

@Test
public void testDIByConstructor(){
    
    
    ApplicationContext ac = new ClassPathXmlApplicationContext("spring-di.xml");
    Student studentOne = ac.getBean("studentTwo", Student.class);
    System.out.println(studentOne);
}

illustrate:

​ When printing the output, since the object is created based on XML according to the constructor injection method, the output can obtain the content of the member method tostring.

5.2.3 Special value processing

5.2.3.1 Literal assignment

<!-- 使用value属性给bean的属性赋值时,Spring会把value属性的值看做字面量 -->
<property name="name" value="张三"/>

5.2.3.2null value

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

detail:

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

In the above writing method, the value assigned to name is the string null.

5.2.3.3xml entity

<!-- 解决方案一:使用XML实体来代替 -->
<property name="expression" value="a &lt; b"/>

illustrate:

​ The less than sign is used to define the beginning of tags in XML documents and cannot be used casually.

5.2.3.4CDATA section

<property name="expression">
    <!-- 解决方案二:使用CDATA节 -->
    <value><![CDATA[a < b]]></value>
</property>

illustrate:

  • The C in CDATA represents Character, which means text and characters. CDATA represents plain text data.
  • When the ML parser sees the CDATA section, it knows it is plain text and will not parse it as an XML tag or attribute.
  • So you can write whatever symbols you want in the CDATA section.

5.2.4 Injecting object type attribute values

5.2.4.1Referencing external beans

Step 1: Configure Clazz type beans

<bean id="clazzOne" class="com.atguigu.spring6.bean.Clazz">
    <property name="clazzId" value="1111"></property>
    <property name="clazzName" value="财源滚滚班"></property>
</bean>

Step 2: Assign a value to the clazz attribute in Student

<bean id="studentFour" class="com.atguigu.spring6.bean.Student">
    <property name="id" value="1004"></property>
    <property name="name" value="赵六"></property>
    <property name="age" value="26"></property>
    <property name="sex" value=""></property>
    <!-- ref属性:引用IOC容器中某个bean的id,将所对应的bean为属性赋值 -->
    <property name="clazz" ref="clazzOne"></property>
</bean>

illustrate:

When referencing an external object, you need to change the ref attribute to the Value attribute. ref attribute, the value represents the reference object, the value attribute, the value represents the string

5.2.4.2 Reference to internal beans

Step 1: Based on referencing external beans

<bean id="studentFour" class="com.atguigu.spring6.bean.Student">
    <property name="id" value="1004"></property>
    <property name="name" value="赵六"></property>
    <property name="age" value="26"></property>
    <property name="sex" value=""></property>
    <property name="clazz">
        <!-- 在一个bean中再声明一个bean就是内部bean -->
        <!-- 内部bean只能用于给属性赋值,不能在外部通过IOC容器获取,因此可以省略id属性 -->
        <bean id="clazzInner" class="com.atguigu.spring6.bean.Clazz">
            <property name="clazzId" value="2222"></property>
            <property name="clazzName" value="远大前程班"></property>
        </bean>
    </property>
</bean>

illustrate:

​Writing the Bean in the attribute tag refers to the internal Bean.

5.2.4.3 Cascading attribute assignment

Step 1: Based on referencing internal beans

<bean id="studentFour" class="com.atguigu.spring6.bean.Student">
    <property name="id" value="1004"></property>
    <property name="name" value="赵六"></property>
    <property name="age" value="26"></property>
    <property name="sex" value=""></property>
    <property name="clazz" ref="clazzOne"></property>
    <property name="clazz.clazzId" value="3333"></property>
    <property name="clazz.clazzName" value="最强王者班"></property>
</bean>

5.2.5 Injecting array type attribute values

Step 1: Add member variable array and getter to setter method in Student class

private String[] hobbies;

public String[] getHobbies() {
    
    
    return hobbies;
}

public void setHobbies(String[] hobbies) {
    
    
    this.hobbies = hobbies;
}

Step 2: Configure Bean

<bean id="studentFour" class="com.atguigu.spring.bean6.Student">
    <property name="id" value="1004"></property>
    <property name="name" value="赵六"></property>
    <property name="age" value="26"></property>
    <property name="sex" value=""></property>
    <!-- ref属性:引用IOC容器中某个bean的id,将所对应的bean为属性赋值 -->
    <property name="clazz" ref="clazzOne"></property>
    <property name="hobbies">
        <array>
            <value>抽烟</value>
            <value>喝酒</value>
            <value>烫头</value>
        </array>
    </property>
</bean>

illustrate:

​ When injecting array type data, you need to use tags

5.2.6 Injecting collection type attribute values

5.2.6.1 Inject List collection type attribute value

Step 1: Add member variable collection and getter to setter method in Clazz class

private List<Student> students;

public List<Student> getStudents() {
    
    
    return students;
}

public void setStudents(List<Student> students) {
    
    
    this.students = students;
}

Step 2: Configure Bean

<bean id="clazzTwo" class="com.atguigu.spring6.bean.Clazz">
    <property name="clazzId" value="4444"></property>
    <property name="clazzName" value="Javaee0222"></property>
    <property name="students">
        <list>
            <ref bean="studentOne"></ref>
            <ref bean="studentTwo"></ref>
            <ref bean="studentThree"></ref>
        </list>
    </property>
</bean>

illustrate:

When injecting List collection type data, you need to use tags

detail:

​ Because List students, the List collection refers to the Student object, so you need to use tags to reference the object when injecting.

5.2.6.2 Injecting Map collection type attribute values

Step 1: Create Student class

package com.atguigu.spring6.bean;
public class Teacher {
    
    

    private Integer teacherId;

    private String teacherName;

    public Integer getTeacherId() {
    
    
        return teacherId;
    }

    public void setTeacherId(Integer teacherId) {
    
    
        this.teacherId = teacherId;
    }

    public String getTeacherName() {
    
    
        return teacherName;
    }

    public void setTeacherName(String teacherName) {
    
    
        this.teacherName = teacherName;
    }

    public Teacher(Integer teacherId, String teacherName) {
    
    
        this.teacherId = teacherId;
        this.teacherName = teacherName;
    }

    public Teacher() {
    
    

    }
    
    @Override
    public String toString() {
    
    
        return "Teacher{" +
                "teacherId=" + teacherId +
                ", teacherName='" + teacherName + '\'' +
                '}';
    }
}

Step 2: Add member variable collection and getter to setter methods in the Student class

private Map<String, Teacher> teacherMap;

public Map<String, Teacher> getTeacherMap() {
    
    
    return teacherMap;
}

public void setTeacherMap(Map<String, Teacher> teacherMap) {
    
    
    this.teacherMap = teacherMap;
}

Step 3: Configure beans

<bean id="teacherOne" class="com.atguigu.spring6.bean.Teacher">
    <property name="teacherId" value="10010"></property>
    <property name="teacherName" value="大宝"></property>
</bean>

<bean id="teacherTwo" class="com.atguigu.spring6.bean.Teacher">
    <property name="teacherId" value="10086"></property>
    <property name="teacherName" value="二宝"></property>
</bean>

<bean id="studentFour" class="com.atguigu.spring6.bean.Student">
    <property name="id" value="1004"></property>
    <property name="name" value="赵六"></property>
    <property name="age" value="26"></property>
    <property name="sex" value=""></property>
    <!-- ref属性:引用IOC容器中某个bean的id,将所对应的bean为属性赋值 -->
    <property name="clazz" ref="clazzOne"></property>
    <property name="hobbies">
        <array>
            <value>抽烟</value>
            <value>喝酒</value>
            <value>烫头</value>
        </array>
    </property>
    <property name="teacherMap">
        <map>
            <entry>
                <key>
                    <value>10010</value>
                </key>
                <ref bean="teacherOne"></ref>
            </entry>
            <entry>
                <key>
                    <value>10086</value>
                </key>
                <ref bean="teacherTwo"></ref>
            </entry>
        </map>
    </property>
</bean>

illustrate:

  • When injecting Map collection type data, you need to use tags
  • Need to use key-value pairs
  • Need to use presentation key

detail:

​ Because Map<String, Teacher> teacherMap, the Teacher object is referenced in the Map collection, so you need to use a label to reference the object when injecting

5.2.6.2 Injecting reference collection type attribute values

Step 1: Configure the corresponding namespace

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

Step 2: Configure Bean

<!--list集合类型的bean-->
<util:list id="students">
    <ref bean="studentOne"></ref>
    <ref bean="studentTwo"></ref>
    <ref bean="studentThree"></ref>
</util:list>
<!--map集合类型的bean-->
<util:map id="teacherMap">
    <entry>
        <key>
            <value>10010</value>
        </key>
        <ref bean="teacherOne"></ref>
    </entry>
    <entry>
        <key>
            <value>10086</value>
        </key>
        <ref bean="teacherTwo"></ref>
    </entry>
</util:map>
<bean id="clazzTwo" class="com.atguigu.spring6.bean.Clazz">
    <property name="clazzId" value="4444"></property>
    <property name="clazzName" value="Javaee0222"></property>
    <property name="students" ref="students"></property>
</bean>
<bean id="studentFour" class="com.atguigu.spring6.bean.Student">
    <property name="id" value="1004"></property>
    <property name="name" value="赵六"></property>
    <property name="age" value="26"></property>
    <property name="sex" value=""></property>
    <!-- ref属性:引用IOC容器中某个bean的id,将所对应的bean为属性赋值 -->
    <property name="clazz" ref="clazzOne"></property>
    <property name="hobbies">
        <array>
            <value>抽烟</value>
            <value>喝酒</value>
            <value>烫头</value>
        </array>
    </property>
    <property name="teacherMap" ref="teacherMap"></property>
</bean>

illustrate:

  • Using tags, you can inject the properties of the List collection or Map collection into references
  • When using the util tag, you need to introduce the corresponding namespace

5.2.7 Introduction of P namespace attribute value

Step 1: Introduce the P namespace

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

Step 2: Assign values ​​to each attribute of the bean through the p namespace

<bean id="studentSix" class="com.atguigu.spring6.bean.Student"
    p:id="1006" p:name="小明" p:clazz-ref="clazzOne" p:teacherMap-ref="teacherMap"></bean>

illustrate:

​ Pass p:成员属性, you can complete the assignment of each attribute.

5.2.8 Introduction of external property files

Step 1: Add dependencies

 <!-- MySQL驱动 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.30</version>
</dependency>

<!-- 数据源 -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.2.15</version>
</dependency>

Step 2: Create an external properties file

jdbc.user=root
jdbc.password=atguigu
jdbc.url=jdbc:mysql://localhost:3306/ssm?serverTimezone=UTC
jdbc.driver=com.mysql.cj.jdbc.Driver

illustrate:

​Create the jdbc.properties file under the resources file

Step 3: Import the properties file

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context.xsd">
    <!-- 引入外部属性文件 -->
    <context:property-placeholder location="classpath:jdbc.properties"/>
</beans>

Notice:

Before using the element to load the outsourcing configuration file function, you first need to add context- related constraints <context:property-placeholder> in the first-level tag of the XML configuration .

Step 4: Configure Bean

<!--完成数据库信息注入-->
<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="url" value="${jdbc.url}"/>
    <property name="driverClassName" value="${jdbc.driver}"/>
    <property name="username" value="${jdbc.user}"/>
    <property name="password" value="${jdbc.password}"/>
</bean>

illustrate:

​ When getting the value in the external file, you need to get the corresponding value based on the name of the attribute in the external file.

Step 5: Demonstrate

@Test
public void testDataSource() throws SQLException {
    
    
    ApplicationContext ac = new ClassPathXmlApplicationContext("spring-datasource.xml");
    DataSource dataSource = ac.getBean(DruidDataSource.class);
    Connection connection = dataSource.getConnection();
    System.out.println(connection);
}

5.2.9 Introducing Bean scope

Step 1: Create a class User

package com.atguigu.spring6.bean;
public class User {
    
    

    private Integer id;

    private String username;

    private String password;

    private Integer age;

    public User() {
    
    
    }

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

    public Integer getId() {
    
    
        return id;
    }

    public void setId(Integer 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 Integer getAge() {
    
    
        return age;
    }

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

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

Step 2: Configure beans

<!-- scope属性:取值singleton(默认值),bean在IOC容器中只有一个实例,IOC容器初始化时创建对象 -->
<!-- scope属性:取值prototype,bean在IOC容器中可以有多个实例,getBean()时创建对象 -->
<bean class="com.atguigu.spring6.bean.User" scope="prototype"></bean>

illustrate:

  • Property value:
    • singleton (default). In the IOC container, the object of this bean is always a single instance. The object can be created when the IOC container is initialized.
    • prototype, in the IOC container, this bean has multiple instances in the IOC container, and objects can be created when the bean is obtained.

Step 3: Demo

@Test
public void testBeanScope(){
    
    
    ApplicationContext ac = new ClassPathXmlApplicationContext("spring-scope.xml");
    User user1 = ac.getBean(User.class);
    User user2 = ac.getBean(User.class);
    System.out.println(user1==user2);
}

5.2.10Bean life cycle

process

  1. Bean object creation (calling the parameterless constructor)

  2. bean object setting properties

  3. bean postprocessor (before initialization)

  4. Bean object initialization (need to specify the initialization method when configuring the bean)

  5. Bean postprocessor (after initialization)

  6. The bean object is ready for use

  7. Bean object destruction (need to specify the destruction method when configuring the bean)

  8. IOC container closed

Step 1: Modify the User class

public class User {
    
    

    private Integer id;

    private String username;

    private String password;

    private Integer age;

    public User() {
    
    
        System.out.println("生命周期:1、创建对象");
    }

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

    public Integer getId() {
    
    
        return id;
    }

    public void setId(Integer id) {
    
    
        System.out.println("生命周期:2、依赖注入");
        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 Integer getAge() {
    
    
        return age;
    }

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

    public void initMethod(){
    
    
        System.out.println("生命周期:3、初始化");
    }

    public void destroyMethod(){
    
    
        System.out.println("生命周期:5、销毁");
    }

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

illustrate:

Among them, initMethod() and destroyMethod() can be specified as initialization and destruction methods by configuring the Bean.

Step 2: Create a Bean Post-Processor

package com.atguigu.spring6.process;
    
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

public class MyBeanProcessor implements BeanPostProcessor {
    
    
    
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    
    
        System.out.println("☆☆☆" + beanName + " = " + bean);
        return bean;
    }
    
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    
    
        System.out.println("★★★" + beanName + " = " + bean);
        return bean;
    }
}

Notice:

​ The post-processor of the bean will add additional operations before and after the initialization of the life cycle. It needs to implement the BeanPostProcessor interface and configure it in the IOC container. It should be noted that the post-processor of the bean does not take effect only for a certain bean, but It will be executed for all beans in the IOC container

Step 3: Configure Bean

<!-- 使用init-method属性指定初始化方法 -->
<!-- 使用destroy-method属性指定销毁方法 -->
<bean class="com.atguigu.spring6.bean.User" scope="prototype" init-method="initMethod" destroy-method="destroyMethod">
    <property name="id" value="1001"></property>
    <property name="username" value="admin"></property>
    <property name="password" value="123456"></property>
    <property name="age" value="23"></property>
</bean>
<!-- bean的后置处理器要放入IOC容器才能生效 -->
<bean id="myBeanProcessor" class="com.atguigu.spring6.process.MyBeanProcessor"/>

illustrate:

  • When configuring a Bean, you need to use the init-method attribute and destroy-method attribute to configure the Bean's initialization method and destruction method.
  • When configuring a bean, you need to put the bean's post-processor into the IOC container to take effect.

Step 4: Demonstrate

@Test
public void testLife(){
    
    
    ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("spring-lifecycle.xml");
    User bean = ac.getBean(User.class);
    System.out.println("生命周期:4、通过IOC容器获取bean并使用");
    ac.close();
}

5.2.11 Introducing FactoryBean property values

Insert image description here

illustrate:

FactoryBean is a common mechanism provided by Spring for integrating third-party frameworks. Different from ordinary beans, when you configure a FactoryBean type bean, what you get when you get the bean is not the object of the class configured in the class attribute, but the return value of the getObject() method. Through this mechanism, Spring can help us shield the detailed process and tedious details of creating complex components, and only show us the simplest user interface.

Step 1: Create class UserFactoryBean

package com.atguigu.spring6.bean;
public class UserFactoryBean implements FactoryBean<User> {
    
    
    @Override
    public User getObject() throws Exception {
    
    
        return new User();
    }

    @Override
    public Class<?> getObjectType() {
    
    
        return User.class;
    }
}

Step 2: Configure beans

<bean id="user" class="com.atguigu.spring6.bean.UserFactoryBean"></bean>

Step 3: Demo

@Test
public void testUserFactoryBean(){
    
    
    //获取IOC容器
    ApplicationContext ac = new ClassPathXmlApplicationContext("spring-factorybean.xml");
    User user = (User) ac.getBean("user");
    System.out.println(user);
}

illustrate:

​ The container object obtained at this time is not UserFactoryBean, but User

5.2.12 Introduction of xml automatic assembly

Step 1: Environment preparation

1.Create the UserController class

package com.atguigu.spring6.autowire.controller
public class UserController {
    
    

    private UserService userService;

    public void setUserService(UserService userService) {
    
    
        this.userService = userService;
    }

    public void saveUser(){
    
    
        userService.saveUser();
    }

}

2. Create UserService interface

package com.atguigu.spring6.autowire.service
public interface UserService {
    
    

    void saveUser();

}

3. Create a UserServiceImpl class to implement the UserService interface

package com.atguigu.spring6.autowire.service.impl
public class UserServiceImpl implements UserService {
    
    

    private UserDao userDao;

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

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

}

4. Create UserDao interface

package com.atguigu.spring6.autowire.dao
public interface UserDao {
    
    

    void saveUser();

}

5. Create the UserDaoImpl class to implement the UserDao interface

package com.atguigu.spring6.autowire.dao.impl
public class UserDaoImpl implements UserDao {
    
    

    @Override
    public void saveUser() {
    
    
        System.out.println("保存成功");
    }

}

Step 2: Configure beans

<bean id="userController" class="com.atguigu.spring6.autowire.controller.UserController" autowire="byType"></bean>

<bean id="userService" class="com.atguigu.spring6.autowire.service.impl.UserServiceImpl" autowire="byType"></bean>

<bean id="userDao" class="com.atguigu.spring6.autowire.dao.impl.UserDaoImpl"></bean>

illustrate:

  • When using the autowire attribute of the Bean tag, it is automatically assembled by byType
  • byType: matches a bean of a compatible type in the IOC container according to the type, and automatically assigns values ​​to the properties
    • If in the IOC, no bean of a compatible type can assign a value to the property, the property will not be assembled , that is, the value will be the default value null.
    • If there are multiple beans of compatible types that can assign values ​​to properties in the IOC , the exception NoUniqueBeanDefinitionException will be thrown.
  • byName: Use the attribute name of the automatically assembled attribute as the bean id to match the corresponding bean in the IOC container for assignment.

Step 3: Demo

@Test
public void testAutoWireByXML(){
    
    
    ApplicationContext ac = new ClassPathXmlApplicationContext("autowire-xml.xml");
    UserController userController = ac.getBean(UserController.class);
    userController.saveUser();
}

illustrate:

​ When using attributes in tags, use the Autowire attribute and byType to achieve automatic injection of attributes.

5.3 Managing Beans based on annotations (key points)

Summary of notes:

  1. Overview:

    • Introduction: Java has added support for annotation , which is a special mark in the code that can be read during compilation, class loading and runtime , and performs corresponding processing.
    • Use annotations:
      1. @Component: represents a generalized component
      2. @Repository: Represents the data access layer component
      3. @Service: Represents business layer components
      4. @Controller:: represents the control layer component
  2. Turn on component scanning

    1. Overview: Enable<context:component-scan> the automatic scanning function of Spring Beans through elements . Spring will automatically scan all classes under the specified package (base-package attribute setting) and its sub-packages. If the @Component annotation is used on the class, the class will be assembled into the container.
    2. Basic use case: using tags<context:component-scan></context:component-scan>
      1. Add conentt constraints
      2. Enable scanning mode
    3. Specify components to exclude : <context:exclude-filter></context:exclude-filter>
    4. Scan only specified components: <context:include-filter></context:include-filter
  3. Define beans using annotations

    1. Use @Autowiredinjection:

      • Property injection

        @Autowired
        private UserDao userDao;
        
      • setter injection

        private UserDao userDao;
        @Autowired
        public void setUserDao(UserDao userDao) {
                   
                   
            this.userDao = userDao;
        }
        
      • Constructor injection

        private UserDao userDao;
        @Autowired
        public UserServiceImpl(UserDao userDao) {
                   
                   
        	this.userDao = userDao;
        }
        
      • Parameter injection

        private UserDao userDao;
        public UserServiceImpl(@Autowired UserDao userDao) {
                   
                   
            this.userDao = userDao;
        }
        
      • Annotation-free injection: When the constructor has only one construction parameter that needs to be injected , @Autowired can be omitted

        private UserDao userDao;
        public UserServiceImpl(UserDao userDao) {
                   
                   
            this.userDao = userDao;
        }
        
      • Joint **@Qualifier annotation injection: annotation differences applicable to multiple implementation classes of an interface**

        @Autowired
        @Qualifier("userDaoImpl") // 指定bean的名字
        private UserDao userDao;
        
    2. Use @Resourceinjection:

      • Name injection: When using annotations, configure the name attribute

        @Resource(name = "myUserDao")
        
      • Unknown Name injection: do not configure the name attribute, inject the member variables of the attribute but need to have the same name as the name of the Bean

        @Repository("myUserDao")
        public class UserDaoImpl implements UserDao {
                   
                   
            ……
        @Resource
        private UserDao myUserDao;
        
      • Type injection: When the name attribute is not configured and the names are different, the member type of the injected attribute will be matched according to the interface type implemented by the bean

        @Repository("myUserDao")
        public class UserDaoImpl implements UserDao {
                   
                   
            ……
        @Resource
        private UserDao userDao1;
        
  4. Full annotation development: no longer use spring configuration files, write a configuration class to replace the configuration file

    @Configuration
    //@ComponentScan({"com.atguigu.spring6.controller", "com.atguigu.spring6.service","com.atguigu.spring6.dao"})
    @ComponentScan("com.atguigu.spring6") //开启包扫描
    public class Spring6Config {
           
           
    }
    

    Note: When using the full annotation development method, you need to specify the scope of the package scan , so that the Spring framework can determine the scope of scanning and injecting beans.

5.3.1 Overview

5.3.1.1 Introduction

Starting from Java 5, Java has added support for annotation, which is a special mark in the code that can be read during compilation, class loading and runtime, and perform corresponding processing. Developers can embed supplementary information in source code without changing the original code and logic through annotations.

​ Spring has provided comprehensive support for annotation technology since version 2.5. We can use annotations to implement automatic assembly and simplify Spring's XML configuration.

5.3.1.2 Steps

  1. Introduce dependencies
  2. Turn on component scanning
  3. Define beans using annotations
  4. dependency injection

5.3.1.3 Using annotations

​ Spring provides the following annotations, which can be directly annotated on Java classes and defined as Spring Beans.

annotation illustrate
@Component This annotation is used to describe Bean in Spring. It is a general concept that only represents a component (Bean) in the container , and can be used at any level of the application, such as Service layer, Dao layer, etc. When using it, you only need to mark the annotation on the corresponding class.
@Repository This annotation is used to identify the class of the data access layer (Dao layer) as a bean in Spring, and its function is the same as @Component.
@Service This annotation usually acts on the business layer (Service layer), and is used to identify the class of the business layer as a bean in Spring, and its function is the same as that of @Component.
@Controller This annotation usually acts on the control layer (such as SpringMVC's Controller) and is used to identify the class of the control layer as a Bean in Spring. Its function is the same as @Component.

5.3.2 Turn on component scanning

5.3.2.1 Overview

​ Spring does not use annotations to assemble beans by default, so we need to enable<context:component-scan> the automatic scanning function of Spring Beans through elements in Spring's XML configuration . After turning on this function, Spring will automatically scan all classes under the specified package (base-package attribute setting) and its sub-packages. If the @Component annotation is used on the class, the class will be assembled into the container.

5.3.2.2 Basic use case-implementing component scanning

Step 1: Add constraints

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

illustrate:

​ Add context-related constraints in the first-level tag of the XML configuration

Step 2: Turn on scanning mode

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

illustrate:

​ In the Beans.xml file, set the scanning method to open.

5.3.2.3 Specify components to exclude

<context:component-scan base-package="com.atguigu.spring6">
    <!-- context:exclude-filter标签:指定排除规则 -->
    <!-- 
 		type:设置排除或包含的依据
		type="annotation",根据注解排除,expression中设置要排除的注解的全类名
		type="assignable",根据类型排除,expression中设置要排除的类型的全类名
	-->
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        <!--<context:exclude-filter type="assignable" expression="com.atguigu.spring6.controller.UserController"/>-->
</context:component-scan>

illustrate:

  1. <context:exclude-filter></context:exclude-filter>Label, specify exclusion rules
    • type attribute: Set the basis for exclusion or inclusion
      • Attribute value: annotation, excluded based on annotation
      • Attribute value: assignable, excluded based on type
    • expression attribute: Set the full class name of the annotation or type to be excluded

5.3.2.4 Scan only specified components

<context:component-scan base-package="com.atguigu" use-default-filters="false">
    <!-- context:include-filter标签:指定在原有扫描规则的基础上追加的规则 -->
    <!-- use-default-filters属性:取值false表示关闭默认扫描规则 -->
    <!-- 此时必须设置use-default-filters="false",因为默认规则即扫描指定包下所有类 -->
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    <!--<context:include-filter type="assignable" expression="com.atguigu.spring6.controller.UserController"/>-->
</context:component-scan>

illustrate:

  1. use-default-filters="false", indicating to turn off the default scanning rules
  2. <context:include-filter></context:include-filter>, indicating the specified filter criteria to determine which classes should be included in the component scan

5.3.2 Define Beans using annotations

5.3.3 Injection using @Autowired

5.3.3.1 Overview

Insert image description here

illustrate:

  1. @Autowired annotations can be marked on: construction methods, methods, formal parameters, properties, annotations
  2. required attribute of @Autowired annotation,
    • The attribute value is True: it means that the injected Bean must exist when injecting, and an error will be reported if it does not exist
    • The attribute value is False: Indicates that the bean required to be injected does not necessarily exist during injection. If it exists, it will be injected. If it does not exist, no error will be reported.

detail:

  1. When the @Autowired annotation is used alone, the default is to assemble based on the type , and the default is "byType", such as managing beans based on XML.
<bean id="userService" class="com.atguigu.spring6.autowire.service.impl.UserServiceImpl" autowire="byType"></bean>

5.3.3.2 Attribute injection

Step 1: Set up the environment

1. Create UserDao interface

package com.atguigu.spring6.dao;

public interface UserDao {
    
    

    public void print();
}

2. Create UserDaoImpl implementation

package com.atguigu.spring6.dao.impl;

import com.atguigu.spring6.dao.UserDao;
import org.springframework.stereotype.Repository;

@Repository
public class UserDaoImpl implements UserDao {
    
    

    @Override
    public void print() {
    
    
        System.out.println("Dao层执行结束");
    }
}

3. Create UserService interface

package com.atguigu.spring6.service;

public interface UserService {
    
    

    public void out();
}

4. Create UserServiceImpl implementation class

package com.atguigu.spring6.service.impl;

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

@Service
public class UserServiceImpl implements UserService {
    
    

    @Autowired
    private UserDao userDao;

    @Override
    public void out() {
    
    
        userDao.print();
        System.out.println("Service层执行结束");
    }
}

5. Create UserController class

package com.atguigu.spring6.controller;

import com.atguigu.spring6.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller
public class UserController {
    
    

    @Autowired
    private UserService userService;

    public void out() {
    
    
        userService.out();
        System.out.println("Controller层执行结束。");
    }
}

Step 2: Demonstration

@Test
public void testAnnotation(){
    
    
    ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
    UserController userController = context.getBean("userController", UserController.class);
    userController.out();
}

illustrate:

  1. When using the @Autowired annotation to inject, you can inject successfully without providing a constructor or a Setter method
  2. result:image-20230512102218784

5.3.3.3set injection

Step 1: Set up the environment

1. Modify the UserServiceImpl class

@Service
public class UserServiceImpl implements UserService {
    
    

    private UserDao userDao;

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

    @Override
    public void out() {
    
    
        userDao.print();
        System.out.println("Service层执行结束");
    }
}

2. Modify the UserController class

@Controller
public class UserController {
    
    

    private UserService userService;

    @Autowired
    public void setUserService(UserService userService) {
    
    
        this.userService = userService;
    }

    public void out() {
    
    
        userService.out();
        System.out.println("Controller层执行结束。");
    }

}

Step 2: Demonstration

@Test
public void testAnnotation(){
    
    
    ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
    UserController userController = context.getBean("userController", UserController.class);
    userController.out();
}

illustrate:

​ By adding the @Autowired annotation on the setter method that needs to be injected

5.3.3.4 Constructor injection

Step 1: Set up the environment

1. Modify the UserServiceImpl class

@Service
public class UserServiceImpl implements UserService {
    
    

    private UserDao userDao;

    @Autowired
    public UserServiceImpl(UserDao userDao) {
    
    
        this.userDao = userDao;
    }

    @Override
    public void out() {
    
    
        userDao.print();
        System.out.println("Service层执行结束");
    }
}

2. Modify the UserController class

@Controller
public class UserController {
    
    

    private UserService userService;

    @Autowired
    public UserController(UserService userService) {
    
    
        this.userService = userService;
    }

    public void out() {
    
    
        userService.out();
        System.out.println("Controller层执行结束。");
    }

}

Step 2: Demonstration

@Test
public void testAnnotation(){
    
    
    ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
    UserController userController = context.getBean("userController", UserController.class);
    userController.out();
}

illustrate:

By adding @Autowired annotation to the constructor method that needs to be injected

5.3.3.5 Formal parameter injection

Step 1: Set up the environment

1. Modify the UserServiceImpl class

@Service
public class UserServiceImpl implements UserService {
    
    

    private UserDao userDao;

    public UserServiceImpl(@Autowired UserDao userDao) {
    
    
        this.userDao = userDao;
    }

    @Override
    public void out() {
    
    
        userDao.print();
        System.out.println("Service层执行结束");
    }
}

2. Modify the UserController class

@Controller
public class UserController {
    
    

    private UserService userService;

    public UserController(@Autowired UserService userService) {
    
    
        this.userService = userService;
    }

    public void out() {
    
    
        userService.out();
        System.out.println("Controller层执行结束。");
    }
}

Step 2: Demonstration

@Test
public void testAnnotation(){
    
    
    ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
    UserController userController = context.getBean("userController", UserController.class);
    userController.out();
}

illustrate:

​ By adding the @Autowired annotation on the formal parameters that need to be injected

5.3.3.6 Injection without annotations

Step 1: Set up the environment

1. Modify the UserServiceImpl class

@Service
public class UserServiceImpl implements UserService {
    
    

 
    private UserDao userDao;

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

    @Override
    public void out() {
    
    
        userDao.print();
        System.out.println("Service层执行结束");
    }
}

Step 2: Demonstration

@Test
public void testAnnotation(){
    
    
    ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
    UserController userController = context.getBean("userController", UserController.class);
    userController.out();
}

illustrate:

​ When there is only one constructor with parameters, the @Autowired annotation can be omitted

5.3.3.7 Combined @Qualifier annotation injection

Step 1: Set up the environment

1. Add UserDaoRedisImpl class

@Repository
public class UserDaoRedisImpl implements UserDao {
    
    

    @Override
    public void print() {
    
    
        System.out.println("Redis Dao层执行结束");
    }
}

illustrate:

  • At this point, adding a class that implements the UserDao interface has resulted in one interface corresponding to two implementation classes.
  • At this time, the program error, the message said: can not be assembled, the number of Bean UserDao is equal to 2

Step 2: Modify the UserServiceImpl class

@Service
public class UserServiceImpl implements UserService {
    
    

    @Autowired
    @Qualifier("userDaoImpl") // 指定bean的名字
    private UserDao userDao;

    @Override
    public void out() {
    
    
        userDao.print();
        System.out.println("Service层执行结束");
    }
}

illustrate:

​ When the interface that needs to be injected has multiple implementation classes, you can use the @Qualifier("userDaoImpl") annotation together and specify the name of the implementation class to complete the attribute injection.

5.3.4 Injection using @Resource

5.3.4.1 Overview

The @Resource annotation is injected through name matching. By default, it is matched by name. If a matching name cannot be found, it will try to match by type.

The @Resource annotation is in the JDK extension package, which means it is part of the JDK. So this annotation is a standard annotation, which is more general. (Annotation types specified in the JSR-250 standard. JSR is a Java specification proposal.)

image-20230512205825581

illustrate:

  • If it is JDK8, there is no need to introduce additional dependencies. Higher than JDK11 or lower than JDK8, the following dependencies need to be introduced
<dependency>
    <groupId>jakarta.annotation</groupId>
    <artifactId>jakarta.annotation-api</artifactId>
    <version>2.1.1</version>
</dependency>

5.3.4.2Name injection

Step 1: Set up the environment

1. Modify the UserDaoImpl class

package com.atguigu.spring6.dao.impl;

import com.atguigu.spring6.dao.UserDao;
import org.springframework.stereotype.Repository;

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

    @Override
    public void print() {
    
    
        System.out.println("Dao层执行结束");
    }
}

illustrate:

​ When using annotations, write the property name in parentheses to define an alias for this Bean.

2. Modify the UserServiceImpl class

package com.atguigu.spring6.service.impl;

import com.atguigu.spring6.dao.UserDao;
import com.atguigu.spring6.service.UserService;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService {
    
    

    @Resource(name = "myUserDao")
    private UserDao myUserDao;

    @Override
    public void out() {
    
    
        myUserDao.print();
        System.out.println("Service层执行结束");
    }
}

illustrate:

​ When using the @Resource annotation, you can use the name attribute to specify the alias for attribute injection.

Step 2: Demonstration

5.3.4.3 Unknown Name Injection

Step 1: Set up the environment

1. Modify the UserDaoImpl class

package com.atguigu.spring6.dao.impl;

import com.atguigu.spring6.dao.UserDao;
import org.springframework.stereotype.Repository;

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

    @Override
    public void print() {
    
    
        System.out.println("Dao层执行结束");
    }
}

2. Modify the UserServiceImpl class

package com.atguigu.spring6.service.impl;

import com.atguigu.spring6.dao.UserDao;
import com.atguigu.spring6.service.UserService;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService {
    
    

    @Resource
    private UserDao myUserDao;

    @Override
    public void out() {
    
    
        myUserDao.print();
        System.out.println("Service层执行结束");
    }
}

illustrate:

​ When using the @Resource annotation, when the name attribute is unknown, define the member attribute variable name of the attribute injection to have the same name as the Bean, and the injection can be completed.

Step 2: Demonstration

5.3.4.4 Type injection

Step 1: Set up the environment

1.Original UserDaoImpl class

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

    @Override
    public void print() {
    
    
        System.out.println("Dao层执行结束");
    }
}

2. Modify the UserServiceImpl class

@Service
public class UserServiceImpl implements UserService {
    
    

    @Resource
    private UserDao userDao1;

    @Override
    public void out() {
    
    
        userDao1.print();
        System.out.println("Service层执行结束");
    }
}

illustrate:

​ When using the @Resource annotation, the userDao1 attribute name does not exist now, but it can still be injected successfully. Because UserDao and their type names are the same

5.3.5 Full annotation development

5.3.5.1 Overview

Full-annotation development means no longer using the spring configuration file, and writing a configuration class to replace the configuration file

5.3.5.2 Basic use cases - full annotation development and implementation

Step 1: Create configuration class

@Configuration
//@ComponentScan({"com.atguigu.spring6.controller", "com.atguigu.spring6.service","com.atguigu.spring6.dao"})
@ComponentScan("com.atguigu.spring6")
public class Spring6Config {
    
    
}

illustrate:

​ Use the @ComponentScan annotation to scan components, thus replacing the original configuration in the xml file

Step 2: Demonstration

@Test
public void testAllAnnotation(){
    
    
    ApplicationContext context = new AnnotationConfigApplicationContext(Spring6Config.class);
    UserController userController = context.getBean("userController", UserController.class);
    userController.out();
    logger.info("执行成功");
}

illustrate:

​You need to use the AnnotationConfigApplicationContext class to obtain the bytecode file of Spring6Config

5.4 Principle

Summary of notes:

  1. Scan the specified package and obtain the class names of all classes that need to be managed.
  2. Instantiate the class that needs to be managed and call the constructor through the reflection mechanism .
  3. Inject property values ​​by calling the setter method or constructor through the reflection mechanism .
  4. Maintain dependencies between objects and achieve decoupling between objects .
  5. Register the instantiated object in the IOC container for subsequent use.

illustrate:

Insert image description here

Step 1: Environment setup

1. Create annotations

  • Create Bean annotations

    // 此注解用于定义容器对象,类似于@Componet、@Service、@Controller注解等作用
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Bean {
          
          
    }
    
  • Create dependency injection annotations

    // 此注解用于完成成员属性的依赖注入,类似于@Autoware、@Resource注解等作用
    @Target({
          
          ElementType.FIELD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Di {
          
          
    }
    

2. Create IOC core logic

  • Define bean container interface

    package com.atguigu.spring.core;
    
    public interface ApplicationContext {
          
          
    
        Object getBean(Class clazz);
    }
    
  • Write annotation bean container interface implementation

    public class AnnotationApplicationContext implements ApplicationContext {
          
          
    
        // 存储Bean的容器
        private HashMap<Class, Object> beanFactory = new HashMap<>();
    
        // 根据字节码文件获取Bean容器中的对象
        @Override
        public Object getBean(Class clazz) {
          
          
            return beanFactory.get(clazz);
        }
    
        /**
         * 根据包扫描加载bean
         * @param basePackage
         */
        public AnnotationApplicationContext(String basePackage) {
          
          
            try {
          
          
                String packageDirName = basePackage.replaceAll("\\.", "\\\\");
                Enumeration<URL> dirs =Thread.currentThread().getContextClassLoader().getResources(packageDirName);
                while (dirs.hasMoreElements()) {
          
          
                    URL url = dirs.nextElement();
                    String filePath = URLDecoder.decode(url.getFile(),"utf-8");
                    rootPath = filePath.substring(0, filePath.length()-packageDirName.length());
                    // 扫描包下的Bean
                    loadBean(new File(filePath));
                }
    
            } catch (Exception e) {
          
          
                throw new RuntimeException(e);
            }
            //依赖注入
            loadDi();
        }
    
    
        private  void loadBean(File fileParent) {
          
          
            if (fileParent.isDirectory()) {
          
          
                File[] childrenFiles = fileParent.listFiles();
                if(childrenFiles == null || childrenFiles.length == 0){
          
          
                    return;
                }
                for (File child : childrenFiles) {
          
          
                    if (child.isDirectory()) {
          
          
                        //如果是个文件夹就继续调用该方法,使用了递归
                        loadBean(child);
                    } else {
          
          
                        //通过文件路径转变成全类名,第一步把绝对路径部分去掉
                        String pathWithClass = child.getAbsolutePath().substring(rootPath.length() - 1);
                        //选中class文件
                        if (pathWithClass.contains(".class")) {
          
          
                            //    com.xinzhi.dao.UserDao
                            //去掉.class后缀,并且把 \ 替换成 .
                            String fullName = pathWithClass.replaceAll("\\\\", ".").replace(".class", "");
                            try {
          
          
                                Class<?> aClass = Class.forName(fullName);
                                //把非接口的类实例化放在map中
                                if(!aClass.isInterface()){
          
          
                                    Bean annotation = aClass.getAnnotation(Bean.class);
                                    if(annotation != null){
          
          
                                        Object instance = aClass.newInstance();
                                        //判断一下有没有接口
                                        if(aClass.getInterfaces().length > 0) {
          
          
                                            //如果有接口把接口的class当成key,实例对象当成value
                                            System.out.println("正在加载【"+ aClass.getInterfaces()[0] +"】,实例对象是:" + instance.getClass().getName());
                                            beanFactory.put(aClass.getInterfaces()[0], instance);
                                        }else{
          
          
                                            //如果有接口把自己的class当成key,实例对象当成value
                                            System.out.println("正在加载【"+ aClass.getName() +"】,实例对象是:" + instance.getClass().getName());
                                            beanFactory.put(aClass, instance);
                                        }
                                    }
                                }
                            } catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {
          
          
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }
        }
    
        private void loadDi() {
          
          
            for(Map.Entry<Class,Object> entry : beanFactory.entrySet()){
          
          
                //就是咱们放在容器的对象
                Object obj = entry.getValue();
                Class<?> aClass = obj.getClass();
                Field[] declaredFields = aClass.getDeclaredFields();
                for (Field field : declaredFields){
          
          
                    Di annotation = field.getAnnotation(Di.class);
                    if( annotation != null ){
          
          
                        field.setAccessible(true);
                        try {
          
          
                            System.out.println("正在给【"+obj.getClass().getName()+"】属性【" + field.getName() + "】注入值【"+ beanFactory.get(field.getType()).getClass().getName() +"】");
                            field.set(obj,beanFactory.get(field.getType()));
                        } catch (IllegalAccessException e) {
          
          
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }
    

    illustrate:

    You can copy this code into IDEA to view the logic in more detail

3. Create Dao layer

  • Create UserDao interface
public interface UserDao {
    
    

    public void print();
}
  • Create UserDaoImpl implementation
@Bean
public class UserDaoImpl implements UserDao {
    
    
    @Override
    public void print() {
    
    
        System.out.println("Dao层执行结束");
    }
}

illustrate:

  • When this class implements the UserDao interface, it will use the UserDao interface as the Key value of the container to obtain the UserDaoImpl implementation class.

  • This is why an interface cannot correspond to multiple implementation classes, because the Key value of HashMap cannot be repeated.

  • // 参数解释,参数1:实现类上实现的第一个接口或者实现类的字节码文件;参数2:实现类实例
    beanFactory.put(aClass.getInterfaces()[0], instance);
    // 此处,参数1:接口为UserDao;参数2,实现类实例为UserDaoImpl
    

4. Create the Service layer

  • Create UserService interface

    public interface UserService {
          
          
        public void out();
    }
    
  • Create UserServiceImpl implementation class

    @Bean
    public class UserServiceImpl implements UserService {
          
          
    
        @DI
        private UserDao userDao;
    
        @Override
        public void out() {
          
          
            userDao.print();
            System.out.println("Service层执行结束");
        }
    }
    

    illustrate:

    • When this class contains the dependency injection interface, the UserServiceImpl implementation class instance will be used as the key value of dependency injection, and the required dependency injection implementation class instance will be determined based on the dependency injection variable name.

    • // 参数解释,参数1:设置字段值的对象实例;参数2:需要设置的字段值
      field.set(obj, beanFactory.get(field.getType()));
      //此处,参数1:实现类实例UserServiceImpl;参数2:实现类实例UserDaoImpl
      

Step 2: Demonstration

ApplicationContext applicationContext = new AnnotationApplicationContext("org.example");
UserService bean = (UserService) applicationContext.getBean(UserService.class);
bean.out();

6. Aspect-oriented: AOP (emphasis)

Summary of notes:

  1. Overview:

    1. Meaning: AOP (Aspect Oriented Programming) is a design idea and aspect-oriented programming in the field of software design.
    2. effect:
      • Simplify development : separate concerns and allow common behaviors (logs, transactions, security) to be reused
      • Reduce code coupling : separate different concerns and improve code reusability and maintainability
    3. Cross-cutting concerns: Cross-cutting concerns refer to functionality or behavior that spans multiple modules of an application . For example, logging, security and other functions that have nothing to do with business logic
    4. Advice: Advice (enhancement) refers to a special type of method defined in AOP, which contains some behavior to be performed at the join point (join point) . For example, some logic such as output logs needs to be added before, during, and after the execution of a certain method.
    5. Aspects: Aspects refer to the combination of cross-cutting concerns and notifications. Simply put, aspects are classes that encapsulate notification methods.
    6. Target: Target refers to the object being notified or the object affected by the aspect . For example, elements such as classes, interfaces, and methods
    7. Proxy: Proxy refers to controlling access to the target object and inserting additional logic during the access process . Simply put, a proxy is a proxy object created after applying notifications to the target object.
    8. Join point: A join point represents a point at which an aspect can be inserted during program execution . Simply put, the connection point is the execution logic in the proxy object
    9. Pointcut: Pointcut (Pointcut) represents one or more specific methods or method execution locations defined in the target object . It indicates where the logic of the aspect should be inserted.
  2. Proxy pattern: The proxy pattern is a structural design pattern that allows a proxy object to be accessed on behalf of another object.

    1. Static proxy: Static proxy uses code to perform some additional operations before or after the method is implemented.
    2. Dynamic proxy: It allows proxy objects to be created dynamically at runtime and aspect logic is woven into the methods of the target object.
      • Category: interface-based proxy (with interface), class-based proxy (without interface)
  3. Pointcut expression: used to match methods in the target object and provide a precise definition of the pointcut

    image-20230814214853767

  4. Annotation-based AOP: Each summary module, please check this summary (key points)

  5. XML-based AOP: Definition and application of aspects through XML (understanding)

6.1 Overview

6.1.1 Definition

​ AOP (Aspect Oriented Programming) is a design idea , which is aspect-oriented programming in the field of software design. It is a supplement and improvement of object-oriented programming. It is implemented through pre-compilation and runtime dynamic proxy . A technology that dynamically adds additional functionality to a program without modifying the source code. AOP can be used to isolate various parts of the business logic, thereby reducing the coupling between the various parts of the business logic, improving the reusability of the program, and improving the efficiency of development.

6.1.2 Function

  1. Code reuse and modularization: AOP can abstract some common behaviors (such as logging, security control, transaction management, etc.) into reusable modules to avoid repeatedly writing these codes in each business logic.

  2. Separation of concerns: AOP separates different concerns, making the responsibilities of each module clearer and making the code more readable and maintainable.

  3. Simplify development: AOP can help developers separate concerns from business logic, making development simpler and clearer.

  4. Improve the scalability of the system: When system requirements change, only the AOP module needs to be modified instead of the business logic, which can make the system easier to expand and maintain.

  5. Reduce code coupling: The role of AOP is to separate different concerns, which can avoid tight coupling between codes and improve code reusability and maintainability.

6.1.3 Cross-cutting concerns

In AOP, cross-cutting concerns refer to cross-cutting behaviors that affect multiple classes or objects in an application, such as logging, performance monitoring, transaction processing, etc. These behaviors may be scattered across different classes and methods throughout the application , rather than being tightly tied to the application's core business logic.

Using AOP technology, these cross-cutting concerns can be separated from the application's core business logic and modularized into reusable modules, resulting in better code structure and better maintainability.

Insert image description here

6.1.4 Notification (Enhanced)

Advice, also known as enhancement, refers to a special type of method defined in AOP, which contains some behaviors to be performed at the join point . Notifications can be executed before , after , or on exception when the target method is executed , or after the target method returns a result. The purpose of advice is to apply enhancements (such as logging, transaction management, etc.) to a specific method or pointcut of an application without modifying the target object. Advice is one of the core components for implementing AOP. It implements aspect-oriented programming by applying advice to specific join points.

Simply put: Notifications are the features you want to enhance, such as security, transactions, logs, etc.

Notification Category:

  1. Pre-advice: Executed before the proxied target method
  2. Return notification: executed after the delegated target method successfully ends ( ends of life )
  3. Exception notification: executed after the proxied target method ends abnormally ( died unexpectedly )
  4. Post-notification: executed after the delegated target method finally ends ( final conclusion )
  5. Surround notifications: Use the try...catch...finally structure to surround the entire proxied target method, including all locations corresponding to the above four notifications.

image-20230513233617466

6.1.5 Sectioning

In AOP, aspect refers to the combination of cross-cutting concerns and notifications. It is a modular horizontal segmentation and can be understood as a horizontal slice. An aspect is an encapsulation of cross-cutting concerns and advice. It contains a set of cut points and advice to describe where, when, and how to execute cross-cutting logic. The aspect can enhance or change the function of the original code without modifying the original code. Usually, an aspect exists in the form of a class, which contains one or more advices and one or more pointcuts.

To put it simply: aspects are classes that encapsulate notification methods.

Insert image description here

6.1.6 Goals

​ In AOP (Aspect-Oriented Programming), the target (Target) refers to the object being notified or the object affected by the aspect. It is a specific element in the application , which can be a class, interface, method, field, etc. To put it simply, the target is the target object being proxied.

6.1.7 Agent

In AOP (Aspect-Oriented Programming), Proxy is a design pattern used to control access to target objects and insert additional logic during the access process . Simply put, a proxy is a proxy object created after applying a notification to a target object

6.1.8 Connection points

In AOP, a join point represents a point where an aspect can be inserted during program execution , such as method invocation, exception handling, field access, etc. Join points define where in the program an aspect can be applied. Aspects can add additional processing logic before and after the connection point, thereby affecting the behavior of the program. In layman's terms, a connection point is a place that can be intercepted during program execution.

image-20230513234310439

illustrate:

​ Arrange the methods in a row, each cross-cutting position is regarded as the x-axis direction, and the order in which the methods are executed from top to bottom is regarded as the y-axis. The intersection of the x-axis and the y-axis is the connection point. In layman's terms, this is where spring allows you to use notifications

6.1.9 Entry point

In AOP, the entry point (Join Point) refers to a clear point during program execution, usually when a method is called, or during the processing of an exception handler. Pointcuts define which methods need to be intercepted or enhanced, and are one of the most important concepts in AOP. Pointcuts are usually defined in the form of methods, such as all methods in a class, all methods in a package, etc. In AOP, expression language is usually used to define pointcuts, such as using the @Pointcut annotation definition in Spring AOP.

6.2 Proxy mode

6.2.1 Overview

The proxy pattern is a structural design pattern that allows a proxy object to be accessed on behalf of another object. It is one of the twenty-three design patterns and belongs to the structural pattern. Its function is to provide a proxy class so that when we call the target method, we no longer call the target method directly, but call it indirectly through the proxy class . Let the code that does not belong to the core logic of the target method be stripped from the target method - decoupling . When calling the target method, first call the method of the proxy object to reduce calls and interruptions to the target method. At the same time, allowing additional functions to be centralized together is also conducive to unified maintenance.

image-20230814214956482

Proxy: After stripping out the non-core logic, encapsulate the classes , objects, and methods of these non-core logic

6.2.2 Static proxy

​ In a static proxy, the proxy class is created at compile time . The proxy class and the delegate class implement the same interface or inherit the same class, and implement the methods in the delegate class in the proxy class. Before calling the method of the delegate class or and then perform some additional operations

public class CalculatorStaticProxy implements Calculator {
    
    
    
    // 将被代理的目标对象声明为成员变量
    private Calculator target;
    
    public CalculatorStaticProxy(Calculator target) {
    
    
        this.target = target;
    }
    
    @Override
    public int add(int i, int j) {
    
    
    
        // 附加功能由代理类中的代理方法来实现
        System.out.println("[日志] add 方法开始了,参数是:" + i + "," + j);
    
        // 通过目标对象来实现核心业务逻辑
        int addResult = target.add(i, j);
    
        System.out.println("[日志] add 方法结束了,结果是:" + addResult);
    
        return addResult;
    }
}

illustrate:

Static proxy does achieve decoupling, but because the code is hard-coded, it does not have any flexibility at all.

6.2.3 Dynamic proxy

6.2.3.1 Overview

6.2.3.1.1Definition

​ In dynamic proxy, the proxy class is dynamically created at run time . It does not need to know the interface or implementation class of the delegate class in advance, but dynamically generates the proxy class through the Java reflection mechanism at runtime.

Insert image description here

6.2.3.1.2 Classification

Dynamic agent classification

  • Interface-based proxy (with interface)
  • Class-based proxy (without interface case)

image-20230814215007178

illustrate:

​AspectJ: It is an implementation of AOP thinking. It is essentially a static proxy that "weaves" the proxy logic into the bytecode file compiled by the proxy target class , so the final effect is dynamic. A weaver is a weaver. Spring just borrows the annotations from AspectJ.

image-20230814215024474

illustrate:

  • When the dynamic proxy is an interface-based proxy, this method is the native implementation of JDK. The target class that needs to be proxied must implement the interface . Because this technology requires the proxy object and the target object to implement the same interface**
  • When the dynamic proxy is a class-based proxy, the proxy is implemented by inheriting the proxied target class. Therefore, there is no need for the target class to implement the interface

Replenish:

  • The proxy class dynamically generated by JDK dynamic proxy will be under the com.sun.proxy package. The class name is $proxy1 and implements the same interface as the target class.
  • The proxy class dynamically generated by cglib dynamic proxy will be in the same package as the target and will inherit the target class.

6.2.3.2 Basic use case-implementing dynamic proxy

Step 1: Create ProxyFactory class

public class ProxyFactory {
    
    

    private Object target;

    public ProxyFactory(Object target) {
    
    
        this.target = target;
    }

    public Object getProxy(){
    
    
        /**
         * newProxyInstance():创建一个代理实例
         * 其中有三个参数:
         * 1、classLoader:加载动态生成的代理类的类加载器
         * 2、interfaces:目标对象实现的所有接口的class对象所组成的数组
         * 3、invocationHandler:设置代理对象实现目标对象方法的过程,即代理类中如何重写接口中的抽象方法
         */
        ClassLoader classLoader = target.getClass().getClassLoader();
        Class<?>[] interfaces = target.getClass().getInterfaces();
        InvocationHandler invocationHandler = new InvocationHandler() {
    
    
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    
                /**
                 * proxy:代理对象
                 * method:代理对象需要实现的方法,即其中需要重写的方法
                 * args:method所对应方法的参数
                 */
                Object result = null;
                try {
    
    
                    System.out.println("[动态代理][日志] "+method.getName()+",参数:"+ Arrays.toString(args));
                    result = method.invoke(target, args);
                    System.out.println("[动态代理][日志] "+method.getName()+",结果:"+ result);
                } catch (Exception e) {
    
    
                    e.printStackTrace();
                    System.out.println("[动态代理][日志] "+method.getName()+",异常:"+e.getMessage());
                } finally {
    
    
                    System.out.println("[动态代理][日志] "+method.getName()+",方法执行完毕");
                }
                return result;
            }
        };

        return Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
    }
}

illustrate:

  • Dynamic proxies need to use the Proxy.newProxyInstance() method
  • It is necessary to set up a proxy object to implement the method process of the target object

Step 2: Demonstration

@Test
public void testDynamicProxy(){
    
    
    ProxyFactory factory = new ProxyFactory(new CalculatorLogImpl());
    Calculator proxy = (Calculator) factory.getProxy();
    proxy.div(1,0);
    //proxy.div(1,1);
}

6.3 Pointcut expressions

In AOP, pointcut expressions specify which methods need to be woven into the enhanced logic . It is an expression that matches methods in the target object and provides a precise definition of the pointcut

image-20230514145900081

illustrate:

​ In the pointcut expression syntax, use *numbers to replace the "permission modifier" and "return value" parts to indicate that the "permission modifier" and "return value" are not limited

6.4 Annotation-based AOP

Summary of notes:

  1. Overview: Add annotations to Java classes, methods, parameters, etc. to implement the definition and application of aspects.

  2. Basic use case:

    Step 1: Import dependencies

    Step 2: Create an aspect class (you need to select the notification method)

    Step 3: Add xml configuration file

  3. method to informe:

    1. Advance notice:@Before
    2. Exception notification:@AfterThrowing
    3. Return notification:@AfterReturning
    4. Post notification:@After
    5. Surround notifications:@Around
  4. Get notification information

    1. Get the connection point: Use JoinPoint in the method to get the connection point information

      public void beforeMethod(JoinPoint joinPoint)
      
    2. Get the return value of the target object: add the returning attribute to the return notification of the target object

      @AfterReturning(value = "execution(* com.atguigu.aop.annotation.CalculatorImpl.*(..))", returning = "result")
      public void afterReturningMethod(JoinPoint joinPoint, Object result)
      
    3. Get the exception of the target object : add the throwing attribute on the exception notification of the target object

      @AfterThrowing(value = "execution(* com.atguigu.aop.annotation.CalculatorImpl.*(..))", throwing = "ex")
      public void afterThrowingMethod(JoinPoint joinPoint, Throwable ex)
      
  5. Reuse pointcut expressions

    1. Statement: Use the **@Pointcut** annotation on methods with empty parameters, empty method bodies, and empty return values.

      @Pointcut("execution(* com.atguigu.aop.annotation.*.*(..))")
      public void pointCut(){
               
               }
      
    2. Use in the same aspect : just reference it directly in the same aspect

      @Before("pointCut()")
      
    3. Use in different aspects : in different aspects

      @Before("com.atguigu.aop.CommonPointCut.pointCut()")
      

6.4.1 Overview

​ Annotation-based AOP is an AOP implementation method. It implements the definition and application of aspects by adding annotations to Java classes, methods, parameters, etc. , which is more convenient and flexible than the traditional XML configuration method.

6.4.2 Basic use case-annotation to implement AOP

Step 1: Import dependencies

 <!--spring aop依赖-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>6.0.2</version>
    </dependency>
    <!--spring aspects依赖-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>6.0.2</version>
    </dependency>

Step 2: Create interface and implementation class

1.Interface

public interface Calculator {
    
    
    int add(int i, int j); 
}

2. Implementation class

@Component
public class CalculatorImpl implements Calculator {
    
    

    @Override
    public int add(int i, int j) {
    
    
        int result = i + j;
        System.out.println("方法内部 result = " + result);
        return result;
    }
}

illustrate:

​ This implementation class also needs to add @Component annotations to facilitate Spring container management

Step 3: Create aspect classes

@Aspect
@Component
public class LogAspect {
    
    
    // 前置通知
    // 异常通知
    // 返回通知
    // 后置通知
    // 环绕通知
    ……
}

Notice:

Here you need to configure the notification method of the aspect class!

illustrate:

  • @Aspect indicates that this class is an aspect class
  • The @Component annotation ensures that this aspect class can be placed in the IOC container

Step 4: Configure Spring configuration file

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--
        基于注解的AOP的实现:
        1、将目标对象和切面交给IOC容器管理(注解+扫描)
        2、开启AspectJ的自动代理,为目标对象自动生成代理
        3、将切面类通过注解@Aspect标识
    -->
    <context:component-scan base-package="com.atguigu.aop.annotation"></context:component-scan>

    <aop:aspectj-autoproxy />
</beans>

Replenish:

After learning SpringBoot, AOP can be realized through SpringBoot, and this file can be omitted. Because SpringBoot implements package scanning and aspect identification

Step 5: Demonstrate

@Test
public void testAdd(){
    
    
    ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
    Calculator calculator = ac.getBean( Calculator.class);
    int add = calculator.add(1, 1);
}

illustrate:

Insert image description here

6.4.3 Notification method

6.4.3.1 Pre-notification

Use the @Before annotation to execute before the proxied target method.

@Before("execution(public int com.atguigu.aop.annotation.CalculatorImpl.*(..))")
public void beforeMethod(JoinPoint joinPoint){
    
    
    // getSignature()获取连接点签名,getName()获取连接点名称
    String methodName = joinPoint.getSignature().getName();
    String args = Arrays.toString(joinPoint.getArgs());
    System.out.println("Logger-->前置通知,方法名:"+methodName+",参数:"+args);
}

illustrate:

  • The @Before annotation contains the pointcut expression
  • JoinPoint refers to a clear point during program execution, such as method invocation or exception handling. JoinPoint provides a way for aspect notification to obtain key information of the method.

6.4.3.2 Exception notification

Use the @AfterThrowing annotation to execute after the proxy target method ends abnormally.

@AfterThrowing(value = "execution(* com.atguigu.aop.annotation.CalculatorImpl.*(..))", throwing = "ex")
public void afterThrowingMethod(JoinPoint joinPoint, Throwable ex){
    
    
    String methodName = joinPoint.getSignature().getName();
    System.out.println("Logger-->异常通知,方法名:"+methodName+",异常:"+ex);
}

illustrate:

​ The @AfterThrowing annotation contains the pointcut expression

6.4.3.3 Return notification

Use the @AfterReturning annotation to execute after the proxied target method successfully ends .

@AfterReturning(value = "execution(* com.atguigu.aop.annotation.CalculatorImpl.*(..))", returning = "result")
public void afterReturningMethod(JoinPoint joinPoint, Object result){
    
    
    String methodName = joinPoint.getSignature().getName();
    System.out.println("Logger-->返回通知,方法名:"+methodName+",结果:"+result);
}

illustrate:

The @AfterReturning annotation contains the pointcut expression

6.4.3.4 Post notification

Use the @After annotation to execute after the proxied target method finally ends

  @After("execution(* com.atguigu.aop.annotation.CalculatorImpl.*(..))")
    public void afterMethod(JoinPoint joinPoint){
    
    
        String methodName = joinPoint.getSignature().getName();
        System.out.println("Logger-->后置通知,方法名:"+methodName);
    }

illustrate:

​ The @After annotation is the pointcut expression

6.4.3.5 Surround notifications

Use the @Around annotation and use the try...catch...finally structure to surround the entire proxied target method, including all locations corresponding to the above four notifications.

@Around("execution(* com.atguigu.aop.annotation.CalculatorImpl.*(..))")
public Object aroundMethod(ProceedingJoinPoint joinPoint){
    
    
    String methodName = joinPoint.getSignature().getName();
    String args = Arrays.toString(joinPoint.getArgs());
    Object result = null;
    try {
    
    
        System.out.println("环绕通知-->目标对象方法执行之前");
        //目标对象(连接点)方法的执行
        result = joinPoint.proceed();
        System.out.println("环绕通知-->目标对象方法返回值之后");
    } catch (Throwable throwable) {
    
    
        throwable.printStackTrace();
        System.out.println("环绕通知-->目标对象方法出现异常时");
    } finally {
    
    
        System.out.println("环绕通知-->目标对象方法执行完毕");
    }
    return result;
}

illustrate:

  • The @Around annotation contains the pointcut expression
  • ProceedingJoinPoint inherits from the JoinPoint interface and is a special type of JoinPoint used for surrounding notifications. It can be used to control the execution of the target method in the notification. In surrounding advice, ProceedingJoinPoint provides a proceed() method, which executes the target method and returns its result.

6.4.4 Obtain notification information

6.4.4.1 Obtain connection point information

In any notification method, to obtain the connection point information, you can set the formal parameter of JoinPoint type in the parameter position of the notification method.

@Before("execution(public int com.atguigu.aop.annotation.CalculatorImpl.*(..))")
public void beforeMethod(JoinPoint joinPoint){
    
    
    //获取连接点的签名信息
    String methodName = joinPoint.getSignature().getName();
    //获取目标方法到的实参信息
    String args = Arrays.toString(joinPoint.getArgs());
    System.out.println("Logger-->前置通知,方法名:"+methodName+",参数:"+args);
}

6.4.4.2 Obtain the return value of the target method

The returning attribute in @AfterReturning is used to transfer a formal parameter of the notification method to receive the return value of the target method.

@AfterReturning(value = "execution(* com.atguigu.aop.annotation.CalculatorImpl.*(..))", returning = "result")
public void afterReturningMethod(JoinPoint joinPoint, Object result){
    
    
    String methodName = joinPoint.getSignature().getName();
    System.out.println("Logger-->返回通知,方法名:"+methodName+",结果:"+result);
}

6.4.4.3 Obtain the exception of the target method

The throwing attribute in @AfterThrowing is used to transfer a formal parameter of the notification method to receive the exception of the target method.

@AfterThrowing(value = "execution(* com.atguigu.aop.annotation.CalculatorImpl.*(..))", throwing = "ex")
public void afterThrowingMethod(JoinPoint joinPoint, Throwable ex){
    
    
    String methodName = joinPoint.getSignature().getName();
    System.out.println("Logger-->异常通知,方法名:"+methodName+",异常:"+ex);
}

6.4.5 Reusing pointcut expressions

illustrate:

For pointcut expressions, please refer to 面向切面:AOPthe overview section in this section

Simplify writing of entry points

6.4.5.1 Statement

@Pointcut("execution(* com.atguigu.aop.annotation.*.*(..))")
public void pointCut(){
    
    }

6.4.5.2 Using the same section

@Before("pointCut()")
public void beforeMethod(JoinPoint joinPoint){
    
    
    String methodName = joinPoint.getSignature().getName();
    String args = Arrays.toString(joinPoint.getArgs());
    System.out.println("Logger-->前置通知,方法名:"+methodName+",参数:"+args);
}

6.4.5.3 Use of different aspects

@Before("com.atguigu.aop.CommonPointCut.pointCut()")
public void beforeMethod(JoinPoint joinPoint){
    
    
    String methodName = joinPoint.getSignature().getName();
    String args = Arrays.toString(joinPoint.getArgs());
    System.out.println("Logger-->前置通知,方法名:"+methodName+",参数:"+args);
}

6.5 XML-based AOP (understand)

<context:component-scan base-package="com.atguigu.aop.xml"></context:component-scan>

<aop:config>
    <!--配置切面类-->
    <aop:aspect ref="loggerAspect">
        <aop:pointcut id="pointCut" 
                   expression="execution(* com.atguigu.aop.xml.CalculatorImpl.*(..))"/>
        <aop:before method="beforeMethod" pointcut-ref="pointCut"></aop:before>
        <aop:after method="afterMethod" pointcut-ref="pointCut"></aop:after>
        <aop:after-returning method="afterReturningMethod" returning="result" pointcut-ref="pointCut"></aop:after-returning>
        <aop:after-throwing method="afterThrowingMethod" throwing="ex" pointcut-ref="pointCut"></aop:after-throwing>
        <aop:around method="aroundMethod" pointcut-ref="pointCut"></aop:around>
    </aop:aspect>
</aop:config>

knowledge gas station

1. The difference and connection between automatic assembly and dependency injection

Dependency Injection is a design pattern that aims to achieve decoupling between objects by passing dependencies from one object to another . In Spring, dependency injection manages and passes dependencies between objects through the container, rather than creating or managing their dependencies by the objects themselves. This can be achieved through constructor injection, setter method injection or field injection etc.

​Autowired is a dependency injection method provided by the Spring Framework , which is used to automatically inject the appropriate dependencies into the corresponding positions, without manually specifying the injection method of each dependency. By using annotations, Spring will automatically find matching dependencies@Autowired in the container and inject them where needed .

Summarize:

  • Autowiring is a feature of the Spring framework that is used to automatically connect components in an application.
  • Dependency injection is a specific implementation of automatic assembly, using the **@Autowired annotation to identify properties, constructors or method parameters that need to be automatically injected**.

2. Two ways of dependency injection

There are two common ways of dependency injection:

  1. Constructor Injection: Inject dependent objects through constructors. Declare parameters in the constructor of the target class, and pass in dependent objects through the constructor when creating the target object. This method ensures that dependent objects are passed in when the target object is created, thereby ensuring the integrity and consistency of the target object.
  2. Setter method injection (Setter Injection): Inject dependent objects through the Setter method. Define the corresponding Setter method in the target class, receive the dependent object as a parameter in the method, and inject the dependent object by calling the Setter method. This method can dynamically set dependent objects after the target object is created, which is more flexible.

Guess you like

Origin blog.csdn.net/D_boj/article/details/132286492