【SSM详细教程】-04-Spring基于注解的组件扫描

 精品专题:

01.《C语言从不挂科到高绩点》课程详细笔记

https://blog.csdn.net/yueyehuguang/category_12753294.html?spm=1001.2014.3001.5482icon-default.png?t=O83Ahttps://blog.csdn.net/yueyehuguang/category_12753294.html?spm=1001.2014.3001.5482

02. 《SpringBoot详细教程》课程详细笔记

https://blog.csdn.net/yueyehuguang/category_12789841.html?spm=1001.2014.3001.5482icon-default.png?t=O83Ahttps://blog.csdn.net/yueyehuguang/category_12789841.html?spm=1001.2014.3001.548203.《SpringBoot电脑商城项目》课程详细笔记

https://blog.csdn.net/yueyehuguang/category_12752883.html?spm=1001.2014.3001.5482icon-default.png?t=O83Ahttps://blog.csdn.net/yueyehuguang/category_12752883.html?spm=1001.2014.3001.548204.《VUE3.0 核心教程》课程详细笔记

https://blog.csdn.net/yueyehuguang/category_12769996.html?spm=1001.2014.3001.5482icon-default.png?t=O83Ahttps://blog.csdn.net/yueyehuguang/category_12769996.html?spm=1001.2014.3001.5482

================================

||   持续分享系列教程,关注一下不迷路  ||

||   视频教程:小破站:墨轩大楼             ||

================================

1. 什么是组件扫描

指定一个包路径,Spring会自动扫描该包及其子包所有组件类,当发现组件类定义前有特定的注解标记时,就将该组件纳入到Spring容器中。等价于原有XML配置中的<bean>定义功能。

组件扫描可以代替大量XML配置的<bean>定义。

1.1. 指定扫描类路径

使用组件扫描,首先需要在applicationContext.xml配置文件中指定扫描类路径,如下所示:

<context:component-scan base-package="com.moxuan" />

上面配置,容器实例化时会自动扫描com.moxuan包及其子包下面所有组件类。

1.2. 自动扫描的注解标记

指定扫描类路径后,并不是该路径下所有组件类都扫描到Spring容器的,只有在组件类定义前面有以下注解标记时,才会扫描到spring容器中:

注解标记

描述

@Component

通用注解

@Name

通用注解

@Repository

持久化层组件注解

@Service

业务层组件注解

@Controller

控制层组件注解

1.3. 自动扫描组件的命名

当一个组件在扫描过程中被检测到时,会生成一个默认id值,默认id为小写开头的类名,也可以在注解标记中自定义id。看下面案例:

首先在application.xml中配置注解扫描包路径:

 <context:component-scan base-package="com.moxuan"></context:component-scan>

然后在com.moxuan的子包entity中新建Cat类 ,使用默认id值,具体代码如下:

package com.moxuan.entity;import lombok.Data;
import org.springframework.stereotype.Component;@Component  // 此处不加名字,采用默认id
@Data
public class Cat {private String name;private String color;
}

然后在com.moxuan的子包entity中新建Dog类 ,指定一个id名字,具体代码如下:

package com.moxuan.entity;import lombok.Data;
import org.springframework.stereotype.Component;@Component("myDog")  // 此处指定了名字,就不再使用默认的id了
@Data
public class Dog {private String name;private String type;
}

分别在测试方法中获取cat和dog对象,具体如下:

/**
* 自动扫描组件的命名
*/
@Test
public void test01(){AbstractApplicationContext context =new ClassPathXmlApplicationContext("application.xml");Cat cat = context.getBean("cat",Cat.class);System.out.println(cat);Dog dog = context.getBean("myDog",Dog.class);System.out.println(dog);
}

运行效果:

2. 指定组件的作用域

通常受Spring管理的组件,默认的作用域是Singleton,如果需要其他的作用域可以使用@Scope注解,只要在注解中提供作用域的名称即可。看下面代码:

Cat类代码不变:

package com.moxuan.entity;import lombok.Data;
import org.springframework.stereotype.Component;@Component  // 此处不加名字,采用默认id
@Data
public class Cat {private String name;private String color;
}

Dog类新增@Scope注解,指定为prototype

package com.moxuan.entity;import lombok.Data;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;@Scope("prototype")
@Component("myDog")  // 此处指定了名字,就不再使用默认的id了
@Data
public class Dog {private String name;private String type;
}

