[Spring] Annotations read and store Bean objects (on)

 

The most basic Spring operations of reading and storing Bean objects have been realized. Use the Spring configuration file (.xml) to store the Bean objects, and use the ApplicationContext or BeanFactory interface to obtain the Spring context objects. The context objects manage the Spring objects. Bean object, and then call the getBean() method to obtain the specified Bean object. This method is an overloaded method. There are three main ways to obtain the Bean object:

1.  Obtain according to the id (flag) of the bean object 

2.  Get Bean according to the object type 

3. Get the bean according to  the id (flag) + type of the bean object

The first two methods of overloading to obtain the specified Bean object have their own defects, and we recommend using the third method.


After the previous study, although we have realized the basic acquisition and storage of Spring, the operation process is relatively cumbersome.

Storing Bean objects requires us to manually add configuration to the Spring configuration file.

To take out the Bean object, first we need to obtain the context object, and secondly, we need to call the getBean() method to obtain it according to the parameters. It is not as good as our traditional method, but there is one more (dependency inversion) idea.

So next we need to learn a simpler way to manipulate Bean objects - using annotations.

Use relevant annotations in Spring to store and read Bean objects.


2. Spring stores Bean objects

Before storing bean objects, we needed to add a line of bean tags to the Spring configuration file (.xml), as shown in the figure above.

Now what we need to learn is how to use annotations to replace the embarrassment of manually writing a line of bean configuration when adding Bean objects .

Annotation is a kind of metadata in the Java language, which provides a code-level marking mechanism to represent some structured information in the program and explain these structures. Annotations can be used on various Java program elements such as classes, fields, methods, parameters, etc., and annotation information can be obtained through the reflection mechanism.

Simple understanding:

Annotations are like labels, we can add them to the code of the program to add some additional information and instructions to the code. This information can help programs automate certain operations, such as code generation, configuration management, documentation generation, and more.

For example, if we want to add some configuration information to a class, usually we need to hand-write some configuration code in the code, and then parse and load it in the program. However, if we use annotations, we can let the program automatically complete the loading and parsing of the configuration by adding some specific annotations to the class. This saves a lot of time and code.

In short, annotation is a tool used to add additional information to the program, which can help us manage and automate various operations of the program more conveniently.


 2.1 Configure scan path

Before, we manually added the Bean object in the Spring configuration file (.xml). If we use the method of annotation to store, we only need to configure the package path where the bean object (not instantiated) is located. When Spring starts, the context object will be based on The path configured in the Spring configuration file is scanned, and only the classes and methods annotated in the path (package) can be correctly identified and instantiated into Spring.

The Spring configuration file (.xml) is configured as follows:

<?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:content="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 https://www.springframework.org/schema/context/spring-context.xsd">
    <content:component-scan base-package="animal"></content:component-scan>
</beans>

If the annotated class or method is not under the package of the configuration scan, it cannot be stored in Spring.


2.2 Add annotations to store Bean objects

To store Bean objects in Spring more easily, there are two types of annotations:

1. Class annotation: As the name implies, it is an annotation used to modify the class, indicating that the modified class instance needs to be stored in the Spring container. Five categories of annotations: the meaning of these annotations is described in detail below

@Controller [controller], @Service [service], @Repository [warehouse], @Component [component],

@Configuratio [Configuration].

2. Method annotation: A method in a class can instantiate another class. At this time, set the return value of the method to the class object after the instance and then use the @Bean method annotation to store the object (bean object) in in the Spring container.

In Spring, the five major types of annotations can store Bean objects in Spring. There is not much to say , but in the learning of the framework later, each annotation hierarchically modifies the class, and their meaning is very particular. At this time, We mainly learn how to use annotations to access Bean objects, and other knowledge points will be expanded later.


2.2.1 @Controller (controller) stores Bean objects in Spring

First define a student class:

public class Student {
    // 属性
    private String id;
    private String name;
    private String sex;
    private int age;

    // 行为
    public void homework() {
        System.out.println(name + "在做作业~");
    }

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

    public String getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public String getSex() {
        return sex;
    }

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

