Spring注解开发

定义bean

我们先直接通过一张图来理解注解在Spring开发中如和定义bean:
注解

那么我们既然加了注解,相当于定义了bean可是Spring的配置文件怎么知道他的存在,于是我们引入component-scan进行包扫描即为了让Spring框架能够扫描到写在类上的注解,我们必需要在配置文件上进行包扫描

<context:component-scan base-package="。。。"/

component-scan

  • component:组件,Spring将管理的bean视作自己的一个组件
  • scan:扫描

base-package指定Spring框架扫描的包路径,它会扫描指定包及其子包中的所有类上的注解。

  • 包路径越多[如:com.taro.dao.impl],扫描的范围越小速度越快
  • 包路径越少[如:com.taro],扫描的范围越大速度越慢
  • 一般扫描到项目的组织名称即Maven的groupId下[如:com.taro]即可。

@Component注解如果不起名称,会有一个默认值就是当前类名首字母小写,所以也可以按照名称获取

对于@Component注解,还衍生出了其他三个注
@Controller : 表现层、@Service :业务层、@Repository :数据层
来定义bean。

纯注解开发

顾名思义架空配置文件(建一个配置类),把权力掌握在我们自己手里,一张图理解一下

配置注解

-@Configuration注解用于设定当前类为配置类
-@ComponentScan注解用于设定扫描路径,此注解只能添加一次,多个数据请用数组格式(用花括号把路径加起来)

可是问题来了主程序怎么知道配置在哪捏?

  • 只需要重新建一个启动类加载配置类就好啦
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);

我们注意一下下面这些小点哦

  • 记住@Component、@Controller、@Service、@Repository这四个注解
  • applicationContext.xml中< context:component-san />的作用是指定扫描包路径,注解为@ComponentScan
  • @Configuration标识该类为配置类,使用类替换applicationContext.xml文件
  • ClassPathXmlApplicationContext是加载XML配置文件
  • AnnotationConfigApplicationContext是加载配置类

注解开发时bean的生命周期控制

众所周知我们的Spring在创建bean时默认都是单例的,这个我们在之前的文章也进行过演示,当我们需要在注解开发时,使bean的创建变成非单例,只需要在其类上添加@Scope(“prototype”)注解

当然我们之前也在配置文件中提到过init-method等属性来定义初始化方法与销毁方法,那么我们现在通过注解开发,没有了配置文件该怎么解决?

  • @PostConstruct //在构造方法之后执行,替换 init-method
  • @PreDestroy //在销毁方法之前执行(容器关闭时执行),替换 destroy-method

@PostConstruct和@PreDestroy注解如果找不到,需要导入javax.annotation-api这个jar包,因为jdk9版本开始删掉了这个包

<dependency> <groupId>javax.annotation</groupId> 
	<artifactId>javax.annotation-api</artifactId> 
	<version>1.3.2</version> 
</dependency>

我们小小通过一张图总结下bean的注解:
注解示意图


依赖注入

Spring为了使用注解简化开发,并没有提供构造函数注入、setter注入对应的注解,只提供了自动装配的注解实现。

自动装配

@Autowired(他是按类型装配的);如果类型相同使用@Qualifirt(“名称”),来制定名称注入

  • @Autowired可以写在属性上,也可也写在setter方法上,最简单的处理方式是写在属性上并将 setter方法删除掉,因为自动装配基于反射设计创建对象并通过暴力反射为私有属性进行设值;普通反射只能获取public修饰的内容,暴力反射除了获取public修饰的内容还可以获取private修改的内容所以此处无需提供setter方法
  • @Autowired默认按照类型自动装配,如果IOC容器中同类的Bean找到多个,就按照变量名和Bean的名称匹配。因为变量名叫bookDao而容器中也有一个booDao,所以可以成功注入。
    🍊个🌰:
    按名称找不到
    这样呢就会报错,因为按照类型会找到多个bean对象,此时会按照bookDao名称去找,因为IOC容器只有名称叫bookDao1和bookDao2 ,所以找不到,会报NoUniqueBeanDefinitionException

指定名称注入

@Qualifier
明明就这一个为啥还要单独放一个标题捏?
@Qualifier注解后的值就是需要注入的bean的名称。

  • 注意:@Qualifier不能独立使用,必须和@Autowired一起使用

🍊个🌰:

@Service
public class BookServiceImpl implements BookService {
    @Autowired
    @Qualifier("bookDao1")
    private BookDao bookDao;
    
