原创

使用Lombok构造器注入bean代替@Autowired,是代码更加简洁

大家平时使用Spring依赖注入,都是怎么写的?

@Service
public class OrderService {
   @Autowired
   private UserService userService;
}

Spring中的bean可以使用@Autowire注解进行自动装配注入。其中有三种方式:

  1. Constructor-based dependency injection 基于构造函数的依赖注入

  2. Setter-based dependency injection 基于setter方法的依赖注入

  3. Field-based dependency injection 基于属性字段的依赖注入

为什么不推荐使用属性注入?

  • 属性注入字段不允许用final修饰 *
    基于属性字段的注入得到的bean不允许声明为final类型。只能通过基于构造函数的注入来声明不可变的bean(immutable bean)。

  • 违反单一原则*
    如果过多地使用属性注入,很容易写很多个bean进行装配。而使用构造注入时,bean作为构造函数的参数,如果数量太多,更容易让人发现该类包含了太多协作者(违反了单一原则),进而将类拆分为更小、更易于维护的碎片。

和Spring的IOC机制紧耦合
当使用基于字段的依赖注入方式,完全把控制权全给Spring的IOC机制,在Spring容器之外,其它类无法重新设置某个注入的属性bean(反射机制除外)。

不方便对注入的bean进行校验
基于字段的依赖注入方式,类构造时并没有拿到被注入的属性的值,只有在被业务使用的时候才会拿到,不方便对该属性进行校验。假如使用构造注入,就可以在构造函数中进行校验,比如非空校验(避免NPE)。当然使用Spring的校验注解也可以实现。

隐藏了依赖关系
当使用Spring的IOC的时候,被注入的类应当使用一些public类型(构造方法,和setter类型方法)的方法来向外界表达:我需要什么依赖。基于字段的依赖注入的方式,基本都是private形式的,外界不易理解所有依赖关系。

总结

避免使用基于字段的依赖注入,推荐使用基于构造函数和基于setter的依赖注入。对于必需的依赖项,建议使用基于构造函数的注入,并声明为final类型,同时可以在构造函数中校验防止它们为null。对于可选的依赖项,建议使用基于Setter的注入。

下面就是Spring推荐的写法

@Service
public class OrderService {
    private final UserService userService;
    @Autowired
    public OrderService(UserService userService) {
        this.userService = userService;
    }
}

利用Lombok编写优雅的Spring依赖注入代码

@RequiredArgsConstructor也是在类上使用,但是这个注解可以生成带参或者不带参的构造方法。

若带参数,只能是类中所有带有 @NonNull注解的和以final修饰的未经初始化的字段

@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class OrderService {
    //这里必须是final,若不使用final,用@NotNull注解也是可以的
    private final UserService userService;

    @NotNull
    private PayService payService;
}
@Service
@RequiredArgsConstructor
public class OrderService {
    //这里必须是final,若不使用final,用@NotNull注解也是可以的
    private final UserService userService;

    @NotNull
    private PayService payService;
}
正文到此结束
该篇文章的评论功能已被站长关闭