IoC DI

Spring 的两大核心思想 : IoC 和 AOP

我们要将对象的控制权交给Spring ,我们就需要告诉 Spring 哪些对象是需要帮我们进行创建的,这里有两类注解可以实现 :

类注解(@Controller @Service @Repository @Component @Configuration)和方法注解(@Bean)

这五大注解都表示把这个对象交给 Spring 进行管理和创建

五大注解和实际项目开发的关系 : 

@Controller @Service @Repository 和三层架构有关系

Controller : 接收请求并返回响应

Service : 接收完请求具体要做些什么样的事情,真正业务的逻辑处理是什么都是 Service 做的

Dao : 对数据进行处理

@Component 存储组件相关,@Configuration 存储配置相关

我们查看五个类注解的原码 : @Controller @Service @Repository @Component @Configuration

这四个注解都是基于 @Component 实现的,可以认为是 @Component 的衍生类

但是是不是说我们所有程序都使用 @Component 就行呢,那是当然不行的,那搞这么多注解就没意义了

我们用代码尝试一下能否使用 @Service 代替 @Controller 呢?@Controller 是接收请求返回响应,看看换成 @Service 是否还能接收请求返回响应

package com.example.ioc.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;@Controller
@ResponseBody
public class TestController {@RequestMapping("/test")public String test(){return "测试Controller 和其他注解的区别";}
}

现在我们把 @Controller 换成 @Service ,我们发现报错了

这是因为 Spring 对 Controller 进行了一些处理,我们想接收请求就只能使用 Controller ,就是说Controller必须作为我们程序的第一关,这是规范,不能使用其他注解

那么 @Service 这些可以使用 @Component 来代替呢? 这是可以的,但是并不建议

但是明明 @Service 和 @Controller 的原码明明差不多,为什么应用上有区别呢?这是因为原码只是注解的声明,只是声明了一个注解,但是 Spring 对于这个注解还会赋予一些别的功能,这些功能在 Spring 的原码里面

五大注解只能加在类上,并且只能加在自己的代码上,如果我引入了一个 jar包,也希望交给Spring 管理,这是没有办法加五大注解的,这时候就要使用 @Bean

@Bean 是方法注解 , @Bean 需要搭配五大注解来使用

使用 @Bean 注解时,bean 的名称是方法名

五大注解是,bean 的名称是类名的首字母转为小写,如果前两个字母都为大写,bean 的名称就是类名

还有另一个场景可以使用 @Bean ,对于一个类,我们需要定义多个对象时,比如数据库操作,定义多个数据源

因为当我们用别的注解的时候,拿到的是同一个数据,地址都一样,我们拿 @Configuration 举例

package com.example.ioc.config;
import org.springframework.context.annotation.Configuration;@Configuration
public class UserConfig {public void doConfig(){System.out.println("do configurarion...");}
}
        UserConfig userConfig = context.getBean(UserConfig.class);userConfig.doConfig();System.out.println("userConfig:"+userConfig);UserConfig userConfig1 = context.getBean(UserConfig.class);System.out.println("userConfig:"+userConfig1);System.out.println("userConfig == userConfig1"+(userConfig==userConfig1));

 我们发现,两个数据的地址是完全相同的,它们是否相等的判定返回也是 true 

接下来我们用 @Bean 试试看

