spring常用的注入方式分为三种:属性注入,setter注入,构造器注入。
属性注入缺点:
1、容易违背单一职责(通常因为使用过多的依赖而未察觉)
2、类和容器强耦合。对于IOC容器以外的环境,只能通过反射提供它需要的依赖
3、可能在属性注入前就被引用,导致NPE;也可能注入失败,导致NPE无法尽早暴露,因为不调用就不会发现。
3、可测试性差(要测试一个类必须启动整个IOC,这还不够可恶吗)
4、循环依赖无检测,有循环依赖隐患
构造器注入:
定义私有final变量,使用构造器传递参数并初始化,构造器添加@Autowired(如果使用spring 4.3+,可以完全将类与DI框架解耦。其支持一个构造函数场景的隐式构造函数注入)(可用lombok的@RequiredArgsConstructor)
优点:
1、保证依赖不为空,保证依赖不可变
2、保证调用时是完全初始化状态,方便单元测试;提升了代码的可复用性;明确成员变量的注入顺序
3、避免了循环依赖(循环依赖通常是糟糕设计的标志)
缺点:注入参数较多时,代码臃肿,不够友好。但这更好地提醒了单一职责。
setter注入:
定义对应的setter并添加@Autowired。setter注入类似于选择性注入,允许在类构造完成后重新注入。使用setter注入依赖项。类应该能够在不提供它们的情况下工作。在对象实例化之后,可以随时更改依赖项。
应尽量避免Field注入。推荐使用构造函数或方法注入依赖项。两者各有利弊,用法取决于具体情况。可以结合setter注入和构造函数注入,构造函数更适合于强制依赖项和以不变性为目标的情况。对于可选的依赖项更适合setter注入。
如果一定要使用@Autowired,替换为@Resource注解。至少idea不警告,不会看着难受。
@Autowired,@Qualifier,@Resource区别
@Autowired:通过byType装配,找不到或找到多个都抛出异常。
@Qualifier:使用@Qualifier指定@Autowired进行byName装配
@Resource:相当于@Autowired,但@Resource默认按照byName装配, 如果没有匹配,则退回到byType方式装配。@Resource是Javax包提供的,不依赖于Spring框架,可以方便替换Ioc容器框架。