什么?一直用的@Autowired居然被IDEA警告了

175 阅读3分钟

依赖注入优化

问题起因

在IDEA中,当我们使用@Autowired的时候,会提示不建议使用字段注入

image.png

有哪些注入方式(三种)

1. 字段注入

开发较为常用的就是字段注入。

@Autowired
private UserService userService;
2. set方法注入

也用到了@Autowired注解,但使用方式不同。

字段用在成员变量,set用在成员变量的setter函数上。

private UserService userService;

@Autowired
public void setUserService(UserService userService){
    this.userService = userService;
}
3. 构造方法注入(最推荐)

最推荐的一种方式,but这样的流程比较麻烦,后面有简化流程

private final UserService userService;

public UserController(UserService userService){
    this.userService = userService;
}
三种方式对比

image-20240728212017802.png

总结:

  • 构造器注入可靠稳定,只是不灵活,性能差。
  • 字段注入和set可靠性和可维护性差。

字段注入缺点

  1. 基于属性注入的方式, 违背单一职责原则

    因为现在的业务一般都会使用很多依赖, 但拥有太多的依赖通常意味着承担更多的责任,而这显然违背了单一职责原则. 并且类和依赖容器强耦合,不能在容器外使用。

  2. 基于属性注入的方式, 容易导致Spring 初始化失败

    因为现在在Spring特别是Spring Boot使用中, 经常会因为初始化的时候, 由于属性在被注入前就引用而导致npe(空指针错误), 进而导致容器初始化失败(类似下面代码块). Java 在初始化一个类时, 是按照 静态变量或静态语句块 –> 实例变量或初始化语句块 –> 构造方法 -> @Autowired 的顺序。 所以在执行这个类的构造方法时,person 对象尚未被注入,它的值还是 null。

  3. 通过@Autowired 注入, 又因为是 byType 注入, 因此有可能会出现两个相同的类型bean

    如下代码快, 就会产生两个相同的Bean, 进而导致Spring 装配失败.

//2. 基于属性注入的方式, 容易导致Spring 初始化失败
@Autowired
private Person person;

private String company;

public UserServiceImpl(){   // 构造方法在person注入之前创建,会初始化失败
    this.company = person.getCompany();
}


//3. 通过@Autowired 注入, 又因为是 ByType 注入, 因此有可能会出现两个相同的类型bean
public interface IUser {
    void say();
}

@Service
public class User1 implements IUser{
    @Override
    public void say() {
    }
}

@Service
public class User2 implements IUser{
    @Override
    public void say() {
    }
}

@Service
public class UserService {

    @Autowired
    private IUser user;   //在这,可能会出现两个相同类型的Bean
} 

解决办法

1. 要用字段注入,可以用@Resource代替

两者作用相当,@Resource支持byName指定名称装配@Resource(name = "userinfo")

2. 构造注入(十分推荐)

上面已介绍,现在是简化流程,使用Lombok的注解@RequiredArgsConstructor,更方便。

这个注解的意思是必备的构造函数,意思是对一开始就需要初始化的变量做构造,所以需要在需要注入的对象上加final关键字,因为常量在类的创建就要构造。

@RequiredArgsConstructor
public class UserController {
    private final UserService userService;
    }

PS:@Autowired和@Resource的区别

1. 来源不同

@Autowired是Spring框架的注解,@Resource是Java定义的注解。

2. 依赖查找顺序不同

依赖注入的功能,是通过先在 Spring IoC 容器中查找对象,再将对象注入引入到当前类中。

分为按名称byName和按类型byType。

  • @Autowired先byType,再byName。
  • @Resource先byName,再byType。
3. 支持参数不同

@Autowired 只支持设置1个 required 的参数,而 @Resource 支持 7 个参数

4. 依赖注入的支持不同

@Autowired 支持属性注入、构造方法注入和 Setter 注入。

@Resource 只支持属性注入和 Setter 注入。

5. 编译器提示不同

注入Mapper时用@Autowired会报错,但是可以运行。

PS OF PS:@Qualifier

使用@Autowired,当容器中存在多个 Bean 的类型与需要注入的相同时,注入将不能执行。

此时要使用byName匹配,就要请出@Qualifier

private Person p;

@Autowired(required=false) 
@Qualifier("ppp") // 如果有好几个Person的实现类,那就通过"ppp"这个名字去匹配类名
public void setPerson(Person p){}





参考&鸣谢

blog.csdn.net/qq_43371556… developer.aliyun.com/article/100…