详解Spring IoCDI(二)

目录

承接上文:详解Spring IoC&DI (一)

1.IoC详解

1.1方法注解@Bean

1.2方法注解要配合类注解使用 

1.3定义多个对象

1.4重命名Bean

1.5扫描路径

2.DI详解

2.1DI与IoC的关系

2.2属性注入

2.3构造方法注入

 2.4Setter注入

2.5 三种注入优缺点分析

2.6Autowired存在问题

2.6.1Primary

 2.6.2Qualifier

2.6.3Resource


承接上文:详解Spring IoC&DI (一)

1.IoC详解

1.1方法注解@Bean

类注解是添加到某个类上的  但是存在两个问:

1.使⽤外部包⾥的类, 没办法添加类注解

2.⼀个类, 需要多个对象, 比如多个数据源

这种场景, 我们就需要使⽤⽅法注解@Bean

代码示例:

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

当我们写完以上代码 ,尝试获取 bean 对象中的 user 时却发现 ,根本获取不到:

@SpringBootApplication
public class TestSpringTwoApplication {

    public static void main(String[] args) {
  ApplicationContext context =  SpringApplication.run(TestSpringTwoApplication.class,args);
        //从Spring上下⽂中获取对象
        User user =context.getBean(User.class);
        //使⽤对象
        System.out.println(user);
    }
}

执行结果如下: 

1.2方法注解要配合类注解使用 

Spring 框架的设计中 ,⽅法注解 @Bean 要配合类注解才能将对象正常的存储到Spring 容器中

如下代码所示:

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

再次执⾏以上代码 ,运⾏结果如下:

1.3定义多个对象

多数据源的场景, 类是同⼀个, 但是配置不同, 指向不同的数据源.

@Component
public class BeanConfig {
    @Bean
    public User user1(){
        User user = new User();
        user.setName("zhangsan");
        user.setAge(18);
        return user;
    }
    @Bean
    public User user2(){
        User user = new User();
        user.setName("lisi");
        user.setAge(28);
        return user;
    }

}

获取对象:

@SpringBootApplication
public class TestSpringTwoApplication {

    public static void main(String[] args) {
        ApplicationContext context =  SpringApplication.run(TestSpringTwoApplication.class, args);
        //从Spring上下⽂中获取对象
        User user1 = (User) context.getBean("user1");
        User user2 = (User) context.getBean("user2");
        //使⽤对象
        System.out.println(user1);
        System.out.println(user2);
    }
}

运行结果:

1.4重命名Bean

可以通过设置 name 属性给 Bean 对象进⾏重命名操作 ,如下代码所示


 @Bean(name = {"u1","user1"})
 public User user1(){
     User user = new User();
     user.setName("zhangsan");
     user.setAge(18);
     return user;
 }

此时我们使用u1就可以获取到User对象:

 User u1 = (User) context.getBean("u1"); 

name={} 可以省略 ,如下代码所⽰: 

 @Bean({"u1","user1"})
 public User user1(){
     User user = new User();
     user.setName("zhangsan");
     user.setAge(18);
     return user;
 }

只有⼀个名称时, {}也可以省略, :

 @Bean("u1")
 public User user1(){
     User user = new User();
     user.setName("zhangsan");
     user.setAge(18);
     return user;
 }

1.5扫描路径

使⽤前⾯学习的四个注解声明的bean想要⽣效 ,还需要Spring扫描

通过修改项目工程的目录结构进行测试:

运行结果:

 解释: 没有bean的名称为u1,

使⽤五⼤注解声明的bean ,要想⽣效, 还需要配置扫描路径, Spring扫描到这些注解也就是通过

@ComponentScan来配置扫描路径.

@ComponentScan({"com.example.demo"}) 
@SpringBootApplication
public class TestSpringTwoApplication {

    public static void main(String[] args) {
  ApplicationContext context =  SpringApplication.run(TestSpringTwoApplication.class,args);
        //从Spring上下⽂中获取对象
        User user =context.getBean(User.class);
        //使⽤对象
        System.out.println(user);
    }
}

@ComponentScan注解虽然没有显式配置,但是实际已经包含在了启动类声明注解

@SpringBootApplication中了,默认扫描的范围是启动类所在包及其子包

 

2.DI详解

2.1DI与IoC的关系

