[Spring] (3) Spring uses annotations to store and read Bean objects


foreword

The previous article introduced in detail the creation of Spring objects and the access operations to Bean objects, but the operation of registering Bean objects through configuration files and obtaining Bean objects by using or is extraordinarily ApplicationContextcomplicated BeanFactory. Therefore, this article mainly introduces in detail a simpler way to realize simpler storage and reading operations on Bean objects.

In Spring, if you want to注解 store and use Bean objects more easily, the core is to use them. This article mainly demonstrates how to use annotations to implement access operations on Bean objects.

1. Use annotations to store Bean objects

When storing Bean objects before, it is necessary to spring-congigadd a line to the file <bean>, and each time a Bean object needs to be added to the Spring container, a new line needs to be added, which is very troublesome.

But now you only need to use one 注解to replace the content of this line <bean>, which becomes very convenient at this time. If you want to store objects in the Spring container through annotations, there are two main types of annotations:

  1. Use class annotations (five categories of annotations):

    • @Controller(Control storage): Verify the legitimacy of the data requested by the user, which is equivalent to a security system;
    • @Service(Service Storage): Used to orchestrate and schedule specific execution methods;
    • @Repository(warehouse storage): Persistence layer, exchange with database;
    • @Component(Component storage): Equivalent to tools;
    • @Configuration(config storage): Some configurations in the project.
  2. Notes on how to use:

    • @Bean: It acts on the method and needs to be used in conjunction with the above class annotations.

But before that, you need to configure it 扫描路径.

1.1 Configure scan path

Add the following line of records in spring-config.xmlthe file:

the meaning is to specify one, base packagethat is, all Bean objects that need to be added to the Spring container are under base packagethe specified package or its subpackage. The package I know here is com.spring.demo, which means that if the Bean object is not under this package, even if it is annotated, it will not be added to the Spring container.

1.2 Class annotations store Bean objects

1.2.1 @Controller (controller storage)

Use @Controllerannotations to store Bean objects:

@Controller
public class StudentController1 {
    
    
    public void sayHi(){
    
    
        System.out.println("do studentController1 sayHi().");
    }
}

The way to ApplicationContextget the Bean object is:

public static void main(String[] args) {
    
    
    ApplicationContext context =
            new ClassPathXmlApplicationContext("spring-config.xml");

    StudentController1 studentController1 =
            context.getBean("studentController1", StudentController1.class);

    studentController1.sayHi();
}

关于 Bean 对象的命名规则可见后文。

1.2.2 @Service (service storage)

Use @Serviceannotations to store Bean objects:

@Service
public class StudentController2 {
    
    
    public void sayHi(){
    
    
        System.out.println("do studentController2 sayHi().");
    }
}

Get the Bean object:

StudentController2 studentController2 =
        context.getBean("studentController2", StudentController2.class);

1.2.3 @Repository (warehouse storage)

Use @Repositoryannotations to store Bean objects:

@Repository
public class StudentController3 {
    
    
    public void sayHi(){
    
    
        System.out.println("do studentController3 sayHi().");
    }
}

Get the Bean object:

StudentController3 studentController3 =
        context.getBean("studentController3", StudentController3.class);

1.2.4 @Component (component storage)

Use @Componentannotations to store Bean objects:

@Component
public class StudentController4 {
    
    
    public void sayHi(){
    
    
        System.out.println("do studentController4 sayHi().");
    }
}

Get the Bean object:

StudentController4 studentController4 =
        context.getBean("studentController4", StudentController4.class);

1.2.5 @Configuration (configuration storage)

Use @Configurationannotations to store Bean objects:

@Configuration
public class StudentController5 {
    
    
    public void sayHi(){
    
    
        System.out.println("do studentController5 sayHi().");
    }
}

Get the Bean object:

StudentController5 studentController5 =
        context.getBean("studentController5", StudentController5.class);

1.2.6 Bean Naming Rules

Through the above code, it can be found that when creating a Bean object, the standard "big hump" naming method is used, while when reading, the name of the bean is the first letter of its class name in lowercase, that is, small hump.


However, at this point create a SControllerclass and add it to the Spring container using annotations, so what is the name of its Bean object at this time? According to the rules of the above code, is it still SController?

SController sController = context.getBean("sController", SController.class);

When running the program, I found an error:

it means that there is no sControllersuch Bean object with the name. SControllerWould it be correct to change it to ?


At this time, the discovery can run normally.

Source code for Bean name generation:

  1. Find beanname, select AnnotationBeanNameGeneratorclass
  2. keep looking

  1. keep looking


4. Found the source code, that is, the method Introspectorunder the class. This method checks whether the first letter of the string is uppercase, and if the second character is also uppercase, it directly returns the original string without lowercase processing. This is done to avoid some special cases, such as abbreviations or acronyms, from being mishandled.decapitalize

1.3 The role of the five categories of annotations