    public void save() {
        System.out.println("book service save ...");
        bookDao.save();
    }
}

当然我们现在提到的都是应用类型的注入那么。。。。

简单类型的注入

@Value(“…”)

🍊个🌰:

@Repository("bookDao")
public class BookDaoImpl implements BookDao {
    @Value("taro")
    private String name;
    public void save() {
        System.out.println("book dao save ..." + name);
    }
}

很明显明明加在name直接给name赋值更方便,那为什么还要专门注入捏?有没有一种可能,这个值还可以来自配置文件。

注解读取properties配置文件

主要也就是针对@Value
1、准备配置文件
2、在配置类使用注解加载properties配置文件(@PropertySource)
3、使用@Value读取配置文件中的内容

🍊个🌰:
1、准备配置文件

我们准备一个名为jdbc.properties的配置文件并添加“name=taro”

2、使用注解加载properties配置文件(@PropertySource)

@Configuration
@ComponentScan("com.itheima")
//@PropertySource加载properties配置文件
@PropertySource({"jdbc.properties"})
public class SpringConfig {
}

3、使用@Value读取配置文件中的内容

@Repository("bookDao")
public class BookDaoImpl implements BookDao {
    //@Value:注入简单类型(无需提供set方法)
    @Value("${name}")
    private String name;

    public void save() {
        System.out.println("book dao save ..." + name);
    }
}

运行结果

  • 如果读取的properties配置文件有多个,可以使用@PropertySource的属性来指定多个
    🍊个🌰:
    @PropertySource({"jdbc.properties","xxx.properties"})

  • @PropertySource注解属性中可以把classpath:加上,代表从当前项目的根路径找文件

  • 🍊个🌰:
    @PropertySource({"classpath:jdbc.properties"})

稍微总结一下注入的注解吧:

@Autowired

名称@Autowired
类型属性注解 或 方法注解(了解) 或 方法形参注解(了解)
位置属性定义上方 或 标准set方法上方 或 类set方法上方 或 方法形参前面
作用为引用类型属性设置值
属性required:true/false,定义该属性是否允许为null

@Qualifier

名称@Qualifier
类型属性注解 或 方法注解(了解)
位置属性定义上方 或 标准set方法上方 或 类set方法上方
作用为引用类型属性指定注入的beanId
属性value(默认):设置注入的beanId

@Value

名称@Value
类型属性注解 或 方法注解(了解)
位置属性定义上方 或 标准set方法上方 或 类set方法上方
作用为 基本数据类型 或 字符串类型 属性设置值
属性value(默认):要注入的属性值

@PropertySource

名称@PropertySource
类型类注解
位置类定义上方
作用加载properties文件中的属性值
属性value(默认):设置加载的properties文件对应的文件名或文件名组成的数组

注解开发管理第三方bean

@Bean

名称@Bean
类型方法注解
位置方法定义上方
作用设置该方法的返回值作为spring管理的bean
属性value(默认):定义bean的id

@Import

名称@Import
类型类注解
位置类定义上方
作用导入配置类
属性value(默认):定义导入的配置类类名,
当配置类有多个时使用数组格式一次性导入多个配置类

嗯。。。其实就这俩
值得注意的是@Import 只能写一次,需要导入多个就跟在后面用数组格式

注解开发实现为第三方bean注入资源

提个问题:在使用@Bean创建bean对象的时候,如果这个方法在创建的过程中需要其他资源捏?我们怎么把其他资源给他捏?
公布答案:注入咯,所以既然是注入,那么一样的,也就分两种简单类型和引用类型咯。

简单类型

其实看一下这个🌰就明白了:
使用@Value注解引入值


public class JdbcConfig {
    @Value("com.mysql.jdbc.Driver")
    private String driver;
    @Value("jdbc:mysql://localhost:3306/spring_db")
    private String url;
    @Value("root")
    private String userName;
    @Value("password")
    private String password;
	@Bean
    public DataSource dataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(userName);
        ds.setPassword(password);
        return ds;
    }
}

引用类型

提出需求:假设在构建DataSource对象的时候,需要用到BookDao对象,该如何把BookDao对象注入进方法内让其使用呢?
如下图所示:

public class JdbcConfig {
	@Bean
    public DataSource dataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
        ds.setUsername("root");
        ds.setPassword("root");
        return ds;
    }
}

解决方案:

🍊个🌰:

