「JavaEE」Spring IoC:依赖注入

依赖注入描述的是一个过程,指的是 IoC 容器在创建 Bean 时, 提供运行时所依赖的对象

通俗来讲就是把对象取出来放到某个类的属性中

Spring 提供了三种依赖注入的方式:

  1. 属性注入(Field Injection)

  2. 构造方法注入(Constructor Injection)

  3. Setter 注入(Setter Injection)

下面我们使用这三种方式分别将 Service 类注入到 Controller 类中


属性注入

使用 @Autowired 实现(autowire 意为自动装配)

@Controller
public class UserController {
    @Autowired
    private UserService userService;

    public void hello() {
        System.out.println("UserController...");
        userService.hello();
    }
}
@Service
public class UserService {
    public void hello() {
        System.out.println("UserService...");
    }
}
@SpringBootApplication
public class ApplicationController {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(ApplicationController.class, args);
        UserController userController = (UserController) context.getBean("userController");
        userController.hello();
    }
}

运行结果:


构造方法注入

构造方法注入就是在类的构造方法中注入依赖

@Controller
public class UserController {
    private UserService userService;

    public void hello() {
        System.out.println("UserController...");
        userService.hello();
    }

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

注意:

① 如果类只有一个构造方法,那么 @Autowired 可以省略;如果有多个构造方法,那就需要加上这个注解指定要用哪个构造方法,如果没有指定,默认使用无参的构造方法

② 一般如果自己写了有参构造方法的话,建议把无参的构造方法也写出来


Setter 注入

这个也顾名思义,就是在 setter 方法上加 @Autowired

@Controller
public class UserController {
    private UserService userService;

    public void hello() {
        System.out.println("UserController...");
        userService.hello();
    }

    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }
}

@Service
public class UserService {
    public void hello() {
        System.out.println("UserService...");
    }
}

@SpringBootApplication
public class ApplicationController {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(ApplicationController.class, args);
        UserController userController = (UserController) context.getBean("userController");
        userController.hello();
    }
}

运行结果:


三种注入的优缺点分析

  • 属性注入

优点:简洁方便(大部分情况下都用这种注入方式)

缺点:

① 只能用于 IoC 容器

② 不能注入被 final 修饰的属性

  • 构造方法注入

优点:

① 可以注入被 final 修饰的属性

② 注入的对象不会被修改

③ 依赖对象在使用前一定会被完全初始化,因为依赖是在类的构造方法中注入的,而构造方法在类加载阶段就会执行

④ 通用性好。因为构造方法是 JDK 支持的, 所以更换任何框架,它都是适用的。也就是说,不加 @Autowired 也可以顺利注入

缺点:注入多个对象时, 构造方法的代码会比较复杂

  • setter 注入

优点:在类实例化之后, 重新对该对象进行配置或注入比较方便

缺点:

① 也是不能注入被 final 修饰的属性

② 由于 setter 方法可能会被多次调用,所以注入对象有被修改的风险

对于这两种没法注入被 final 修饰的属性,有两种解决方式:

① 在构造方法中赋值

② 在定义时就进行初始化


@Primary、@Qualifier、@Resource

当同一个类存在多个 bean 时, 使用 @Autowired 就会有问题

public class BeanConfig {
    @Bean
    public User user1() {
        User user = new User();
        user.setAge(24);
        user.setName("zhangsan");
        return user;
    }

    @Bean
    public User user2() {
        User user = new User();
        user.setAge(20);
        user.setName("lisi");
        return user;
    }
}
@Controller
public class UserController {
    @Autowired
    private User user;
    @Autowired
    private UserService userService;

    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    public void hello() {
        System.out.println("UserController...");
        userService.hello();
        System.out.println(user);
    }
}



public class UserService {
    public void hello() {
        System.out.println("UserService...");
    }
}

运行报错:有多个 Bean,不知道要把哪个注入到 UserController 的 User 对象

可以用小标题那三个关键字来解决上述问题

使用 @Primary 注解,可以指定 Bean 默认的实现
    @Primary //指定该 bean 为默认 bean 的实现
    @Bean
    public User user1() {
        User user = new User();
        user.setAge(24);
        user.setName("zhangsan");
        return user;
    }


使用  @Qualifier 注解可以指定当前要注入的 bean 对象: @Qualifiervalue 属性中, 指定注入 的 bean 的名称
注意:@Qualifier 注解必须配合 @Autowired 使用,不能单独用,

  • 20
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值