编写测试方法:

@Test
public void test02(){AbstractApplicationContext context =new ClassPathXmlApplicationContext("application.xml");Cat cat1 = context.getBean("cat",Cat.class);Cat cat2 = context.getBean("cat",Cat.class);System.out.println(cat1==cat2); // trueDog dog1 = context.getBean("myDog",Dog.class);Dog dog2 = context.getBean("myDog",Dog.class);System.out.println(dog1==dog2); //false}

cat未指定作用域,默认的作用域是Singleton,所以可以看到虽然我们获取了两次对象,但是由于默认的作用域是Singleton,单例模式,只有一个对象,所以比较的时候,值为true。而Dog上面我使用@Scope指定了非单例模式,两次获取到的对象不是同一个,所以比较结果为false。

3. 初始化和销毁回调的控制

@PostConstruct @PreDestroy 注解标记分别用于指定初始化和销毁回调函数,使用示例如下:

首先添加ExampleBean,分别添加初始化和销毁方法,并使用两个注解,具体如下:

package com.moxuan.entity;import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;@Component
public class ExampleBean {public ExampleBean(){System.out.println("构造函数执行。..");}@PostConstructpublic void init(){System.out.println("初始化方法被调用了");}@PreDestroypublic void destroy(){System.out.println("销毁方法被调用了");}
}

编写测试方法,具体代码如下:

/**
* 测试初始化和销毁注解
*/
@Test
public void test03(){AbstractApplicationContext context =new ClassPathXmlApplicationContext("application.xml");ExampleBean eb = context.getBean("exampleBean",ExampleBean.class);System.out.println(eb);System.out.println("-------------");context.close();// 关闭容器,测试销毁
}

运行效果如图所示:

4. 指定依赖注入关系

具有依赖关系的Bean对象,利用下面任意一种注解都可以实现关系注入:

@Resource

@Autowired / @Qulifier

@Inject / @Named

4.1. @Resource 注解

@Resource 注解标记可以用在字段定义或setter方法定义前面,默认首先按名称匹配注入,如果匹配不到再按照类型匹配注入。

首先创建武器类Weapon.java,代码如下:

package com.moxuan.entity;import lombok.Data;
import org.springframework.stereotype.Component;@Component
@Data
public class Weapon {private String name;public Weapon(){this.name = "擎天柱";}
}

再创建一个装备类Equip.java,代码如下:

package com.moxuan.entity;import lombok.Data;
import org.springframework.stereotype.Component;@Data
@Component
public class Equip {private String name;public Equip(){this.name = "皇帝的新衣";}
}

接下来创建Hero.java,使用@Resource进行属性注入:

package com.moxuan.entity;import lombok.Data;
import org.springframework.stereotype.Component;import javax.annotation.Resource;@Component
@Data
public class Hero {@Resource  //根据属性名去匹配private Weapon weapon;@Resource(name="weapon")  // 指定属性名去匹配private Weapon weapon01;@Resource  // 根据类型匹配private Weapon weapon02;private Equip equip;@Resource  // 作用在setter方法上public void setEquip(Equip equip) {this.equip = equip;}
}

最后编写测试方法,代码如下:

/**
* 测试@Resource
*/
@Test
public void test04(){AbstractApplicationContext context =new ClassPathXmlApplicationContext("application.xml");Hero hero = context.getBean("hero", Hero.class);System.out.println(hero);
}

运行效果:

4.2. @Autowired 注解

@Autowired 注解标记也可以用在字段定义或setter方法定义前面,默认按类型匹配注入

首先新建一个Computer类,添加相应属性

package com.moxuan.entity;import lombok.Data;
import org.springframework.stereotype.Component;@Data
@Component
public class Computer {private String mainBoard;private String hdd;private String ram;public Computer(){this.mainBoard = "技嘉";this.hdd = "希捷";this.ram = "金士顿";}
}

然后添加Programmer类,分别定义两个Computer属性,并分别对两个属性在属性前和setter方法前使用@Autowired注解。

package com.moxuan.entity;import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
@Data
public class Programmer {@Autowiredprivate Computer com1;private Computer com2;@Autowiredpublic void setCom2(Computer com2) {this.com2 = com2;}
}

最后编写测试方法,代码如下:

/**
* 测试@Autowired
*/
@Test
public void test05(){AbstractApplicationContext context =new ClassPathXmlApplicationContext("application.xml");Programmer pro = context.getBean("programmer",Programmer.class);System.out.println(pro);
}

运行效果如图所示:

此时发现两种方式都能够成功注入属性值。

由于@Autowired 注解方式是按照类型去匹配注入的,如果出现两个类型相同的Bean,会根据属性名去匹配Bean,如果匹配得到就能注入成功,反之匹配不到就会报错。

首先,去掉Computer类上面的注解

package com.moxuan.entity;import lombok.Data;
import org.springframework.stereotype.Component;@Data
//@Component
public class Computer {private String mainBoard;private String hdd;private String ram;public Computer(){this.mainBoard = "技嘉";this.hdd = "希捷";this.ram = "金士顿";}
}

在applicationContext.xml中添加bean配置,配置两个Computer类型的bean,注入不同的属性,代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"><context:component-scan base-package="com.moxuan"></context:component-scan><bean id="com1" class="com.moxuan.entity.Computer"><property name="mainBoard" value="技嘉" /><property name="hdd" value="希捷" /><property name="ram" value="金士顿"/></bean><bean id="com2" class="com.moxuan.entity.Computer"><property name="mainBoard" value="华硕" /><property name="hdd" value="西部" /><property name="ram" value="金士顿"/></bean>
</beans>

Programmer类中保留之前的代码,代码如下:

package com.moxuan.entity;import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
@Data
public class Programmer {@Autowiredprivate Computer com1;private Computer com2;@Autowiredpublic void setCom2(Computer com2) {this.com2 = com2;}
}

测试方法如下:

/**
* 测试@Autowired
*/
@Test
public void test05(){AbstractApplicationContext context =new ClassPathXmlApplicationContext("application.xml");Programmer pro = context.getBean("programmer",Programmer.class);System.out.println("com1:"+pro.getCom1());System.out.println("com2:"+pro.getCom2());
}

运行效果:

此时会发现,application.xml中配置的id为com1的bean 注入给了Programmer中com1属性。而com2的bean注入给了Programmer中的com2属性。不难看出,当有多个类型相同的bean时@Autowired会自动根据名称去匹配。

但是当没有匹配到名字相同的bean时,就会出错,比如下面,我们将配置文件中两个Bean的id分别修改为computer1和computer2,代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"><context:component-scan base-package="com.moxuan"></context:component-scan><bean id="computer1" class="com.moxuan.entity.Computer"><property name="mainBoard" value="技嘉" /><property name="hdd" value="希捷" /><property name="ram" value="金士顿"/></bean><bean id="computer2" class="com.moxuan.entity.Computer"><property name="mainBoard" value="华硕" /><property name="hdd" value="西部" /><property name="ram" value="金士顿"/></bean>
</beans>

再次运行测试方法时,会出现下图问题:

4.3. @Qualifier 注解

在前面的操作中,如果使用@Autowired 注解,会优先根据类型去匹配,如果存在多个类型相同的bean时,会根据名称去匹配,如果名称匹配不成功,就会报错。而@Qualifier 注解可以用来和@Autowired 进行配合,解决当属性名和bean中的id不同时注入错误的问题。

修改前面的Programmer类如下:

package com.moxuan.entity;import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;@Component
@Data
public class Programmer {@Autowired@Qualifier("computer1")private Computer com1;private Computer com2;@Autowiredpublic void setCom2(@Qualifier("computer2") Computer com2) {this.com2 = com2;}
}

运行测试方法,结果如下:

我们可以发现,这回也注入成功了。所以使用@Autowired 注入时,需要注入指定名称的Bean时,可以使用@Qualifier 去注入指定名称的Bean

总结:@Autowired 自动装配的流程如下图所示:

首先根据所需要的组件类型到IOC容器中查找

  • 如果能够找到唯一的bean:直接执行装配
  • 如果完全找不到匹配这个类型的bean:装配失败

如果匹配到的bean不止一个

  • 没有@Qualifier注解:根据@Autowired标记位置成员变量的变量名作为bean的id进行匹配
  • 如果能够找到:执行装配
  • 如果找不到:装配失败
  • 使用@Qualifier注解:根据@Qualifier注解中指定的名称作为bean的id进行匹配
  • 能够找到:执行装配
  • 找不到:装配失败

4.4. @Value注解

@Value 注解可以注入Spring表达式的值,使用方法步骤如下:

  1. 首先在项目resources目录中添加properties文件,比如:mysql.properties,内容如下:
driver=com.mysql.jdbc.Driver
url=jdbc:mysql:///moxuan
username=root
password=123456
  1. 在application.xml配置中,引入mysql.properties文件
<util:properties location="classpath:mysql.properties" id="jdbc"></util:properties>
  1. 添加MySQLUtils类,代码如下:
package com.moxuan.entity;import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;@Component
@Data
public class MySQLUtils {@Value("#{jdbc.driver}")private String driver;@Value("#{jdbc.url}")private String url;@Value("#{jdbc.username}")private String user;@Value("#{jdbc.password}")private String password;
}
  1. 添加测试方法如下:
@Test
public void test06(){AbstractApplicationContext context =new ClassPathXmlApplicationContext("application.xml");MySQLUtils utils = context.getBean("mySQLUtils",MySQLUtils.class);System.out.println(utils);
}

运行结果:

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

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

相关文章

HTML5教程(三)- 常用标签

1 文本标签-h 标题标签&#xff08;head&#xff09;&#xff1a; 自带加粗效果&#xff0c;从h1到h6字体大小逐级递减一个标题独占一行 语法 <h1>一级标题</h1><h2>二级标题</h2><h3>三级标题</h3><h4>四级标题</h4><h5…

CANoe_CDD_FaultMemory_显示<DTC is defined in the database>解决方法

1、显示<DTC is defined in the database> 2、问题原因 a、在Base Variant中的Fault Memory没有数据 b、新建数据&#xff08;参考导入或者新建方法&#xff09; c、复制数据过来 &#xff08;在Fault Memory中Diagnostic Trouble Codes的Avariable中全选复制到此处&am…

FFmpeg的简单使用【Windows】--- 指定视频的时长

目录 功能描述 效果展示 代码实现 前端代码 后端代码 routers 》users.js routers 》 index.js app.js 功能描述 此案例是在上一个案例【FFmpeg的简单使用【Windows】--- 视频混剪添加背景音乐-CSDN博客】的基础上的进一步完善&#xff0c;可以先去看上一个案例然后再…

Java基于SSM微信小程序物流仓库管理系统设计与实现(lw+数据库+讲解等)

选题背景 随着社会的发展&#xff0c;社会的方方面面都在利用信息化时代的优势。互联网的优势和普及使得各种系统的开发成为必需。 本文以实际运用为开发背景&#xff0c;运用软件工程原理和开发方法&#xff0c;它主要是采用java语言技术和mysql数据库来完成对系统的设计。整个…

mysql的各种存储引擎

文章目录 前言1. InnoDB特点 2. MyISAM特点innodb与myisam引擎之间的区别 3. MEMORY特点 4. ARCHIVE特点 5. NDBCluster特点 6. FEDERATED特点 7. CSV特点 总结 前言 MySQL 支持多种存储引擎&#xff0c;每种引擎都有其独特的功能和适用场景。存储引擎是指数据库管理系统用来存…

[PHP]__callStatic

第一种&#xff1a;以下代码不会触发__callStatic&#xff0c;也不会报错 test是空方法 <?php class A {public function test(){}public static function __callStatic($method, $args){print_r(aaaaaaaaaaaaaaaaaaaaa);} }A::test();第二种&#xff1a;以下代码不会触发…

MYSQL-多表查询和函数

第一题讲解 # 1. 查出至少有一个员工的部门&#xff0c;显示部门编号、部门名称、部门位置、部门人数。 分析:(分析要查的表): (显示的列):(关联条件):(过滤条件):[分组条件]:[排序条件]:[分页条件]:SELECT d.deptno, dname, loc, count(empno) FROM dept d JOIN emp e ON d…

C#从零开始学习(基本语法概念)(2)

深入C# 本章所有的代码都放在 https://github.com/hikinazimi/head-first-Csharp 控制台项目结构 每个C#程序采用同样的方式组织,命名空间,类和方法 using System;namespace helloworld//命名空间 {class Program//类{static void Main(string[] args)//程序入口{Console.Writ…

YOLOv11改进-卷积-空间和通道重构卷积SCConv

本篇文章将介绍一个新的改进模块——SCConv&#xff08;小波空间和通道重构卷积&#xff09;&#xff0c;并阐述如何将其应用于YOLOv11中&#xff0c;显著提升模型性能。为了减少YOLOv11模型的空间和通道维度上的冗余&#xff0c;我们引入空间和通道重构卷积。首先&#xff0c;…

C语言笔记(指针的进阶)

目录 1.字符指针 2.指针数组 3.数组指针 3.1.创建数组指针 3.2.&数组名和数组名 1.字符指针 int main() { char ch w;char* pc &ch;const char *p "abcdef";//常量字符串 产生的值就是首元素的地址//常量字符串不能被修改 因此需要加上一个…

10月18日

二次型矩阵要是对称矩阵 通解要带入特解 集体化 逆反思维 先定特解&#xff0c;再求通解 反函数...我谢谢你 依旧是原函数

视频的编解码格式

文章目录 视频的编解码格式概念术语视频处理流程视频封装格式视频编码格式视频编解码器&#xff0c;视频容器和视频文件格式之间的区别补充视频码率 参考资料 视频的编解码格式 概念术语 两大组织主导视频压缩的组织及其联合(joint)组织 ITU-T(VCEG) ITU-T的中文名称是国际电信…

【动手学深度学习】6.2 图像卷积(个人向笔记)

1. 互相关运算 严格来说&#xff0c;卷积层是一个错误的叫法&#xff0c;因为它本质上是互相关运算而不是卷积运算。我们暂时忽略通道看看二维图像数据和隐藏表示。那么输出大小可以表示为 我们自己实现一个二维互相关运算 2. 卷积层 卷积层中有两个参数&#xff1a;卷积核权…

工业物联网关-TCP透传

TCP透传功能提供类似于DTU(Data Transmit Unit)的功能&#xff0c;用户在网络端使用TCP协议连接网关&#xff0c;与串口通道绑定&#xff0c;建立起TCP与串口的通道&#xff0c;网关相当于一个中转点。 菜单选择"数据上行-tcp透传"&#xff0c;查看当前透传通道列表&…

QtCreator14调试Qt5.15出现 Launching Debugger 错误

1、问题描述 使用QtCreator14调试程序&#xff0c;Launching Debugger 显示红色&#xff0c;无法进入调试模式。 故障现象如下&#xff1a; 使能Debugger Log窗口&#xff0c;显示&#xff1a; 325^error,msg"Error while executing Python code." 不过&#xff…

反走样算法(MSAA、TAA、FXAA、DLSS)

光栅化的采样过程会导致图形走样,走样有很多种形式: 锯齿 摩尔纹 走样的本质原因是采样速度跟不上信号变化的速度 采样频率低,使得我们将连续变化的信号离散化. 反走样方法 anti-alisaing MSAA 多重采样反走样 超采样 优点&#xff1a; 对几何反走样效果良好 缺点…

【Python语言进阶(二)】

一、函数的使用方式 将函数视为“一等公民” 函数可以赋值给变量函数可以作为函数的参数函数可以作为函数的返回值 高阶函数的用法&#xff08;filter、map以及它们的替代品&#xff09; items1 list(map(lambda x: x ** 2, filter(lambda x: x % 2, range(1, 10)))) # filter…

uniapp uni.uploadFile errMsg: “uploadFile:fail

uniapp 上传后一直显示加载中 1.检查前后端上传有无问题 2.检查失败信息 await uni.uploadFile({url,filePath,name,formData,header,timeout: 30000000, // 自定义上传超时时间fail: async function(err) {$util.hideAll()// 失败// err 返回 {errMsg: "uploadFile:fai…

stata基本操作

文章目录 数据导入及存储变量的标签、审视数据变量的标签审视数据数据删除数据排序 画图直方图使用帮助文件散点图 统计分析描述性分析频数分析相关分析 生成新变量、计算器、终止命令生成新变量设置哑变量修改变量名更改变量内容调用命令和终止命令 日志命令库更新、学习资源 …

如何用pyhton修改1000+图片的名字?

import os oldpath input("请输入文件路径&#xff08;在windows中复制那个图片文件夹的路径就可以):") #注意window系统中的路径用这个‘\分割&#xff0c;但是编程语言中一般都是正斜杠也就是’/‘ #这里写一个代码&#xff0c;将 \ > / path "" fo…