当前位置: 首页 > article >正文

六、深入了解DI

依赖注入是⼀个过程,是指IoC容器在创建Bean时,去提供运⾏时所依赖的资源,⽽资源指的就是对象. 在上⾯程序案例中,我们使⽤了 @Autowired 这个注解,完成了依赖注⼊的操作. 简单来说,就是把对象取出来放到某个类的属性中。

关于依赖注⼊,Spring也给我们提供了三种⽅式:

1. 属性注入(FieldInjection)

2. 构造⽅法注入(ConstructorInjection)

3. Setter 注入(SetterInjection)

4.1 属性注入

属性注⼊是使⽤ @Autowired 实现的,将Service类注⼊到Controller类中.

Service 类的实现代码如下:

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

Controller 类的实现代码如下:

@Controller
public class UserController {
    @Autowired
    private UserService userService;
    public void sayHi(){
        System.out.println("hi,UserController...");
        userService.sayHi();
    }
}

获取Controller中的sayHi方法:

public class DemoApplication {
    public static void main(String[] args) {
        //获取Spring上下文对象
        ApplicationContext context = SpringApplication.run(DemoApplication.class, args);
        //从Spring上下文中获取对象
        UserController userController = (UserController) context.getBean("userController");

        //使用对象
        userController.sayHi();
   }
}

运行结果: 

去掉@Autowired,再运行⼀下程序看看结果:

4.2 构造方法注入

构造方法注入是在类的构造方法中实现注入,如下代码所示:


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

    public void sayHi() {
        System.out.println("hi,UserController...");
        userService.sayHi();
    }
}

注意事项:如果类只有⼀个构造方法,那么@Autowired 注解可以省略;如果类中有多个构造方法, 那么需要添加上@Autowired 来明确指定到底使用哪个构造方法。

4.3 Setter 注入

Setter 注入和属性的Setter方法实现类似,只不过在设置set方法的时候需要加上@Autowired 注 解,如下代码所示例:

@Controller
public class UserController {

    
    private UserService userService;

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

    public void sayHi() {
        System.out.println("hi,UserController...");
        userService.sayHi();
    }
}

4.4 三种注入优缺点分析

优点缺点
属性注入简洁,使用方便

1、只能⽤于IoC容器,如果是⾮IoC容器不可⽤,并且只有在使⽤的时候才会出现NPE(空指 针异常)

2、不能注⼊⼀个Final修饰的属性

构造函数注入(Spring4.X推荐)

1、可以注⼊final修饰的属性

2、注⼊的对象不会被修改

3、 依赖对象在使⽤前⼀定会被完全初始化,因为依赖是在类的构造⽅法中执⾏的,⽽构造⽅法 是在类加载阶段就会执⾏的⽅法.

4、 通⽤性好,构造⽅法是JDK⽀持的,所以更换任何框架,他都是适⽤的

注⼊多个对象时,代码会⽐较繁琐
Setter注入(Spring3.X推荐)方便在类实例之后,重新对该对象进⾏配置或者注⼊

1、不能注⼊⼀个Final修饰的属性

2、注⼊对象可能会被改变,因为setter⽅法可能会被多次调⽤,就有被修改的⻛险

4.5 @Autowired存在问题

当同⼀类型存在多个bean时,使⽤@Autowired会存在问题

@Component
public class BeanConfig {


    @Bean("u1")
    public UserInfo user1() {
        UserInfo userInfo = new UserInfo();
        userInfo.setName("张三");
        userInfo.setAge(18);
        return userInfo;
    }


    @Bean
    public UserInfo user2() {
        UserInfo userInfo = new UserInfo();
        userInfo.setName("李四");
        userInfo.setAge(20);
        return userInfo;
    }

}
@Controller
public class UserController {


    @Autowired
    UserService userService;

    @Autowired
    UserInfo userInfo;

    public void sayHi() {
        System.out.println("hi,UserController...");
        userService.sayHi();
    }
}

编译时出现报错

 报错的原因是,非唯一的Bean对象。

Spring提供了以下几种注解的解决方案:

• @Primary

• @Qualifier

• @Resource

使用@Primary注解:当存在多个相同类型的Bean注入时,加上@Primary注解,来确定默认的实现.

@Component
public class BeanConfig {
    
    @Primary //指定该bean为默认的bean的实现
    @Bean("u1")
    public UserInfo user1() {
        UserInfo userInfo = new UserInfo();
        userInfo.setName("张三");
        userInfo.setAge(18);
        return userInfo;
    }
    
    @Bean("u2")
    public UserInfo user2() {
        UserInfo userInfo = new UserInfo();
        userInfo.setName("李四");
        userInfo.setAge(20);
        return userInfo;
    }

}

使用@Qualifier注解:指定当前要注⼊的bean对象。在@Qualifier的value属性中,指定注入的bean 的名称。

@Qualifier注解不能单独使用,必须配合@Autowired使用

@Controller
public class UserController {


    @Qualifier("u2")
    @Autowired
    private UserInfo userInfo;

    public void sayHi() {
        System.out.println("hi,UserController...");
        System.out.println(userInfo);
    }
}

运行结果:

 使用@Resource注解:是按照bean的名称进行注入。通过name属性指定要注⼊的bean的名称。

@Controller
public class UserController {

    @Resource(name="u2")
    private UserInfo userInfo;

    public void sayHi() {
        System.out.println("hi,UserController...");
        System.out.println(userInfo);
    }
}

运行结果:

@Autowird与@Resource的区别
1、@Autowired是spring框架提供的注解,而@Resource是JDK提供的注解
2、@Autowired默认是按照类型注入,而@Resource是按照名称注入.相比于@Autowired来说         @Resource支持更多的参数设置,例如name设置,根据名称获取Bean.

Autowired装配顺序


http://www.kler.cn/a/517914.html

相关文章:

  • LongLoRA:高效扩展大语言模型上下文长度的微调方法
  • GESP2024年3月认证C++六级( 第三部分编程题(1)游戏)
  • 【Linux线程总结】VMA ELF 地址转换 同步和互斥 条件变量 PC模型 循环队列 POSIX信号量 线程池
  • 为什么IDEA提示不推荐@Autowired❓️如果使用@Resource呢❓️
  • 12Express简易实战项目(编写api)
  • Vue2官网教程查漏补缺学习笔记 - 3Vue实例4模板语法5计算属性监听器
  • 【Uniapp-Vue3】触底加载更多
  • EtherNet/IP转Modbus协议网关在现代工业自动化领域的应用
  • 产品Web3D交互展示有什么优势?
  • 【NPC】SkyAGI:LLM 在模拟可信人类行为
  • 如何在服务器中实现双因子认证?
  • miniconda学习笔记
  • 合并两个有序数组(Leetcode)
  • 【Jave全栈】Java与JavaScript比较
  • Git客户端工具
  • Elasticsearch 性能测试工具 Loadgen 之 001——部署及应用详解
  • React进阶之高阶组件HOC、react hooks、自定义hooks
  • thingsBoard去除地图logo以及在ThingsBoard中实现 高德地图实时路线绘制,可实现车辆行驶状态监控
  • CPU 缓存基础知识
  • rust 自定义错误(十二)
  • 「全网最细 + 实战源码案例」设计模式——生成器模式
  • Pytest插件介绍:pytest-django
  • iOS 网络请求: Alamofire 结合 ObjectMapper 实现自动解析
  • 新型人工智能“黑帽”工具:GhostGPT带来的威胁与挑战
  • 深度学习中Batch Normalization(BN)原理、作用浅析
  • 食堂校园预约就餐小程序ssm+论文源码调试讲解