SpringIOC第二课,@Bean用法,DI详解,常见面试题Autowired VS Resource

一、回顾

但是我们之前MVC时候,在页面上,为什只用Controller,不用其他的呢?

用其他的好使吗?(我们可以在这里看到,出现404的字样)

@Service
@ResponseBody
public class TestController {
    @RequestMapping("/test")
    public String test(){
        return "测试Controller和其他注解的区别";
    }
}

但是Controller就是好使的,事实上Spring对Controller有更屌的权限

二、@Bean用法

五大注解只能加在类上,并且只能加在自己的代码上

如果我引入一个第三方的jar包,也希望交给Spring管理,是没有办法加五大注解

第一个应用场景:可以使用@Bean, @Bean是方法注解

在这里,我们可以看到一个问题,就是两个引用指向的是一个对象(看后面的那几位,说明地址相同)

第二个应用场景:那么假如说要求是一个类,定义多个对象,比如说数据库操作,定义多个数据源使用@Bean

@Bean相当于是一个上交作业的过程,交完了作业,要告诉老师,交完作业了

所以也就是说@Bean要搭配五大注解来使用并且当一个类型存在多个bean中,采用多个Bean的时候,我们就不能使用类型来获取对象了。

我们上节课学的注释

是getBean+方法名(小驼峰形式,特殊情况(两个首字母都是大写,那么她就会变成小写)

@Bean需要加的是方法名(方法名不遵守小驼峰形式)

如何进行相应的传递参数

那么我们在应用中,一般不会让写死

假如对Bean的方法中的内容进行传参数,则定义一个这种方法,当然现在这个也是死的,但是以后可以用这种方法变成“活的”

@Configuration
public class BeanConfig {
    @Bean
    public String name(){
        return "zhangsan";
    }
    @Bean
    public UserInfo UserInfo(String string){
        UserInfo userInfo=new UserInfo();

        userInfo.setName(string);
        return  userInfo;
    }

Spring的扫描文件约定

SpringBoot是属于我们的开发框架(其实叫做开发框架,更感觉像是打开idea,后呈现的这个结构)

SpringBoot特点:约定大于配置,约定到,放到哪里就扫描当前文件夹里面的所有文件,但是假如说你硬是想在一个小的目录里面去执行(也有方法,加路径)(约定的体现之一扫描路径,默认的扫描路径是:启动类所在的目录及其子孙目录

放到这个文件夹里面会报错

解决方式就是

//默认扫描当前类的目录及子目录
在前面加上这个注解(路径自己填)@ComponentScan("com.example")
@ComponentScan("com.example")
@SpringBootApplication
public class IoCtryApplication {

    public static void main(String[] args) {
        //启动类是帮助我们启动spring,这个命令可以返回一个spring

DI详解

DI依赖注入,属性装配“依赖装配”,

只要加上这些依赖注入(就跟我们导包一样,没导包不能用)

1.属性注入 @Autowired

(相当于导游,带着去找这个东西)和上面那个匹配的一致,和那个@Bean传递参数一样。

@Controller
public class UserController {
//⚠️假如没有下面的这个Autowired注释,那么就会报空指针异常
@Autowired
private UserService userService;

public void prin(){
    userService.doService();
    System.out.println("春节快乐");
}
}
UserController userController=context.getBean(UserController.class);
        userController.prin();

2.构造方法注入

如下图


@Controller
public class UserController {
//@Autowired
private UserService userService;
    private UserInfo userInfo;
//⚠️注意此时加完构造函数之后,还要把无参数的也写一遍,因为无参数的构造函数,有很多东西在用,所以一旦经过修改,就会让使用无参数的报错。

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

    public  UserController(UserInfo userInfo,UserService userService){
        this.userService=userService;
        this.userInfo=userInfo;
    }
public void prin(){
    userService.doService();
    System.out.println("春节快乐");
}

3.Setter方法注入

三种注入的优缺点

1.属性注入:

优点:简洁方便

缺点:只能用于IOC容器,如果非IOC容器无法使用,并且只有在使用的时候才会出现NPE(空指针异常),并且不能修饰Final。

2.构造函数注入:

优点:

(1).可以注入final属性(通过构造方法的形式)。

(2).注入的对象不会被修改(因为除非你再new,不然构造方法不能被再次调用),依赖对象使用之前一定会被初始化,因为依赖在类的构造方法中执行的,构造方法是类加载阶段就会执行的方法

(3).通用型好:构造方法是JDK支持的

缺点:

代码会比较繁琐

Setter注入

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

缺点:不能修饰Final,注入的对象肯会被改变,因为setter方法可能会被多次调用,就有被修改的风险。

当程序同一个类型,多个对象时候,使用@AutoWired会报错

这里说的情况是这样的一个代码

package com.example.IOCtry;

import com.example.IOCtry.config.UserInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;

@Controller
public class UserController {
@Autowired                //⚠️
private UserService userService;
@Autowired                //⚠️
private UserInfo userInfo;
//注意此时加完构造函数之后,还要把无参数的也写一遍,因为无参数的构造函数,有很多东西在用,所以一旦经过修改,就会让使用无参数的报错。

//public UserController(){
//}
//
//public  UserController(UserService userService){
//    this.userService=userService;
//}
//
//    public  UserController(UserInfo userInfo,UserService userService){
//        this.userService=userService;
//        this.userInfo=userInfo;
//    }
//   @Autowired
//    public  void setUserController(UserService userService){
//        this.userService=userService;
//    }
public void prin(){
    userService.doService();
    System.out.println(userInfo);
    System.out.println("春节快乐");
}
}

改法一需要改属性名字:让属性名和方法名字一致

package com.example.IOCtry;

import com.example.IOCtry.config.UserInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;

@Controller
public class UserController {
@Autowired
private UserService userService;
@Autowired
private UserInfo UserInfo1;       //⚠️这个名字改成和方法名字一摸一样
//注意此时加完构造函数之后,还要把无参数的也写一遍,因为无参数的构造函数,有很多东西在用,所以一旦经过修改,就会让使用无参数的报错。

//public UserController(){
//}
//
//public  UserController(UserService userService){
//    this.userService=userService;
//}
//
//    public  UserController(UserInfo userInfo,UserService userService){
//        this.userService=userService;
//        this.userInfo=userInfo;
//    }
//   @Autowired
//    public  void setUserController(UserService userService){
//        this.userService=userService;
//    }
public void prin(){
    userService.doService();
    System.out.println(UserInfo1);
    System.out.println("春节快乐");
}
}
不想改名的第二种方法:加上@Primary
//这个是在另一个类中搞的方法
package com.example.IOCtry.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

@Configuration
public class BeanConfig {
    @Bean
    public String name(){
        return "zhangsan";
    }
    @Bean
    public String name2(){
        return "wangwu";
    }

   // ⚠️@Primary这个只有加上,程序才会不发生错误,会执行这个Setter方法
    @Bean
    public UserInfo UserInfo1(String name2){
        UserInfo userInfo=new UserInfo();
        userInfo.setName(name2);
        return  userInfo;
    }
    @Bean
    public UserInfo userInfo2(){
        UserInfo userInfo=new UserInfo();
        userInfo.setId(2);
        userInfo.setAge(22);
        userInfo.setName("lclyr");
        return  userInfo;
    }

}
改法3(优先):使用@Qualifier
package com.example.IOCtry;

import com.example.IOCtry.config.UserInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;

@Controller
public class UserController {
@Autowired
private UserService userService;
@Qualifier("userInfo2")            //⚠️
@Autowired
private UserInfo userInfo;
//注意此时加完构造函数之后,还要把无参数的也写一遍,因为无参数的构造函数,有很多东西在用,所以一旦经过修改,就会让使用无参数的报错。

//public UserController(){
//}
//
//public  UserController(UserService userService){
//    this.userService=userService;
//}
//
//    public  UserController(UserInfo userInfo,UserService userService){
//        this.userService=userService;
//        this.userInfo=userInfo;
//    }
//   @Autowired
//    public  void setUserController(UserService userService){
//        this.userService=userService;
//    }
public void prin(){
    userService.doService();
    System.out.println(userInfo);
    System.out.println("春节快乐");
}
}

改法4(优先):使用@Resource(name="userInfo2")

package com.example.IOCtry;

import com.example.IOCtry.config.UserInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;

import javax.annotation.Resource;

@Controller
public class UserController {
@Autowired
private UserService userService;
//@Qualifier("userInfo2")
    @Resource(name="userInfo2")
@Autowired
private UserInfo userInfo;
//注意此时加完构造函数之后,还要把无参数的也写一遍,因为无参数的构造函数,有很多东西在用,所以一旦经过修改,就会让使用无参数的报错。

//public UserController(){
//}
//
//public  UserController(UserService userService){
//    this.userService=userService;
//}
//
//    public  UserController(UserInfo userInfo,UserService userService){
//        this.userService=userService;
//        this.userInfo=userInfo;
//    }
//   @Autowired
//    public  void setUserController(UserService userService){
//        this.userService=userService;
//    }
public void prin(){
    userService.doService();
    System.out.println(userInfo);
    System.out.println("春节快乐");
}
}

三、常见面试题Autowired VS  Resource

@Autowired:是Spring开发的框架,@Resource是JDK提供的框架

@Autowired:默认是按照类型来去注入,假如说同一个类型存在多个对象,那么就按名称匹配,假如名称匹配不上,那么就会报错,相对于Autowired来说,@Resource支持更多的参数设置,如name设置,根据名称获取Bean​​​​​​​

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

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

相关文章

Apache Doris 详细教程(三)

7、监控和报警 Doris 可以使用 Prometheus 和 Grafana 进行监控和采集,官网下载最新版即可。 Prometheus 官网下载:https://prometheus.io/download/ Grafana 官网下载:https://grafana.com/grafana/download Doris 的监控数据通过 FE 和…

外卖平台推荐算法的优化与实践

目录 引言 一、推荐算法的原理 二、推荐算法的挑战 三、实际案例分析 四、优化推荐算法的策略 五、结论 引言 在当今数字化社会,外卖平台成为了人们生活中不可或缺的一部分。为了提供更加个性化、高效的服务,外卖平台使用推荐算法成为了一项关键技…

使用Pytoch实现Opencv warpAffine方法

随着深度学习的不断发展,GPU/NPU的算力也越来越强,对于一些传统CV计算也希望能够直接在GPU/NPU上进行,例如Opencv的warpAffine方法。Opencv的warpAffine的功能主要是做仿射变换,如果不了解仿射变换的请自行了解。由于Pytorch的图像…

web自动化 -- pyppeteer

由于Selenium流行已久,现在稍微有点反爬的网站都会对selenium和webdriver进行识别,网站只需要在前端js添加一下判断脚本,很容易就可以判断出是真人访问还是webdriver。虽然也可以通过中间代理的方式进行js注入屏蔽webdriver检测,但…

【算法套路】(数组中)等价转换

文章目录 例题——2488. 统计中位数为 K 的子数组⭐【套路】子数组统计问题常用技巧:等价转换 相似题目列表面试题 17.05. 字母与数字525. 连续数组1124. 表现良好的最长时间段解法1解法2——利用单调栈 例题——2488. 统计中位数为 K 的子数组⭐ https://leetcode…

了解大模型 RAG (Retrieval-Augmented Generation):大模型外挂知识库 (检索增强技术)

本心、输入输出、结果 文章目录 了解大模型 RAG (Retrieval-Augmented Generation):大模型外挂知识库 (检索增强技术)前言什么是检索增强技术 RAG (Retrieval-Augmented Generation)检索增强技术…

分享几个电视颜色测试图形卡

介绍 本文分享几个常见的电视颜色测试图形卡和一段matlab程序,完成JPG转FPGA烧写文件,便于把彩色图片预装载到FPGA内。 电视颜色测试图形卡 一种专业检测电视显示效果的工具。它通常由一张卡片和一些色块组成,可以根据标准色彩空间和颜色渐…

数据结构 | 查漏补缺之ASL、

目录 ASL 情形之一:二分查找 线索二叉树 哈夫曼树 大根堆 邻接表&邻接矩阵 ASL 参考博文 关于ASL(平均查找长度)的简单总结_平均查找长度asl-CSDN博客 情形之一:二分查找 线索二叉树 参考博文 线索二叉树(线索链表遍历,二叉树…

『亚马逊云科技产品测评』活动征文|基于亚马逊云EC2搭建私有网盘 Nextcloud系统

授权声明:本篇文章授权活动官方亚马逊云科技文章转发、改写权,包括不限于在 Developer Centre, 知乎,自媒体平台,第三方开发者媒体等亚马逊云科技官方渠道 亚马逊EC2云服务器(Elastic Compute Cloud)是亚马…

[架构之路-256]:目标系统 - 设计方法 - 软件工程 - 软件设计 - 架构设计 - 软件系统不同层次的复用与软件系统向越来越复杂的方向聚合

目录 前言: 一、CPU寄存器级的复用:CPU寄存器 二、指令级复用:二进制指令 三、过程级复用:汇编语言 四、函数级复用:C语言 五、对象级复用:C, Java, Python 六、组件级复用 七、服务级复用 八、微…

leetcode 202 快乐数

leetcode 202 快乐数 题目题解代码 题目 编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」 定义为: 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变…

【尾递归】

尾递归 如果函数在返回前才进行递归调用,则该函数可以被编译器或解释器优化,使其在空间效率上与迭代相当。这种情况被称为「尾递归 tail recursion」。 普通递归:当函数返回到上一层级的函数后,需要继续执行代码,因此…

Android Init系统:引领设备启动的先锋

Android Init系统:引领设备启动的先锋 引言 Init系统是一个操作系统启动的必要组件,负责在启动时初始化所有系统资源、服务和应用程序。在Android设备中,Init系统起到了至关重要的作用,它是启动过程中的第一个进程,负…

C++分数计算器

C分数计算器各种分数计算类型都能计算 代码:https://mbd.pub/o/bread/ZZeZk5hx 一 目的 (1)定义一个整数类。 定义一个分数类,由整数类派生。能对分数进行各种计算和输入/输出。可进行分数的加、减、乘和除法等四则运算。 流程…

YOLOv8 区域计数 | 入侵检测 | 人员闯入

大家好,昨天的 YOLOv8 新增加了一个功能,区域计数,用这个功能我们能实现很多的任务, 比如入侵检测,流量统计,人员闯入等,使用方式也非常的方便,但是一定要使用最新版的 YOLOv8 代码(2023/12/03更新的代码)。 低版本是不具备这个功能的,上面是演示效果。 使用非常的方…

Leetcode2661. 找出叠涂元素

Every day a Leetcode 题目来源:2661. 找出叠涂元素 解法1:哈希 题目很绕,理解题意后就很简单。 由于矩阵 mat 中每一个元素都不同,并且都在数组 arr 中,所以首先我们用一个哈希表 hash 来存储 mat 中每一个元素的…

C语言中的动态内存管理

在C语言中,动态内存管理是通过一系列的标准库函数来实现的,这些函数包括malloc, free, calloc 和 realloc。它们允许程序在运行时动态地分配和释放内存,这是管理复杂数据结构(如链表、树等)时非常有用的功能。 为什么…

软件生命周期四个阶段SDLC

软件产品生命周期:指软件产品研发全部过程、活动和任务的结构框架。 产品的生命周期一般包括四个阶段:引入期、成长期、成熟期和衰退期,在不同的阶段中,市场对产品的反应不同,其销售特点不同,因而产品管理的…

【强化学习算法】Q-learning原理及实现

实现代码github仓库:RL-BaselineCode 代码库将持续更新,希望得到您的支持⭐,让我们一起进步! 文章目录 1. 原理讲解1.1 Q值更新公式1.2 ε-greedy随机方法 2. 算法实现2.1 算法简要流程2.2 游戏场景2.3 算法实现 3. 参考文章 1. 原…

数据挖掘实战-基于word2vec的短文本情感分析

🤵‍♂️ 个人主页:艾派森的个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞&#x1f4…
最新文章