In the Spring framework, five commonly used annotations are: @Component, @Controller, @Service, @Repository and @Configuration.

  • @Component: A general component annotation, indicating that the class is a Spring-managed component (Bean).

  • @Controller: Used to identify the controller class, usually used in Spring MVC, to handle HTTP requests and view rendering.

  • @Service: Used to identify the service class, indicating that the class provides some business logic processing.

  • @Repository: Used to identify the warehouse class, indicating that this class is used for data access, usually interacting with the database.

  • @Configuration: It is used to identify the configuration class, indicating that the class contains Spring configuration information, and is usually @Beanused together with to define beans.

1.3.1 Why are there so many annotations

Through the demonstration of the above code, it is found that the functions of these annotations are the same. Since they are all the same, why do we need so many different annotations?

The reason why Spring provides so many annotations is to better organize and manage application components and dependencies . Because each annotation has its own specific purpose, it makes it easier for developers to identify and distinguish different types of classes in the application . At the same time, the project hierarchy of the program is also withdrawn:

  1. Among them @Controllerrepresents the control layer, which is responsible for interacting with users and verifying the legitimacy of data submitted by users;
  2. @ServiceIt represents the service layer, which is used to arrange and dispatch specific execution methods, which is equivalent to the service desk in the station;
  3. @RepositoryRepresents the persistence layer, which is responsible for persistent storage of data and usually needs to interact with the database.

The above three levels realize the engineering layering of the program, and are also the core layering of the Java EE standard layering.

1.3.2 Relationship between class annotations

  • Looking at @Controller / @Service / @Repository / @Configurationthe source code of annotations such as and found that:
    they are all @Componentsubclass annotations, which means that @Controller / @Service / @Repository / @Configurationclasses marked as are also considered @Component.

  • In addition, @Configurationthe annotation is a special annotation that indicates that this class is a Spring configuration class used to define beans and configure other elements of the application. Annotations in configuration classes @Beanare used to define beans.

1.4 Method annotations store Bean objects

First create a User entity class:

package com.spring.demo.entity;

/**
 * 普通的用户实体类
 */
public class User {
    
    
    private Integer uid;
    private String username;
    private String password;
    private Integer age;

    public Integer getUid() {
    
    
        return uid;
    }

    public void setUid(Integer uid) {
    
    
        this.uid = uid;
    }

    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{" +
                "uid=" + uid +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", age=" + age +
                '}';
    }
}


1.4.1 Use of @Bean annotation

Create a component class UserBeansand @Beanadd the User class to the Spring container using method annotations:

@Controller
public class UserBeans {
    
    
    @Bean
    public User getUser(){
    
    
        User user = new User();
        user.setUid(1);
        user.setUsername("王五");
        user.setPassword("123456");
        user.setAge(18);
        return user;
    }
}

Note that @Beanwhen using method annotations, five types of annotations need to be used to take effect.

Get the Bean object:

public static void main(String[] args) {
    
    
    ApplicationContext context =
            new ClassPathXmlApplicationContext("spring-config.xml");

    User user = context.getBean("getUser", User.class);
    System.out.println(user);
}

Note that when using method annotations @Bean, the default name of the Bean object is the name of the method it adds to the Spring container.

1.4.2 Bean object renaming

If you directly use the method name as the name of the Bean object, for example, getUserit seems very unreasonable, so it is often necessary to rename the Bean. But @Beanwhen you look at the source code, you can find that the nameor valueattribute is an array, which means that a Bean object can take multiple names.

For example:

At this point, the Bean object can be obtained through these two names, and they are found to be the same Bean:

Another thing to note is that if the Bean is renamed, the original default method name will become invalid.

2. Use annotations to get Bean objects

2.1 The method of obtaining the Bean object through annotation

Obtaining the Bean object is also called 对象装配, that is, taking the object out and putting it in a certain class, and it is also called 对象注入.

There are three ways to implement object injection:

  1. Property Injection : Property injection is achieved by using annotations on properties. Common annotations are @Autowiredand @Resource. Property injection is directly injected into the property of the Bean object without providing settera method.

  2. SetterInjection : Injection is achieved Setterby using annotations on the methods of the Bean object . setterThis injection method is to pass in the dependent object as a parameter when calling the Bean's settermethod.

  3. Constructor injection : Constructor injection is achieved by using annotations on the Bean object's constructor. This injection method is to pass in the dependent object through the constructor parameter when creating the Bean object.

2.2 Use of three injection methods

Following the pattern in actual development, inject the Service class into the Controller class, and then mainobtain the Bean object in the Controller through the method.
First create a UserServiceclass and UserControllerclass:


@Service
public class UserService {
    
    
    public void sayHi(){
    
    
        System.out.println("hi, userService.");
    }
}

2.2.1 Attribute injection

@Controller
public class UserController {
    
    
    // 1. 属性注入
    @Autowired
    private UserService userService;

    public void sayHi(){
    
    
        System.out.println("do userController sayHi().");

        userService.sayHi();
    }
}

2.2.2 Setter injection