    public int getAge() {
        return age;
    }

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

Add the @Controller annotation to the Student class to store the Student object (automatically at runtime) in Spring

1. Set the scanning path in the Spring configuration file

2. Add annotations to the Student class

It's very cool, just an annotation + set the scanning path to get it done~ When Spring starts, it will automatically add the Student class instance to Spring.

At this point we can use the method of getting the object before to try to get the object of the Student class from Spring.

The ApplicationContext interface obtains the context object, and then calls the getBean() method to obtain the specified Bean object.

public class App {
    public static void main(String[] args) {
        //1. 得到 Spring 的上下文对象
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-test.xml");
        //2. 调用 getBean() 方法获取指定的 Bean 对象
        Student student = context.getBean("student",Student.class);

        //3. 使用 Bean 对象
        student.setId("1");
        student.setName("张三");
        student.setSex("男");
        student.setAge(20);

        student.homework();
        System.out.println(student.toString());
    }
}


2.2.1 @Service (service) stores Bean objects in Spring

The remaining three annotations @Repository [warehouse], @Component [component], @Configuratio [configuration]. It doesn't have much meaning in Spring, they all store Bean objects, and I won't show you that the results are the same here. Interested veterans can demonstrate it by themselves.


2.3 Why do we need so many class annotations?

As shown in the above example, the functions of the five types of annotations can store Bean objects in Spring. Why do we need so many class annotations when the functions are the same? ? ?

The specific application scenarios and meanings of each annotation:

1. @Controller annotation: [Controller] Verify the parameters transmitted by the front end [Security Inspection]

The Controller layer is part of the MVC (Model-View-Controller) design pattern and is responsible for handling user requests and controlling the flow of the application. It is a component in the application that receives requests from the user interface (View), coordinates the work of other components (such as the Service layer and the Repository layer), and returns the corresponding results to the user interface.

2. @Service annotation: [Service Layer]

It is mainly used to process business logic and perform specific business operations. It is located in the middle layer of the application, between the control layer and the data access layer, and is used to realize the encapsulation and processing of business logic.

3. @Repository annotation: [warehouse (data warehouse)] can be understood as directly operating the database

The Repository layer is a design pattern in software development that handles data access and persistence. In Java applications, the Repository layer is usually part of the data access layer, interacting with databases or other data storage media.

4. @Component annotation: [Component] general tool class

The Component layer is a componentized layer in Java applications, mainly used for component management and assembly. It is responsible for combining various functional modules or components to provide the overall functionality of the application. The Component layer is usually located at the top of the application and serves as the entry point of the application.

5. @Configuration annotation: [Configuration] Here are all the configurations of the project

The @Configuration annotation is used by the Spring Framework in addition to traditional XML configuration. In order to better support Java configuration, it represents a configuration class that can be used as a Bean definition after being annotated. Through the @Configuration annotation, you can easily configure the Bean components in the Spring container.

for example:

Each of us has a unique 18-digit ID number, which includes: area number, date of birth, sequence code and check code. The first few digits of the mass ID numbers of the same province/city are the same. For example, the ID numbers of the new generation in Hubei Province all start with "42XXXX". Among them, XXXX is a specific area code, which is used to represent different administrative divisions in Hubei Province. Yes, we can use a String type  region variable to describe the region code, so that we can intuitively see which region the people come from. The birthday variable can be used to describe a date of birth... To separate a complete ID number, It can express the basic information of this person more intuitively. It can be seen that the region variable describes the region. The old iron at the beginning of 42 is from Hubei. The class annotation is the same reason. I use different annotations for different "levels" of classes Description, is it very intuitive, for example: @Repository annotation is used to modify the class that operates the database according to the standard, which is very convenient for maintenance.

To sum up, although the functions of these five types of annotations can store Bean objects in Spring, their usage scenarios and semantics are slightly different, which can better meet different needs and scenarios. Because of this, there are so many types of annotations involved in the Spring framework to deal with different business scenarios and complex requirements.

The engineering layering of the program, the call flow chart:


2.3.1 Relationship between class annotations

Check the source code of @Controller / @Service / @Repository / @Configuration These annotations are found:

ctrl + mouse click on the annotation to view it.

There is a @Component annotation inside these annotations, indicating that these annotations can be considered as subclasses of @Component.


2.4 Naming rules for Bean objects

Above we store Bean objects by using annotations, which is to set the path (package) where the Bean objects are located in the Spring configuration article. When the Spring container starts, it will scan the path in the configuration file and instantiate the annotated class to in the container. If we use the old method before to obtain the Bean object, we need to obtain the Spring context object (management bean) first. There are two ways [ApplicationContext interface] (officially recommended after Spring 3.x version), [BeanFactory interface]

After getting the context object, we need to call the getBean() method to get the specific Bean object, because the getBean() method has an overload, so there are three main ways to get it: 1. According to the Bean
object ID, we manually get the name (disadvantages,: The return value is Object, so it needs to be cast )

2. According to the type of the Bean object (disadvantage: if there are multiple beans of the same type stored in the container, an exception will be thrown at this time)

3. According to the ID of the Bean object and the type of the Bean object (recommended)

At this point we add Bean objects through class annotations, so what adjustments should be made to the method of obtaining Bean objects?

Usually, the Bean (class) is named using the standard big hump, and the Bean object can be obtained when the first letter is lowercase when reading:


When the first letter and the second letter of the class name are capitalized, the Bean cannot be read normally by using the default lowercase first letter:


Regarding the default ID of obtaining the Bean object, we need to understand the naming rules generated by Spring when storing the Bean object

Double-click the shift key to open the global search: Enter AnnotationbeanName