1、在SpringConfig中扫描BookDao;扫描的目的是让Spring能管理到BookDao,也就是说要让IOC容器中有一个bookDao对象

@Configuration
@ComponentScan("com.taro.dao")
@Import({JdbcConfig.class})
public class SpringConfig {
}

2、在JdbcConfig类的方法上添加参数

@Bean
public DataSource dataSource(BookDao bookDao){
    System.out.println(bookDao);
    DruidDataSource ds = new DruidDataSource();
    ds.setDriverClassName(driver);
    ds.setUrl(url);
    ds.setUsername(userName);
    ds.setPassword(password);
    return ds;
}

引用类型注入只需要为bean定义方法设置形参即可,容器会根据类型自动装配对象。


最后对Spring注解开发做个总结吧:
注解总结

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

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

相关文章

Lego- 美团接口自动化测试实战(详细解析)

目录&#xff1a;导读 一、概述 1.1 接口自动化概述 1.2 提高 ROI 1.3 Lego 的组成 二、脚本设计 2.1 Lego 的做法 2.2 测试脚本 2.3 配置文件 三、用例设计 3.1 一些思考 3.2 Lego 接口自动化测试用例 3.3 参数化 3.4 前后置动作 3.5 执行各部分 四、网站功能 …

八百字讲清楚——BCEWithLogitsLoss二分类损失函数

BCEWithLogitsLoss是一种用于二分类问题的损失函数&#xff0c;它将Sigmoid函数和二元交叉熵损失结合在一起。 假设我们有一个大小为NNN的二分类问题&#xff0c;其中每个样本xix_ixi​有一个二元标签yi∈0,1y_i\in {0,1}yi​∈0,1&#xff0c;并且我们希望预测每个样本的概率…

Seal AppManager发布:基于平台工程理念的全新应用部署管理体验

4月12日&#xff0c;数澈软件Seal&#xff08;以下简称“Seal”&#xff09;宣布推出新一代应用统一部署管理平台 Seal AppManager&#xff0c;采用平台工程的理念&#xff0c;降低基础设施操作的复杂度为研发和运维团队提供易用、一致的应用管理和部署体验&#xff0c;进而提升…

28岁,他是如何成为上市公司测试总监的

现在的大环境下&#xff0c;各行各业都开始内卷起来&#xff0c;测试也不例外&#xff0c;企业要求也越来越高&#xff0c;“会代码”逐渐成为测试工程师的一个标签。你要想拿到一个不错的薪资&#xff0c;必不可少的一个技能—自动化测试&#xff0c;自动化测试难吗&#xff1…

【2023最新】超详细图文保姆级教程:App开发新手入门(5)

上文回顾&#xff0c;我们已经完成了一个应用的真机调试&#xff0c;本章我们来了解一下如何引入YonBuilder移动开发的&#xff08;原生&#xff09;移动插件, 并利用移动插件完成一个简单的视频播放器。 8. 「移动插件」的使用 8.1 什么是 「移动插件」&#xff1f; 用通俗…

HDLBits-Modules 题解【Verilog模块例化】(中文翻译+英文原文,可顺带学习英文)

Moudule 概念介绍 到目前为止&#xff0c;你已经熟悉了一个模块&#xff0c;它是一个通过输入和输出端口与其外部交互的电路。更大、更复杂的电路是通过将较小的模块和其他连接在一起的部分&#xff08;例如赋值语句和always块&#xff09;组合而成的更大模块来构建的。因为模…

对决:Kubernetes vs Docker Swarm - 谁才是最优秀的容器编排方案?

✅创作者&#xff1a;陈书予 &#x1f389;个人主页&#xff1a;陈书予的个人主页 &#x1f341;陈书予的个人社区&#xff0c;欢迎你的加入: 陈书予的社区 文章目录一、介绍1. 什么是Kubernetes2. 什么是Docker Swarm3. 为什么需要容器编排&#xff1f;二、 架构比较1. Kubern…

C++【栈队列(3种)反向迭代器】

文章目录一、容器适配器二、栈&#xff08;一&#xff09;栈定义&#xff08;二&#xff09;栈使用接口&#xff08;三&#xff09;栈模拟实现(1) 栈模拟实现解析(2) 栈模拟实现代码(3) 栈模拟结果三、队列&#xff08;一&#xff09;普通队列&#xff08;1&#xff09;普通队列…

30天学会《Streamlit》(3)