@Controller
public class UserController {
    
    
    // 2. setter 注入
    private UserService userService;

    @Autowired
    public void setUserService(UserService userService) {
    
    
        this.userService = userService;
    }
    
    public void sayHi(){
    
    
        System.out.println("do userController sayHi().");

        userService.sayHi();
    }
}

2.2.3 Constructor injection

@Controller
public class UserController {
    
    
    // 3. 构造方法注入
    private UserService userService;

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

    public void sayHi(){
    
    
        System.out.println("do userController sayHi().");

        userService.sayHi();
    }
}

Note that if there is only one constructor at this time, @Autowiredcan be omitted.

2.3 Advantages and disadvantages of the three injection methods

attribute injection

  1. Advantages: concise, less code, suitable for direct injection of attributes;
  2. shortcoming:
    • For properties that must be injected, if no matching Bean is found, a runtime error will result;
    • Compatibility is not good, it can only be used for IoC container;
    • There is no way to achieve finallyinjection of modified variables;
    • Too simple, easy to violate the single design principle.

Setter injection:

  1. Advantages: In line with the single design principle, each method can only pass one object.

  2. shortcoming:

    • There is no way to achieve finallyinjection of modified variables;
    • Objects injected using Setters may be modified.

Constructor injection:

  1. advantage:

    • finallyModified variables can be implemented to achieve injection;
    • The injected object will not be changed, that is, the constructor can only be executed once;
    • Constructor injection ensures that the injected object is fully initialized.
  2. Disadvantages: When the construction method has many parameters, the code becomes tedious.

2.4 @Resource injection

When performing class injection, in addition to using @Autowiredthe keyword, we can also use @Resourcefor injection, as shown in the following code:

Property injection:

public class UserController {
    
    
    // 1. 属性注入
    @Resource
    private UserService userService;

    public void sayHi(){
    
    
        System.out.println("do userController sayHi().");

        userService.sayHi();
    }
}

Setter injection:


@Controller
public class UserController {
    
    

    // 2. setter 注入
    private UserService userService;
    
    @Resource
    public void setUserService(UserService userService) {
    
    
        this.userService = userService;
    }

    public void sayHi(){
    
    
        System.out.println("do userController sayHi().");

        userService.sayHi();
    }
}

Unfortunately, @Resourceconstructor injection is not supported:

2.5 The difference between @Autowired and @ Resource

  1. @AutowiredIt is an annotation provided by the Spring framework, not @Resourcean annotation provided by the JSR-250 specification, but Spring also supports it.
  2. @AutowiredBeans are assembled by type by default. If multiple types match, @Qualifierspecific bean names can be specified with annotations. By @Resourcedefault, it is assembled according to the attribute name, and a specific Bean name can be specified through the name attribute.
  3. @AutowiredIt is Spring's proprietary annotation, which is more flexible and powerful. @Resourceare standard Java annotations for more general cases
  4. @AutowiredCan be used for Setterinjection, constructor injection and property injection, and @Resourcecan only be used for Setterinjection and property injection, not for constructor injection.

2.6 Injecting multiple @Beans of the same type and reporting errors

When multiple Bean objects of the same type exist and need to be injected into other Bean objects through annotations, if the Bean to be injected is not clearly specified, an error will be reported.

2.6.1 Error reporting problem

UserBeansFor example, inject User into Controller in Controller through in Component UserController.

First, add two User objects to the Spring container UserBeansusing :@Bean

@Controller
public class UserBeans {
    
    
    @Bean(name = {
    
    "user1", "u1"})
    public User getUser1(){
    
    
        User user = new User();
        user.setUid(1);
        user.setUsername("张三");
        user.setPassword("123456");
        user.setAge(18);
        return user;
    }

    @Bean(name = "user2")
    public User getUser2(){
    
    
        User user = new User();
        user.setUid(1);
        user.setUsername("李四");
        user.setPassword("123456");
        user.setAge(18);
        return user;
    }
}

Use and inject UserControllerrespectively in to get the Bean object:@Autowired@Resource

@Autowired:

At this point, since there are two Bean objects of the same type but with different names, the @Autowiredannotation does not know which object to obtain.

@Resource

@ResourceIt is also impossible to determine which object to get by using annotations.

Regarding the order in which @Autowiredand @Resourcefind Bean objects:

  • @AutowiredSearch by type first, then by name;
  • @ResourceLook up first by name, then by type.

2.6.2 Use @Resource(name="XXX") to solve

@Controller
public class UserController {
    
    

    @Resource(name = "user1")
    private User user;

    public void sayHi(){
    
    
        System.out.println("do userController sayHi().");
    }
}

2.6.3 @Autowired with @Qualifier to solve

@Controller
public class UserController {
    
    

    @Autowired
    @Qualifier(value = "user1")
    private User user;

    public void sayHi() {
    
    
        System.out.println("do userController sayHi().");
    }
}

Guess you like

Origin blog.csdn.net/qq_61635026/article/details/132080955