Spring Boot - @Autowired vs. (final + constructor)

演示

代码定义

UserService.java 定义了函数 findByUserName()

public interface UserService {
    User findByUserName(String userName);
}

UserServiceImpl.java 是实现类,通过UserMapper.java / UserMapper.xml 实现查询功能。

@Service
public class UserServiceImpl implements UserService {
    private InformationVerification informationVerification = new InformationVerification();

    @Autowired
    UserMapper userMapper;

    @Override
    public User findByUserName(String userName) {
        return (userMapper.selectByUserName(userName) != null ? userMapper.selectByUserName(userName) : null);
    }
}

UserMapper.java

@Component
public interface UserMapper {
   User selectByUserName(String userName);
}

UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.test.mapper.UserMapper">
    ...

    <select id="selectByUserName" resultType="com.test.entity.User">
        SELECT * FROM user WHERE userName = #{userName};
    </select>
</mapper>

UserService -> UserServiceImpl -> UserMapper.java -> UserMapper.xml

以上是各个文件之间的依赖关系。

实现方式1

@RestController
@RequestMapping("test/user")
public class UserController {
    @Autowired
    UserService userService;

    @GetMapping("findByUserName")
    public Result<User> findByUserName(@RequestParam("userName") String userName) {
        return new Result<User>().success(userService.findByUserName(userName));
    }
}

通过@Autowired注入。

实现方式2

@RestController
@RequestMapping("test/user")
public class UserController {
    private final UserService userService;

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

    @GetMapping("findByUserName")
    public Result<User> findByUserName(@RequestParam("userName") String userName) {
        return new Result<User>().success(userService.findByUserName(userName));
    }
}

final + 构造函数,完成注入。

实现方式3

@RestController
@RequestMapping("test/user")
@RequiredArgsConstructor
public class UserController {
    private final UserService userService;

    @GetMapping("findByUserName")
    public Result<User> findByUserName(@RequestParam("userName") String userName) {
        return new Result<User>().success(userService.findByUserName(userName));
    }
}

利用Lombok插件的@RequiredArgsConstructor,完成构造函数。

准确的说,实现方式2与实现方式3是同一种方法,只不过方式3借助Lombok简化了代码而已。

为何使用final修饰成员变量?

Springboot官方建议使用final来修饰成员变量,然后通过构造方法来进行注入。

注意:final修饰的成员变量是不能够被修改的,

1. 防止已经注入的成员变量被修改。

2. 避免以后因修改代码,例如将方法的返回值更新为null,而造成恶劣影响。

Lombok 构造器注解

注解构造函数参数非空校验备注
@NoArgsConstructor无参可使用参数
@RequiredArgsConstructor未初始化的final字段、标注为nonnull的字段可使用参数@RequiredArgsConstructor(staticName = “of”),将构造方法私有化,并提供静态函数of创建构造函数。
@AllArgsConstrutor所有字段有可使用参数@AllArgsConstrutor(access = AccessLevel.PROTECTED)来控制构造函数的访问级别。

 

 

 

 

 

  • @NoArgsConstructor

@NoArgsConstructor
用于生成无参构造函数。如果因为final字段未初始化导致构造失败,则会导致编译失败。可以使用@NoArgsConstructor(force
= true)参数,从而强制将未初始化的fianl字段赋值为 0 / false / null。 对于具有约束的字段(例如 @NonNull 字段),不会进行检查。因此请注意,正确初始化这些字段之前,这些约束无效。

  • @RequiredArgsConstructor

@RequiredArgsConstructor
为有需要特殊处理的字段生成带有一个参数的构造函数,所有未能初始化的fianl字段,以及被标记为@NonNull且在声明时没有初始化的字段,都是该构造函数的参数。
参数的顺序与类中字段出现的顺序是保持一致的,对于@NonNull的字段也会进行空值检查,如果不符合校验规则,抛出空指针异常。

  • @AllArgsConstructor

@AllArgsConstructor:为类中的每个字段生成一个具有1个参数的构造函数。 标记为@Non Null的字段会进行空值检查。

  • 9
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
好的,下面是一个使用`spring-boot-starter-amqp`、`application.yml`和`controller`的代码案例。 在`pom.xml`文件中添加以下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency> ``` 在`application.yml`文件中添加以下配置: ```yml spring: rabbitmq: host: localhost port: 5672 username: guest password: guest ``` 这里配置了RabbitMQ的连接信息,包括主机名、端口、用户名和密码。 在`controller`中注入`AmqpTemplate`,用于发送消息。 例如: ```java @RestController public class MyController { @Autowired private AmqpTemplate rabbitTemplate; @PostMapping("/send") public String send(@RequestBody String message) { rabbitTemplate.convertAndSend("myexchange", "myroutingkey", message); return "Message sent: " + message; } } ``` 这个例子中,我们注入了`AmqpTemplate`,用于发送消息。在`send`方法中,我们使用`convertAndSend`方法发送消息到名为`myexchange`的交换器,并指定路由键为`myroutingkey`。 在代码中可以通过`@EnableRabbit`注解开启RabbitMQ支持,然后使用`@RabbitListener`注解指定消息监听方法。 例如: ```java @SpringBootApplication @EnableRabbit public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } @RabbitListener(queues = "myqueue") public void processMessage(String content) { System.out.println("Received message: " + content); } } ``` 这个例子中,我们使用`@RabbitListener`注解指定了一个名为`myqueue`的队列,当消息到达这个队列时,`processMessage`方法将被调用,打印出接收到的消息内容。 当然,还有其他更复杂的用法,比如配置交换器、队列等等。你可以参考Spring Boot官方文档和RabbitMQ官方文档了解更多信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值