30学会《Streamlit》是一项编码挑战&#xff0c;旨在帮助您开始构建Streamlit应用程序。特别是&#xff0c;您将能够&#xff1a; 为构建Streamlit应用程序设置编码环境 构建您的第一个Streamlit应用程序 了解用于Streamlit应用程序的所有很棒的输入/输出小部件 第3天 - st.…

实验三、图像复原

1. 实验目的 (1) 理解退化模型。 (2) 掌握常用的图像复原方法。 2. 实验内容 (1) 模拟噪声的行为和影响的能力是图像复原的核心。 示例 1 &#xff1a;使用 imnoise 添加噪声。 J imnoise(I,gaussian) 将方差为 0.01 的零均值高斯白噪声添加到灰度图像 I。 J imnoise(I,g…

最近ChatGPT封号太严重了,这里是解封攻略步骤(建议收藏)

这个周末&#xff0c;先是意大利暂时封杀ChatGPT&#xff0c;限制OpenAI处理本国用户信息。 接着&#xff0c;据韩国媒体报道&#xff0c;三星导入ChatGPT不到20天&#xff0c;便曝出机密资料外泄。 还没结束&#xff0c;又有大量网友发现ChatGPT目前停止注册&#xff0c;开始…

​力扣解法汇总1026. 节点与其祖先之间的最大差值

目录链接&#xff1a; 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目&#xff1a; https://github.com/September26/java-algorithms 原题链接&#xff1a;力扣 描述&#xff1a; 给定二叉树的根节点 root&#xff0c;找出存在于 不同 节点 A 和 B 之间的最大值…

Samba共享

关闭selinux跟防火墙 setenforce 0 systemctl stop firewalld 安装samba以及客户端 yum install samba samba-client -y 创建共享目录 mkdir -p /data/share1 mkdir -p /data/public 添加samba用户并配置权限 useradd zsuser smbpasswd -a zsuser 修改配置文件并重启服…

【Hello Linux】信号量

作者&#xff1a;小萌新 专栏&#xff1a;Linux 作者简介&#xff1a;大二学生 希望能和大家一起进步&#xff01; 本篇博客简介&#xff1a;简单介绍linux中信号量的概念 信号量信号量的概念信号量的使用信号量函数二元信号量模拟互斥功能基于环形队列的生产者消费者模型空间资…

23-Ajax-axios

一、原生Ajax <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-width…

中科大ChatGPT学术镜像小白部署教程,全民都可以拥抱AI

docker…不会用…python不会用…服务器默认python版本3.6不会升级…代理也不会配置…各种命令不会用… 那么下面就是最简单办法&#xff0c;点点点即可【希望有帮助&#xff1f;】 文章目录一、体验镜像地址二、 基本配置2.1 config.py文件2.2 main.py文件三、下载项目四、项目…

【C++】哈希表:开散列和闭散列

&#x1f4dd; 个人主页 &#xff1a;超人不会飞)&#x1f4d1; 本文收录专栏&#xff1a;《C的修行之路》&#x1f4ad; 如果本文对您有帮助&#xff0c;不妨点赞、收藏、关注支持博主&#xff0c;我们一起进步&#xff0c;共同成长&#xff01; 目录前言一、基于哈希表的两个…

一条更新语句的执行流程又是怎样的呢?

当一个表上有更新的时候&#xff0c;跟这个表有关的查询缓存会失效&#xff0c;所以这条语句就会把表T上所有缓存结果都清空。这也就是我们一般不建议使用查询缓存的原因。 接下来&#xff0c;分析器会通过词法和语法解析知道这是一条更新语句。优化器决定要使用ID这个索引。然…

JAVA+SQL离散数学题库管理系统的设计与开发

题库、试卷建设是教学活动的重要组成部分&#xff0c;传统手工编制的试卷经常出现内容雷同、知识点不合理以及笔误、印刷错误等情况。为了实现离散数学题库管理的信息化而开发了离散数学题库管理系统。 该系统采用C/S 模式&#xff0c;前台采用JAVA&#xff08;JBuilder2006&am…

如何选择合适的网络自动化工具

通过网络自动化工具实现网络自动化是所有网络组织的关键。如果没有合适的网络自动化工具&#xff0c;拥有由许多设备组成的大型网络环境的组织将无法执行重要操作&#xff0c;例如按时备份配置、实时跟踪不需要的更改以及遵守行业法规。当组织未能使用正确的网络自动化工具来执…