0
点赞
收藏
分享

微信扫一扫

SpringBoot的@Autowired、@Resource、@RequiredArgsConstructor注解的学习

一、概念

@Autowired默认按类型装配,通过@Qualifier注解指定bean的名称也可以做到按名称装配。

@Resource默认按名称装配,通常使用name属性制定bean的名称,当找不到与名称匹配的bean时,才会按类型装配。

@RequiredArgsConstructor 是Lombok中的一个注解,可以简化@Autowired注解,在类上使用这个注解的时候,需要注入的bean用final定义。

二、环境搭建

1.引入依赖

  <!--lomobk-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

完整的pom文件如下所示

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.13</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>MySpringBoot</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>MySpringBoot</name>
    <description>MySpringBoot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--lomobk-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

2.创建实体类

package com.example.myspringboot.bean;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * 测试实体
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {

    private Long id;

    private String name;

}

3.创建服务层接口及两个实现类

package com.example.myspringboot.service;

import com.example.myspringboot.bean.Student;

import java.util.List;

/**
 * @author qx
 * @date 2023/7/3
 * @des 服务层
 */
public interface StudentService {

    List<Student> getAll();
}

package com.example.myspringboot.service;

import com.example.myspringboot.bean.Student;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * @author qx
 * @date 2023/7/3
 * @des 服务层实现类1
 */
@Service
public class StudentServiceImpl1 implements StudentService {
    @Override
    public List<Student> getAll() {
        List<Student> studentList = new ArrayList<>();
        studentList.add(new Student(1L, "aa"));
        studentList.add(new Student(2L, "bb"));
        return studentList;
    }
}

package com.example.myspringboot.service;

import com.example.myspringboot.bean.Student;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * @author qx
 * @date 2023/7/3
 * @des 服务层实现类2
 */
@Service
public class StudentServiceImpl2 implements StudentService {
    @Override
    public List<Student> getAll() {
        List<Student> studentList = new ArrayList<>();
        studentList.add(new Student(3L, "cc"));
        studentList.add(new Student(4L, "dd"));
        return studentList;
    }
}

三、测试@Autowired

测试控制层示例代码如下:

package com.example.myspringboot.controller;

import com.example.myspringboot.bean.Student;
import com.example.myspringboot.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * @author qx
 * @date 2023/7/3
 * @des 测试控制器
 */
@RestController
public class StudentController {

    @Autowired
    private StudentService studentService;

    @GetMapping("/")
    public List<Student> getAll() {
        return studentService.getAll();
    }
}

启动程序

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2023-07-03 11:29:10.271 ERROR 10976 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

Field studentService in com.example.myspringboot.controller.StudentController required a single bean, but 2 were found:
	- studentServiceImpl1: defined in file [D:\javaLearn\MySpringBoot\target\classes\com\example\myspringboot\service\StudentServiceImpl1.class]
	- studentServiceImpl2: defined in file [D:\javaLearn\MySpringBoot\target\classes\com\example\myspringboot\service\StudentServiceImpl2.class]


Action:

Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed


Process finished with exit code 1

我们看到了报错的信息,意思是服务接口有2个实现类,因为@Autowired是按类型装配的,现在就不知道该注入哪一个了。 

解决方法1:

直接注入指定的类名

package com.example.myspringboot.controller;

import com.example.myspringboot.bean.Student;
import com.example.myspringboot.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * @author qx
 * @date 2023/7/3
 * @des 测试控制器
 */
@RestController
public class StudentController {

    /**
     * 指定注入StudentServiceImpl1
     */
    @Autowired
    private StudentService studentServiceImpl1;

    @GetMapping("/")
    public List<Student> getAll() {
        return studentServiceImpl1.getAll();
    }
}

在浏览器访问测试地址,测试成功

SpringBoot的@Autowired、@Resource、@RequiredArgsConstructor注解的学习_spring

解决方法2:

添加@Qualifier注解的value属性指定注入的实现类

package com.example.myspringboot.controller;

import com.example.myspringboot.bean.Student;
import com.example.myspringboot.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * @author qx
 * @date 2023/7/3
 * @des 测试控制器
 */
@RestController
public class StudentController {


    // @Qualifier指定注入StudentServiceImpl2
    @Autowired
    @Qualifier(value = "studentServiceImpl2")
    private StudentService studentService;

    @GetMapping("/")
    public List<Student> getAll() {
        return studentService.getAll();
    }
}

继续在浏览器访问测试地址,测试成功

SpringBoot的@Autowired、@Resource、@RequiredArgsConstructor注解的学习_java_02

四、测试@Resource 

我们在控制层使用@Resource注解并使用name属性指定要注入的实现类

package com.example.myspringboot.controller;

import com.example.myspringboot.bean.Student;
import com.example.myspringboot.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.List;

/**
 * @author qx
 * @date 2023/7/3
 * @des 测试控制器
 */
@RestController
public class StudentController {


    @Resource(name = "studentServiceImpl1")
    private StudentService studentService;

    @GetMapping("/")
    public List<Student> getAll() {
        return studentService.getAll();
    }
}

在浏览器访问测试地址,测试成功

SpringBoot的@Autowired、@Resource、@RequiredArgsConstructor注解的学习_List_03

五、测试@RequiredArgsConstructor 

1.再创建一个服务层UserService

package com.example.myspringboot.service;

import org.springframework.stereotype.Service;

/**
 * @author qx
 * @date 2023/7/3
 * @des 用户实现类
 */
@Service
public class UserService {

    public void list() {
        System.out.println("用户列表");
    }
}

2.修改测试控制层

我们在类上加上@RequiredArgsConstructor注解,并在注入的bean使用final修饰

package com.example.myspringboot.controller;

import com.example.myspringboot.bean.Student;
import com.example.myspringboot.service.StudentService;
import com.example.myspringboot.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * @author qx
 * @date 2023/7/3
 * @des 测试控制器
 */
@RestController
@RequiredArgsConstructor
public class StudentController {


    private final StudentService studentServiceImpl2;
    private final UserService userService;


    @GetMapping("/")
    public List<Student> getAll() {
        // 用户列表
        userService.list();
        return studentServiceImpl2.getAll();
    }
}

启动浏览器测试,分别获取到了StudentService服务和UserService服务中功能。

SpringBoot的@Autowired、@Resource、@RequiredArgsConstructor注解的学习_java_04

我们就可以不使用属性注入(@Autowired@Resource)的方式,直接通过构造器的方式来完成注入,不仅能够省略简化许多代码,也解决了属性注入可能存在的空指针问题。

举报

相关推荐

0 条评论