 The rule uses the decapitallze method in JDK introspector, the source code is as follows:

public static String decapitalize(String name) {
        if (name == null || name.length() == 0) {
            return name;
        }
        // 1. 如果第一个字母和第二个字母都为大写的情况,不做任何处理直接返回,也是就是id 是类名
        if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) &&
                        Character.isUpperCase(name.charAt(0))){
            return name;
        }
        // 2. 否则就将首字母小写
        char chars[] = name.toCharArray();
        chars[0] = Character.toLowerCase(chars[0]);
        return new String(chars);
}

Summarize:

When registering a bean object using the five major types of annotations, the bean object is obtained (getBean() method) by default. You only need to lowercase the first letter of the class name as the parameter of the getBean() method; when the first letter of the class and the first letter of the class When the two first letters are capitalized, we need to use the original class name as the parameter of the getBean() method to get the bean object.

We can also manually perform naming operations on bean objects on class annotations:

[Class annotation] (value = "name")

Here's a concise way of writing it:

Expansion : If there is no directory in the project, how can all the classes be stored in the root directory of java, and how to get the bean object? ? ?

<content:component-scan base-package="**"></content:component-scan>

We can replace the file path with a wildcard "**" in the Spring configuration file. Using a wildcard means that after Spring starts, it will scan from the root directory to find those classes decorated with class annotations, and then instantiate these classes into the container . However, such a result will lead to slower execution speed and very low efficiency, so we suggest adding a suitable path to the project. 


2.5 Method annotation @Bean

Class annotations are added to a class. As the name suggests, method annotations are used to modify methods. The prerequisite for using method annotations (@Bean) is that objects need to be stored in the Spring container normally with class annotations, and the The return value of the method needs to be the same type as the expected storage Bean object:

@Component
public class StudentDemo {
    @Bean
    public Student getStu() {
        //1. 创建对象
        Student student = new Student();
        //2. 初始化对象
        student.setId("1");
        student.setName("李小四");
        student.setSex("男");
        student.setAge(18);
        //3. 返回对象
        return student;
    }
}

The function of the above code is that the StudengDemo class modified by the @Component annotation is scanned after Spring starts. Naturally, it needs to be instantiated into the Spring container. During the instantiation process, a @Bean annotation is found, which means that if you want to instantiate StudengDemo Class, then you have to modify the @Bean so that the Student object (Bean object) returned by the getStu() method is registered in Spring. The execution results are as follows:

At this point, we can make a slight modification to provide a construction method for the StudentDemo class and the Student class, so we can judge which class is loaded first? Note: We need to remove the class annotations on the Student class first, otherwise two bean objects will be stored in Spring, and the storage of multiple bean objects of the same type will be described below...

Note: By default, there is no default ID for storing Bean objects through method annotations, so we can manually set the ID (name) for Bean objects through type acquisition.

Conclusion: The method annotation @Bean can also register the object in Spring, provided that it needs to be used with the class annotation.

In the above code, the Student bean object registered by the @Bean method annotation needs to depend on the instance of the StudentDemo class. When we start Spring, the StudentDemo class will be loaded first, and the construction method will be executed. During the loading process, we find a need to execute the getStu() method ( Set properties), so first instance Student, and then instance StudentDemo, this one involves five stages of JVM loading classes - the life cycle of the Bean object, the next blog will tell you about it~~

Class A depends on Class B, so first, class B is instanced into Spring, and there is no annotation to dynamically extract the Bean object, so this example is not appropriate. I will talk about it later~~~


2.5.1 Bean object renaming

The @Bean annotation can be used to name the bean object by setting the name attribute:

 @Bean(name = "***")

name is actually an array, so a bean object can have multiple names:

@Bean(name = {"student", "李小四"})

 name = {} can also be omitted:

 @Bean({"student", "李小四"})

Note: When we give the Bean a name, the default name used cannot be used! ! !

The above is the whole content of storing bean objects in Spring by using annotations. If there is anything wrong, please criticize and correct


 My years are wasted, and my whole body is tired.

Guess you like

Origin blog.csdn.net/zzbzxzzdf/article/details/131614344