DI(Dependency Injection,依赖注入)和 IoC(Inversion of Control,控制反转)有着密切的关系。 可以说 DI 是实现 IoC 的一种具体方式。 IoC 是一种设计思想,强调将对象之间的控制权进行反转,不再由对象自己去创建或获取其依赖,而是由外部(如框架)来控制和管理依赖关系的创建和注入。 而 DI 则侧重于具体的将依赖对象注入到目标对象的操作,它是实现 IoC 理念的重要手段之一。通过 DI,依赖对象在合适的时候被准确地注入到需要它们的对象中,从而体现了 IoC 的原则。 简单来说,IoC 是更宏观的概念,DI 是实现 IoC 的具体策略和机制。

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

属性注⼊(Field Injection)、构造⽅法注⼊(Constructor Injection)、Setter 注⼊(Setter Injection)

2.2属性注入

 @SpringBootApplication
 public class SpringIocDemoApplication { 

    public static void main(String[] args) { 
      //获取Spring上下⽂对象
       ApplicationContext context = SpringApplication.run(SpringIocDemoApplicatio 
      //从Spring上下⽂中获取对象
      UserController userController = (UserController) context.getBean("userCont 
      //使⽤对象
       userController.sayHi(); 11    }
 }

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

Service类的实现代码如下: 

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

Controller 类的实现代码如下:

 @Controller
 public class UserController { 
     //注⼊⽅法1: 属性注⼊
     @Autowired
     private UserService userService;

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

获取Controller中的sayHi方法: 

 @SpringBootApplication
 public class SpringIocDemoApplication { 

    public static void main(String[] args) { 
      //获取Spring上下⽂对象
  ApplicationContext context =  SpringApplication.run(TestSpringTwoApplication.class,args);

      //从Spring上下⽂中获取对象
      UserController userController = context.getBean(UserController.class);
      //使⽤对象
       userController.sayHi(); 
    }
 }

 运行结果为:

2.3构造方法注入

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

@Controller
public class UserController2 { 
     //注⼊⽅法2: 构造⽅法
     private UserService userService; 

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

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

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

 2.4Setter注入

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

 @Controller
 public class UserController3 { 
     //注⼊⽅法3: Setter⽅法注⼊
    private UserService userService; 

    @Autowired
     public void setUserService(UserService userService) {
        this.userService = userService;
      } 
     public void sayHi(){
         System.out.println("hi,UserController3...");
        userService.sayHi();
     }
    }

2.5 三种注入优缺点分析

属性注⼊

  优点: 简洁 ,使⽤⽅便; 

  缺点:只能⽤于 IoC 容器 并且只有在使⽤的时候才会出现 NPE 空指针异常)、 能注入⼀个Final修饰的属性

 构造函数注⼊(Spring 4.X推荐) 

 优点:可以注⼊final修饰的属性、注⼊的对象不会被修改、依赖对象在使⽤前⼀定会被完全初始化 ,因为依赖是在类的构造⽅法中执⾏的 ,⽽构造⽅法是在类加载阶段就会执⾏的⽅法、 通⽤性好, 构造⽅法是JDK⽀持的, 所以更换任何框架,他都是适⽤的

 缺点: 注入多个对象时, 代码会比较繁琐

  Setter注⼊(Spring 3.X推荐)

 优点: ⽅便在类实例之后, 重新对该对象进⾏配置或者注⼊

缺点:不能注⼊⼀个Final修饰的属性、注⼊对象可能会被改变, 因为setter⽅法可能会被多次调⽤ , 就有被修改的风险.

2.6Autowired存在问题

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


 @Component
 public class BeanConfig { 

     @Bean("u1")
     public User user1(){
        User user = new User();
        user.setName("zhangsan");
        user.setAge(18);
         return user;
     } 

     @Bean
     public User user2() {
        User user = new User();
        user.setName("lisi");
        user.setAge(19);
         return user;
     }
 }
 @Controller
 public class UserController { 

     //注⼊user 
     @Autowired
     private User user;

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

运行结果: 

报错的原因是 ,⾮唯—的 Bean 对象。

Spring提供了以下几种解决⽅案:

2.6.1Primary

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

 @Component
 public class BeanConfig { 

     @Primary //指定该bean为默认bean的实现
     @Bean("u1")
     public User user1(){
        User user = new User();
        user.setName("zhangsan");
        user.setAge(18);
         return user;
     } 
     @Bean
     public User user2() {
        User user = new User();
        user.setName("lisi");
        user.setAge(19);
         return user;
     }
 }

 2.6.2Qualifier

指定当前要注⼊的bean对象。 在@Qualifiervalue属性中 ,指定注⼊的bean 的名称。

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

 @Controller
 public class UserController {
     @Qualifier("user2") //指定bean名称
     @Autowired
     private User user;

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

2.6.3Resource

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

 @Controller
 public class UserController { 
     @Resource(name = "user2")
     private User user; 

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

@Autowird @Resource的区别

•  @Autowired spring框架提供的注解 ,而@ResourceJDK提供的注解

•  @Autowired 默认是按照类型注⼊ ,⽽@Resource是按照名称注⼊ . 相⽐于 @Autowired  来说, @Resource ⽀持更多的参数设置 ,例如 name 设置 ,根据名称获取 Bean

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/666836.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Endnote】如何在word界面加载Endnote

如何在word界面加载Endnote 方法1:方法2:从word入手方法3:从CWYW入手参考 已下载EndNote,但Word中没有显示EndNote,应如何加载显示呢? 方法1: 使用EndNote的Configure EndNote.exe 。 具体步骤为&#x…

内网安全:横向传递攻击(PTH || PTK || PTT 哈希票据传递)

内网安全:横向传递攻击. 横向移动就是在拿下对方一台主机后,以拿下的那台主机作为跳板,对内网的其他主机再进行后面渗透,利用既有的资源尝试获取更多的凭据、更高的权限,一步一步拿下更多的主机,进而达到控…

理解AdaBoost算法:简单流程概述(一)【流程理解、无数学推导】

什么是AdaBoost 算法? AdaBoost(Adaptive Boosting)算法,全称为 自适应提升 ,是 一种在机器学习中用作集成方法的提升技术 。它之所以被称为自适应提升,因为每个实例的权重会重新分配,错误分类…

C语言 | Leetcode C语言题解之第123题买卖股票的最佳时机III

题目&#xff1a; 题解&#xff1a; #define max(a, b) ((a) < (b) ? (b) : (a))int maxProfit(int* prices, int pricesSize) {int buy1 -prices[0], sell1 0;int buy2 -prices[0], sell2 0;for (int i 1; i < pricesSize; i) {buy1 max(buy1, -prices[i]);sell…

解决:【无法安装“vue.volar“扩展,因为它与当前 VIsual Studio Code 版本不兼容(版本 1.80.0)】

目录 问题复现问题分析解决步骤1、进入VSCode插件市场&#xff0c;搜索Vue.volar2、点击搜索结果&#xff0c;进入详情页面3、下载.vsix文件完成后&#xff0c;用解压软件打开 4、复制package.json文件&#xff0c;修改vscode版本5、保存package.json文件&#xff0c;并更新.v…

【NPS】微软NPS配置802.1x,验证域账号,动态分配VLAN(有线网络篇)

上两篇中介绍了如何配置NPS和在WLC上如何配置802.1X来实现验证域账号和动态分配VLAN&#xff0c;802.1x协议作为一种成熟的身份验证框架&#xff0c;不仅适用于无线网络&#xff0c;同样也适用于有线网络环境。这里我们将介绍如何在有线网络中部署802.1x认证&#xff0c;以验证…

Visual Studio的桌面快捷方式图标不显示

1.问题描述 以下以Visual Studio 2019举例&#xff0c; 正常图标&#xff1a; 但是当前Visual Studio的桌面快捷方式图标不显示了&#xff1f; 2.问题原因分析 Visual Studio 2019桌面快捷方式图标不显示可能由以下几个原因造成&#xff1a; 图标缓存问题&#xff1a;Windo…

Spring boot 集成thymeleaf

Spring boot 集成thymeleaf 背景 自己通过Spring boot集成通义千问实现了一个智能问答系统。Spring boot集成通义千问已经完成&#xff0c;现在需要做一个简单的页面展示&#xff0c;作为一个八年没有摸过前端的后端开发人员&#xff0c;不得不又拿起了html和thymeleaf。 Sp…

笔记-docker基于ubuntu22.04安装Jitsi Meet

背景 利用JitsiMeet打造一个可以在线会议的环境&#xff0c;根据躺的坑&#xff0c;做个记录 参考 JitsMeet部署安装说明 开始操作 环境 docker run -it --name ubuntu22.04 ubuntu:22.04 /bin/bash问题 1、安装 openjdk-11 apt install openjdk-11-jdk配置环境变量&…

探索 Ollama: 你的本地 AI 助手

本期推荐的开源项目是 Ollama&#xff0c;它是一款本地大模型运行工具&#xff0c;可以帮助用户轻松下载和运行各种大型语言模型&#xff08;LLM&#xff09;&#xff0c;而无需将数据上传到云端。以下是关于 Ollama 的介绍以及安装和使用教程&#xff1a; Ollama 是什么&#…

深入分析 Android Service (四)

文章目录 深入分析 Android Service (四)1. 使用 Messenger 进行通信2. 详细示例&#xff1a;使用 Messenger 进行通信2.1 创建 MessengerService2.2 在 Activity 中绑定服务并发送消息 3. 使用 AIDL 进行进程间通信3.1 定义 AIDL 接口3.2 实现 AIDL 接口3.3 在客户端绑定 AIDL…

ABAP 自动填充DATAX

问题 经常做BAPI开发的时候&#xff0c;SAP有个什么DATAX的表对应DATA&#xff0c;每次都要写一堆成对的DATA和DATAX&#xff0c;不然就会修改失败&#xff0c;每次复制粘贴也有点麻烦而且容易漏 代码实现 群里大姑刚好写了段代码用来匹配这个DATA和DATAX格式的&#xff0c…

k8s集群的存储卷、pvc和pv

目录 简介 简介 PV 全称叫做 Persistent Volume&#xff0c;持久化存储卷。它是用来描述或者说用来定义一个存储卷的&#xff0c;这个通常都是由运维工程师来定义。 PVC 的全称是 Persistent Volume Claim&#xff0c;是持久化存储的请求。它是用来描述希望使用什么样的或者说…

Spring Cloud | 客户端 “负载均衡器“ : Ribbon

目录: 1. 什么是 "负载均衡" ? ( 通过 "负载均衡" 可以将 "用户请求" "分发" 到 不同的服务器&#xff0c;以此来提高 "性能" 和 "可靠性" )2. "负载均衡" 的 分类 &#xff1f;3. 认识 Ribbon :3.1 R…

[香橙派 AIpro] 性能强劲的昇腾AI开发板,应用广泛,性能出众,遥遥领先!

[香橙派 AIpro] 性能强劲的昇腾AI开发板&#xff0c;应用广泛&#xff0c;性能出众&#xff0c;遥遥领先&#xff01; 开发板简介 香橙派AIpro开发板凭借华为昇腾AI芯片的强大算力、丰富的接口、完善的开发工具等优势&#xff0c;在AI开发板市场具有很高的竞争力&#xff0c;可…

基于模板匹配的信用卡数字识别

文章目录 一、项目介绍二、模板匹配的原理三、模板匹配的步骤模板图片处理信用卡图片处理进行模板匹配 一、项目介绍 模板识别&#xff08;Template Matching&#xff09;是一种基于图像匹配的技术&#xff0c;用于在较大图像中识别和定位小图像&#xff08;模板&#xff09;。…

如何在 llama.cpp 服务器中实现用户登录功能的优化方案?(语言-c++)

&#x1f3c6;本文收录于「Bug调优」专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&&…

揭秘APP广告变现项目

在当今移动应用市场&#xff0c;广告变现已经成为开发者盈利策略的重要组成部分。 通过在应用程序中展示多种类型的广告&#xff0c;如插页式广告、横幅广告和激励视频广告&#xff0c;开发者能够获得经济效益。 实现这一目标的核心在于平衡收入与用户体验&#xff0c;避免过…

前端树形结构组件的设计与实现:以企查查、天眼查股权结构为例

摘要 随着信息化时代的不断发展&#xff0c;数据可视化在各行各业的应用越来越广泛。特别是在商业信息查询领域&#xff0c;如企查查、天眼查等平台&#xff0c;通过直观的数据展示方式&#xff0c;帮助用户快速理解复杂的商业关系。本文将以一个前端tree树形结构模版组件为例…

C语言序列化和反序列化--TPL中的API(三)

tpl_map 创建tpl的唯一方法是调用tpl_map()。第一个参数是格式字符串。后面是格式字符串中特定字符所需的参数列表。例如, tpl_node *tn; int i; tn tpl_map( "A(i)", &i );该函数在格式字符串中的项和给定地址的C程序变量之间创建映射。稍后&#xff0c;C变量…