package com.example.ioc.config;
import lombok.Data;@Data
//假如这是第三方包下的一个类
//现在我在我的项目中用到了 UserInfo,并且我需要用它定义多个对象
public class UserInfo {private Integer id;private String name;private Integer age;
}
package com.example.ioc.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class BeanConfig {@Beanpublic UserInfo userInfo(){UserInfo userInfo = new UserInfo();userInfo.setId(1);userInfo.setName("zhangsan");userInfo.setAge(12);return userInfo;}@Beanpublic UserInfo userInfo2(){UserInfo userInfo = new UserInfo();userInfo.setId(2);userInfo.setName("wangwu");userInfo.setAge(13);return userInfo;}
}
package com.example.ioc;import com.example.ioc.component.UserComponent;
import com.example.ioc.config.UserConfig;
import com.example.ioc.config.UserInfo;
import com.example.ioc.controller.UserController;
import com.example.ioc.repo.UserRepository;
import com.example.ioc.service.UserService;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {//Spring 上下文ApplicationContext context = SpringApplication.run(DemoApplication.class, args);//返回的就是 Spring 的运行环境//@Bean演示UserInfo userInfo = (UserInfo) context.getBean("userInfo");System.out.println(userInfo);UserInfo userInfo2 = (UserInfo) context.getBean("userInfo2");System.out.println(userInfo2);}}

这样就能返回两个不一样的内容了 

当一个类型存在多个 bean 时,我们就不能使用类型来获取对象了,就要使用名称进行获取了,或者是名称+类型进行获取

 UserInfo userInfo1 = context.getBean("userInfo",UserInfo.class);System.out.println(userInfo1);

这样依然可以拿到 

当我们想进行传参,代码改为 :

package com.example.ioc.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class BeanConfig {@Beanpublic String name(){return "wangwu";}@Beanpublic UserInfo userInfo(String name){UserInfo userInfo = new UserInfo();userInfo.setId(1);userInfo.setName(name);userInfo.setAge(12);return userInfo;}}

运行结果如下 

上面代码我把 public String name 改为 public String name2 依然可以被拿到,但是如果name和name2都存在,那么就根据名称去匹配,需要哪个就把名称放进传参的括号里

DI 依赖注入也可以叫做"属性装配"或者"依赖装配"

依赖可以简单认为是属性,比如下面代码中,userService 可以看做是 UserController 的属性

我们该如何完成依赖注入呢?

1.属性注入

我们用 @Autowired,这样就能把 Service 给引进来

属性注入以类型进行匹配,与注入的属性名称无关,但是如果一个类型存在多个对象时,优先进行名称匹配,如果名称都匹配不上,那就报错

@Autowired 无法注入一个被 final 修饰的属性(很少遇到这种情况)

@Controller
//用 @Controller 告诉 Spring 帮我们管理这个对象
public class UserController {@Autowiredprivate UserService userService;public void doController(){userService.doService();System.out.println("do Controller...");}
}@Service
public class UserService {public void doService(){System.out.println("do service....");}
}@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {//Spring 上下文ApplicationContext context = SpringApplication.run(DemoApplication.class, args);//返回的就是 Spring 的运行环境UserController bean = context.getBean(UserController.class);bean.doController();}
}

运行结果如下 

2.构造方法注入

如果存只有一个构造函数,@Autowired 可以省略,当有多个构造函数的时候,默认使用无参的构造函数,如果没有无参的构造函数,我们要告诉 Spring 我们用哪个构造函数,在那个构造函数上面添加 @Autowired 就行

package com.example.ioc.controller;import com.example.ioc.config.UserInfo;
import com.example.ioc.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;@Controller
//用 @Controller 告诉 Spring 帮我们管理这个对象
public class UserController {//属性注入//@Autowired//private UserService userService;//构造方法注入private UserService userService;private UserInfo userInfo;//    public UserController() {
//
//    }public UserController(UserService userService) {this.userService = userService;}@Autowiredpublic UserController(UserService userService, UserInfo userInfo) {this.userService = userService;this.userInfo = userInfo;}public void doController(){userService.doService();System.out.println("do Controller...");}
}

3.Setter 方法注入

public class UserController {private UserService userService;@Autowiredpublic void setUserService(UserService userService) {this.userService = userService;}public void doController(){userService.doService();System.out.println("do Controller...");}
}

当程序中同一个类型有多个对象时,使用@Autowired 会报错(一些情况下)

解决方法如下:

1,属性名和你需要使用的对象名保持一致

2.使用@Primary 注解标识默认的对象,优先用它

3.使用@Qualifier 

4.使用@Resource

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Qt布局技巧

可以先把控件放置了,再选中所有控件右键布局 或者是点击上面的:

【数据结构与算法】线性表 - 顺序表

目录 1. 线性表2.顺序表3.顺序表的优缺点4.实现(C语言)4.1 头文件 seqList.h4.2 实现 seqList.c 1. 线性表 线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见…

计算机网络的体系结构

目录 一. 计算机体系结构的形成二. 协议与层次划分2.1 数据传输过程2.2 什么是网络协议2.3 网络协议的三要素2.4 协议有两种形式2.4 各层协议2.5 什么是复用和分用 \quad 一. 计算机体系结构的形成 \quad 计算机网络是一个非常复杂的系统, 相互通信的两个计算机系统必须高度协调…

tomcat8.5处理get请求时,控制台输出中文乱码问题的解决

问题描述 控制台输出中文乱码 版本信息 我使用的是tomcat8.5 问题解决 配置web.xml 注&#xff1a;SpringMVC中处理编码的过滤器一定要配置到其他过滤器之前&#xff0c;否则无效 <!--配置springMVC的编码过滤器--> <filter><filter-name>CharacterEn…

C#特性(Attribute)

C#特性&#xff08;Attribute&#xff09;是一种在程序中添加元数据的机制&#xff0c;它可以为代码提供额外的信息和指示。通过使用特性&#xff0c;我们可以为类、方法、属性等元素添加标记&#xff0c;以便在运行时进行更多的操作和决策。 C#特性是一种声明式编程的工具&…

NSSCTF第13页(1)

[NCTF 2018]Easy_Audit 小小代码审计 $_REQUEST:PHP的内置变量&#xff0c;是一个数组&#xff0c;保存传递的参数&#xff0c;它的特性是如果get,post一起传参&#xff0c;则会优先post传参&#xff0c;可以由此进行变量覆盖。 $_SERVER:PHP的内置变量&#xff0c;是一个数组…

一文搞懂RC滤波器的设计?

滤波器是一种可以对“波”进行过滤的器件&#xff0c;一般是特定频率的信号。所以可以常常看到滤波器的种类繁多&#xff0c;有高通滤波器&#xff0c;低通滤波器&#xff0c;带通滤波器及带阻滤波器等等。 滤波器的主要作用就是滤波&#xff0c;它需要尽可能的让有用信号能够做…

unity教程

前言 伴随游戏行业的兴起&#xff0c;unity引擎的使用越来越普遍&#xff0c;本文章主要记录博主本人入门unity的相关记录大部分依赖siki学院进行整理。12 一、认识unity引擎&#xff1f; 1、Unity相关信息&#xff1a; Unity的诞生&#xff1a;https://www.jianshu.com/p/550…

M2 Mac Xcode编译报错 ‘***.framework/‘ for architecture arm64

In /Users/fly/Project/Pods/YYKit/Vendor/WebP.framework/WebP(anim_decode.o), building for iOS Simulator, but linking in object file built for iOS, file /Users/fly/Project/Pods/YYKit/Vendor/WebP.framework/WebP for architecture arm64 这是我当时编译模拟器时报…

The ultimate UI kit and design system for Figma 组件库下载

Untitled UI 是世界上最大的 Figma UI 套件和设计系统。可以启动任何项目&#xff0c;为您节省数千小时&#xff0c;并祝您升级为专业设计师。 采用 100% 自动布局 5.0、变量、智能变体和 WCAG 可访问性精心制作。 900全局样式、变量&#xff1a;超级智能的全局颜色、排版和效…

springboot321基于java的校园服务平台设计与开发

交流学习&#xff1a; 更多项目&#xff1a; 全网最全的Java成品项目列表 https://docs.qq.com/doc/DUXdsVlhIdVlsemdX 演示 项目功能演示&#xff1a; ————————————————

【MySQL】InnoDB和MyISAM区别详解(MySQL专栏启动)

&#x1f4eb;作者简介&#xff1a;小明java问道之路&#xff0c;2022年度博客之星全国TOP3&#xff0c;专注于后端、中间件、计算机底层、架构设计演进与稳定性建设优化&#xff0c;文章内容兼具广度、深度、大厂技术方案&#xff0c;对待技术喜欢推理加验证&#xff0c;就职于…