Spring的三种注入方式

一、属性注入

@Resource和@Autowired的区别

为什么尽量使用 @Resource? 

二、setter 注入 

三、构造器注入

具体可以看看Spring官网

为什么构造器注入不需要 @Autowired 或 @Resource 注解?


Spring的三种注入方式

Spring有三种注入方式,分别是——属性注入、setter 注入、构造器注入 

java 构造注入 spring构造器注入注解_java 构造注入

一、属性注入

这种方式是最常用的,我们可以使用 @Autowired 或者是 @Resource 进行注入

@RestController
@RequestMapping("/shop")
public class ShopController {

    @Resource
    public IShopService shopService;

    /**
     * 根据id查询商铺信息
     * @param id 商铺id
     * @return 商铺详情数据
     */
    @GetMapping("/{id}")
    public Result queryShopById(@PathVariable("id") Long id) {
        //return Result.ok(shopService.getById(id));
        return shopService.queryById(id);
    }
}

使用方式是最简单,但是也是最不推荐的!要使用也是推荐使用 @Resource

@Resource和@Autowired的区别

为什么尽量使用 @Resource? 

看看我写的这一篇文章!!! 

@Autowired 和 @Resource 的区别(为什么更推荐使用@Resource ?)_面向鸿蒙编程的博客-CSDN博客@Autowired和@Resource注解的区别,趣头条面试官:@Resource和@Autowired有啥区别?,@Autowired 和 @Resource 的区别,【Java面试】面试被问:ConcurrentHashMap 底层实现原理?(3)如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常。,找到之后把具体的值赋值到userDao中去(但是如果找到多个的话,会报错!

二、setter 注入 

这种方法是 Spring3.X 版本比较推荐的,但是我基本上没有见到有人用过!

@Controller
public class DemoController {
  private DemoService demoService;
   
  @Autowired
  public void setDemoService(DemoService demoService) {
      this.demoService = demoService;
  }
}

用法大概就像上面的那样,在 set方法 上面加上注解即可。 

三、构造器注入

这就是目前 Spring 最为推荐的注入方式,直接通过带参构造方法来注入。

这种方式我有在项目中有看到有人用过,但是也不是很多。

// 部分代码
@Component
public class RedisIdWorker {

    private StringRedisTemplate stringRedisTemplate;

    public RedisIdWorker(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }
}

关于构造器注入Spring在文档里是这么说的

The Spring team generally advocates constructor injection as it enables one to implement application components as immutable objects and to ensure that required dependencies are not null. Furthermore constructor-injected components are always returned to client (calling) code in a fully initialized state.

这个构造器注入的方式啊,能够保证注入的组件不可变,并且确保需要的依赖不为空。此外,构造器注入的依赖总是能够在返回客户端(组件)代码的时候保证完全初始化的状态

单一职责: 当使用构造函数注入的时候,你会很容易发现参数是否过多,这个时候需要考虑你这个类的职责是否过大,考虑拆分的问题;而当使用@Autowired注入field的时候,不容易发现问题

依赖不可变: 只有使用构造函数注入才能注入final

依赖隐藏:使用依赖注入容器意味着类不再对依赖对象负责,获取依赖对象的职责就从类抽离出来,IOC容器会帮你自动装备。这意味着它应该使用更明确清晰的公用接口方法或者构造器,这种方式就能很清晰的知道类需要什么和到底是使用setter还是构造器

降低容器耦合度: 依赖注入框架的核心思想之一是托管类不应依赖于所使用的DI容器。换句话说,它应该只是一个普通的POJO,只要您将其传递给所有必需的依赖项,就可以独立地实例化。这样,您可以在单元测试中实例化它,而无需启动IOC容器并单独进行测试(使用一个可以进行集成测试的容器)。如果没有容器耦合,则可以将该类用作托管或非托管类,甚至可以切换到新的DI框架。

具体可以看看Spring官网

java 构造注入 spring构造器注入注解_依赖注入_02

Setter injection versus constructor injection and the use of @Required (spring.io)

https://spring.io/blog/2007/07/11/setter-injection-versus-constructor-injection-and-the-use-of-required

Field Dependency Injection Considered Harmful | Vojtech Ruzicka's Programming Blog


https://www.vojtechruzicka.com/field-dependency-injection-considered-harmful/

为什么构造器注入不需要 @Autowired 或 @Resource 注解?

这是 Spring 框架自身的一个特性,对于一个 SpringBean 来说,如果其只有一个构造方法,那么 Spring 会使用该构造方法并自动注入其所需要的全部依赖