【Spring】注解开发

news2024/12/26 20:25:14

为了提高开发效率,从 Spring 2.0 开始引入了多种注解,而在 Spring 3.0 中则实现了纯注解的开发方式。

一、注解的使用

在 Spring 2.0 之后,使用注解进行开发主要分为两个步骤:

  1. 定义 Bean:使用 @Component 注解来定义一个 Bean。
  2. 加载 Bean:在核心配置文件中,通过组件扫描功能来加载这些 Bean 所在包。

在定义和使用 Bean 时,我们可以通过指定 Bean 的名称来获取其实现对象,也可以通过类型自动装配来获取对象。

(1)通过指定名称获取 Bean 对象

在使用 @Component 定义 Bean 时,为 Bean 对象起名称。在实际应用时通过名称获取 Bean 对象:

// Bean 的定义
@Component("bookDao")
public class BookDaoImpl implements BookDao {
    @Override
    public void save() {
    }
}
// Bean 的应用
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
System.out.println(bookDao);

在定义 Bean 后,还需要在配置文件 applicationContext.xml 中指定需要 Spring 扫描的包,Spring 会扫描包下的类并注入相应的 Bean 对象:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
               http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
               http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <context:component-scan base-package="com.it"/>
</beans>

(2)通过类型自动装配 Bean 对象

这种方式与通过指定名称获取 Bean 对象的方式不同,因为它不需要为每个 Bean 设置唯一的名称。在实际应用中,Spring 会通过类型来自动装配 Bean 对象。虽然这种方法比指定名称更简便,但在存在多个相同类型的 Bean 的情况下,它就不太适用了。在使用时,仍然需要在配置文件中扫描指定的包。

// Bean 的定义
@Component
public class BookServiceImpl implements BookService {
    private BookDao bookDao;
    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }
}
// Bean 的应用
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
BookService bookService = ctx.getBean(BookService.class);
System.out.println(bookService);

另外,Spring 提供了 @Component 注解的三个衍生注解,分别是:

  • @Controller:用于表现层 bean 定义
  • @Service:用于业务层 bean 定义
  • @Repository:用于数据层 bean 定义

这些注解的功能与 @Component 相同,它们在不同层的使用主要是为了更清晰地表达代码结构。

二、纯注解模式

Spring 3.0 升级了纯注解开发模式,使用 Java 类代替配置文件,提高了 Spring 开发效率。下面是纯注解模式的简单使用过程:

(1)定义配置类

这里在 config 包下创建一个 SpringConfig 类,通过 @Configuration 注解设定当前类为配置类,通过 @ComponentScan 注解设定扫描路径,以此替代配置文件:

@Configuration
@ComponentScan("com.it")
public class SpringConfig {
}

其中,@ComponentScan 注解只能添加一次,但可以使用数组格式来实现多个扫描路径:

@Configuration
@ComponentScan({"com.it.dao", "com.it.service"})
public class SpringConfig {
}

(2)实际应用

在使用纯注解时,通过为 AnnotationConfigApplicationContext 指定配置类来获取上下文,并通过上下文获取需要的 Bean 对象:

ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
BookService bookService = ctx.getBean(BookService.class);
System.out.println(bookDao);
System.out.println(bookService);

2.1 Bean 作用范围

在纯注解模式下,Bean 的作用范围通过 @Scope 指定:

@Repository("bookDao")
@Scope("singleton")
public class BookDaoImpl implements BookDao {
    @Override
    public void save() {
    }
}

2.2 Bean 生命周期

在纯注解模式下,Bean 生命周期中初始化和销毁阶段通过 @PostConstruct@PreDestroy 注解实现。首先,在 pom.xml 文件中引入 javax 库:

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

接着,在定义 Bean 时,实现初始化和销毁操作:

@Repository("bookDao")
public class BookDaoImpl implements BookDao {
    @Override
    public void save() {
    }

    @PostConstruct
    public void init() {
        System.out.println("Init...");
    }

    @PreDestroy
    public void destroy() {
        System.out.println("Destroy...");
    }
}

在使用时,如果希望看到销毁操作的执行,需要调用 close() 方法:

public class AppForAnnotation {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        BookDao bookDao = (BookDao) ctx.getBean("bookDao");
        System.out.println(bookDao);
        ctx.close();
    }
}

2.3 Bean 依赖注入

与其他注解模式一样,纯注解模式的 Bean 依赖注入也分引用类型注入和简单类型注入。

(1)引用类型注入

在实现引用类型注入的过程中,可以选择自动装配注入,也可以通过指定名称的方式注入。

自动装配使用 @Autowired 注解实现注入。这种方式基于反射设计创建对象并暴力反射对应属性为私有属性初始化数据,因此无需提供 setter 方法。另外,
自动装配建议使用无参构造方法创建对象(默认),如果不提供对应构造方法,则需提供唯一的构造方法。

// 自动装配
@Component
public class BookServiceImpl implements BookService {
    @Autowired
    private BookDao bookDao;
    // ...
}

指定名称注入使用 @Qualifier 注解指定装配 Bean 的名称。需要注意的是 @Qualifier 注解无法单独使用,必须配合 @Autowired 注解使用。

// 指定名称
@Component
public class BookServiceImpl implements BookService {
    @Autowired
    @Qualifier("bookDao")
    private BookDao bookDao;
    // ...
}

(2)简单类型注入

使用 @Value 注解实现简单类型注入:

@Repository("bookDao")
public class BookDaoImpl implements BookDao {
    @Value("test")
    private String name;
    // ...
}

(3)配置文件注入

在引用类型和简单类型注入的基础上,可以使用配置文件完成更加复杂的注入。在 resources 文件夹下创建配置文件 jdbc.properties,其内容为:

name=test

使用 @PropertySource 注解在配置类中加载内容:

@Configuration
@ComponentScan({"com"})
@PropertySource("jdbc.properties")
public class SpringConfig {
}

通过 @Value 注解和 ${} 配合使用完成注入:

@Repository("bookDao") // 起名称为 bookDao
public class BookDaoImpl implements BookDao {
    @Value("${name}")
    private String name;

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

注意:路径仅支持单一文件配置,多文件请使用数组格式配置,不允许使用通配符*。

2.4 第三方 Bean 管理

在纯注解模式下,管理自定义 Bean 的过程可以遵循之前提到的定义 Bean 和包扫描的步骤。对于第三方提供的 Bean 对象,管理过程如下:以 Druid 数据库连接池为例。首先,我们需要定义一个方法来获取要管理的对象,也就是 DruidDataSource 对象。然后,在这个方法上添加 @Bean 注解,以表明该方法的返回值是一个 Bean 对象:

public class JdbcConfig {
    // 1. 定义一个方法获取要管理的对象
    // 2. 添加 @Bean,表示当前方法的返回值是一个 Bean
    @Bean("dataSource")
    public DataSource dataSource () {
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://localhost:3306/db");
        ds.setUsername("root");
        ds.setPassword("123456");
        return ds;
    }
}

这里将 JDBC 相关的配置类分离出来,并利用 @Import 注解手动加入配置类到核心配置,实现多个配置类的使用:

@Configuration
@Import({JdbcConfig.class})
public class SpringConfig {
}

之后,同样通过 AnnotationConfigApplicationContext 类对象获取上下文,再从上下文中获取指定的 Bean 对象:

public class App {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        DataSource dataSource = ctx.getBean(DataSource.class);
        System.out.println(dataSource);
    }
}

2.5 第三方 Bean 依赖注入

在纯注解模式下,当管理第三方 Bean 时,如果涉及到 Bean 对象的依赖注入,简单类型和引用类型的依赖注入可以通过以下方式实现:

(1)第三方简单类型注入

简单类型注入只需要为 Bean 定义对应成员变量,并通过 @Value 注解和变量调用实现注入:

public class JdbcConfig {
    @Value("com.mysql.jdbc.Driver")
    private String driver;
    @Value("jdbc:mysql://localhost:3306/db")
    private String url;
    @Value("root")
    private String userName;
    @Value("123456")
    private String password;
    
    // 1. 定义一个方法获取要管理的对象
    // 2. 添加 @Bean,表示当前方法的返回值是一个 Bean
    @Bean("dataSource")
    public DataSource dataSource () {
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(userName);
        ds.setPassword(password);
        return ds;
    }
}

(2)第三方引用类型注入

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

public class JdbcConfig {
    @Value("com.mysql.jdbc.Driver")
    private String driver;
    @Value("jdbc:mysql://localhost:3306/db")
    private String url;
    @Value("root")
    private String userName;
    @Value("123456")
    private String password;

    // 1. 定义一个方法获取要管理的对象
    // 2. 添加 @Bean,表示当前方法的返回值是一个 Bean
    @Bean("dataSource")
    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 对象已经注入,即需要确保传入的 Bean 对象被扫描到(添加 @ComponentScan 注解和对应 @Component 注解):

@Configuration
@Import({JdbcConfig.class})
@ComponentScan({"com.it"})
public class SpringConfig {
}
@Repository
public class BookDaoImpl implements BookDao {
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

从技术视角看AI在Facebook全球化中的作用

在全球化日益加深的今天&#xff0c;人工智能&#xff08;AI&#xff09;作为一种变革性技术&#xff0c;正在深刻影响全球互联网巨头的发展方向。Facebook作为全球最大的社交媒体平台之一&#xff0c;正通过AI技术突破语言、文化和技术的障碍&#xff0c;推动全球化战略的实现…

jmeter 压测常用静默参数解释应用

简介&#xff1a; JMeter静默压测&#xff08;即无界面压测&#xff09;是一种常用的性能测试方法&#xff0c;用于模拟多个用户同时访问系统并测量系统的响应时间和吞吐量等关键性能指标。在JMeter静默压测中&#xff0c;常用的压测参数及其解释如下&#xff1a; 一、基本…

【机器学习】分类任务: 二分类与多分类

二分类与多分类&#xff1a;概念与区别 二分类和多分类是分类任务的两种类型&#xff0c;区分的核心在于目标变量&#xff08;label&#xff09;的类别数&#xff1a; 二分类&#xff1a;目标变量 y 只有两个类别&#xff0c;通常记为 y∈{0,1} 或 y∈{−1,1}。 示例&#xff…

【自用】管材流转项目前端重部署流程 vue2 webpackage4 vuecli4

一、配置 1.下载项目&#xff0c;使用 IDEA 打开&#xff0c;并配置 Nodejs 它提示我&#xff0c;需要 Node.js&#xff0c;因为 nodejs 14 的 installer 已经官网已经找不到了&#xff0c;使用 fnm 又太麻烦&#xff0c; 所以直接采用在 IDEA 中下载的方式就好了。 2.清除缓…

java调用ai模型:使用国产通义千问完成基于知识库的问答

整体介绍&#xff1a; 基于RAG&#xff08;Retrieval-Augmented Generation&#xff09;技术&#xff0c;可以实现一个高效的Java智能问答客服机器人。核心思路是将预先准备的问答QA文档&#xff08;例如Word格式文件&#xff09;导入系统&#xff0c;通过数据清洗、向量化处理…

跨平台应用开发框架(4)----Qt(系统篇)

目录 1.Qt事件 1.事件来源 2.事件处理 3.按键事件 1.组合按键 4.鼠标事件 1.鼠标单击事件 2.鼠标释放事件 3.鼠标双击事件 4.鼠标移动事件 5.滚轮事件 5.定时器 1.QTimerEvent类 2.QTimer 类 3.获取系统日期及时间 6.事件分发器 7.事件过滤器 2.Qt文件 1.输入…

算法刷题Day8:BM30 二叉搜索树与双向链表

题目 牛客网题目传送门 思路 对二叉搜索树进行中序遍历&#xff0c;结果就是按序数组。因此想办法把前面遍历过的节点给记下来&#xff0c;记作pre。当遍历到某个节点node的时候&#xff0c;令前驱指向pre&#xff0c;然后让pre的后驱指向node。 代码 class TreeNode:def…

MySQL--视图

目录 1 认识视图 1.1 视图的定义 1.1 创建视图 1.2 查询 1.3 修改 1.4 删除 1.5 视图的优缺点 1.5.1 优点 1.5.2 缺点 1.6 视图的类型 1.7 视图与物化视图 2 视图检查选项 2.1 CASCADED 2.2 LOCAL 3 视图更新及作用 3.1 视图案列结合 3.1.1 屏蔽敏感数据 3.1…

基于Matlab高速动车组转臂定位橡胶节点刚度对车辆动力学影响仿真研究

本研究针对高速动车组转臂定位系统中橡胶节点的刚度对车辆动力学性能的影响进行仿真研究。随着高速铁路的发展&#xff0c;动车组的运行稳定性和舒适性成为设计和运营的核心问题&#xff0c;其中&#xff0c;转臂定位系统作为动车组悬挂系统的重要组成部分&#xff0c;其性能对…

并发专题(8)之JUC阻塞容器源码剖析

一、ArrayBlockingQueue源码剖析 ArrayBlockingQueue底层是采用数组实现的一个队列。因为底层是数据&#xff0c;一般被成为有界队列、其阻塞模式是基于ReentrantLock来实现的。 // 存数据操作 add(E),offer(E),put(E)&#xff0c;offer(E,time,unit) // add(E)&#xff1a;添加…

AI/ML 基础知识与常用术语全解析

目录 一.引言 二.AI/ML 基础知识 1.人工智能&#xff08;Artificial Intelligence&#xff0c;AI&#xff09; (1).定义 (2).发展历程 (3).应用领域 2.机器学习&#xff08;Machine Learning&#xff0c;ML&#xff09; (1).定义 (2).学习方式 ①.监督学习 ②.无监督…

【WRF-Urban】WPS中有关Urban的变量设置

【WRF-Urban】WPS中有关Urban的变量设置 地理数据源的配置WRF-Urban所需静态地理数据1、LANDUSE&#xff1a;包含城市地表分类的土地利用数据。2、URB_PARAM&#xff1a;城市参数数据集。3、FRC_URB2D&#xff1a;城市覆盖度数据集 WRF默认设置&#xff08;美国&#xff09;数据…

NVR录像机汇聚管理EasyNVR多个NVR同时管理基于B/S架构的技术特点与能力应用

EasyNVR视频融合平台基于云边端协同设计&#xff0c;能够轻松接入并管理海量的视频数据。该平台兼容性强、拓展灵活&#xff0c;提供了视频监控直播、录像存储、云存储服务、回放检索以及平台级联等一系列功能。B/S架构使得EasyNVR实现了视频监控的多元化兼容与高效管理。 其采…

c++预编译头文件

文章目录 c预编译头文件1.使用g编译预编译头文件2.使用visual studio进行预编译头文件2.1visual studio如何设置输出预处理文件&#xff08;.i文件&#xff09;2.2visual studio 如何设置预编译&#xff08;初始创建空项目的情况下&#xff09;2.3 visual studio打开输出编译时…

Zookeeper的通知机制是什么?

大家好&#xff0c;我是锋哥。今天分享关于【Zookeeper的通知机制是什么?】面试题。希望对大家有帮助&#xff1b; Zookeeper的通知机制是什么? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Zookeeper的通知机制主要通过Watcher实现&#xff0c;它是Zookeeper客…

基于Pyside6开发一个通用的在线升级工具

UI main.ui <?xml version"1.0" encoding"UTF-8"?> <ui version"4.0"><class>MainWindow</class><widget class"QMainWindow" name"MainWindow"><property name"geometry"&…

开源 - Ideal库 - Excel帮助类,ExcelHelper实现(四)

书接上回&#xff0c;前面章节已经实现Excel帮助类的第一步TableHeper的对象集合与DataTable相互转换功能&#xff0c;今天实现进入其第二步的核心功能ExcelHelper实现。 01、接口设计 下面我们根据第一章中讲解的核心设计思路&#xff0c;先进行接口设计&#xff0c;确定Exce…

嵌入式系统应用-LVGL的应用-平衡球游戏 part1

平衡球游戏 part1 1 平衡球游戏的界面设计2 界面设计2.1 背景设计2.2 球的设计2.3 移动球的坐标2.4 用鼠标移动这个球2.5 增加边框规则2.6 效果图2.7 游戏失败重启游戏 3 为小球增加增加动画效果3.1 增加移动效果代码3.2 具体效果图片 平衡球游戏 part2 第二部分文章在这里 1 …

《Python基础》之Pandas库

目录 一、简介 二、Pandas的核心数据结构 1、Series 2、DataFrame 三、数据读取与写入 1、数据读取 2、数据写入 四、数据清洗与处理 1、处理缺失值 2、处理重复值 3、数据转换 五、数据分析与可视化 1、统计描述 2、分组聚合 3、数据可视化 六、高级技巧 1、时…

网络安全-夜神模拟器如何通过虚拟机的Burp Suite代理应用程序接口

第一步、查看虚拟机的IP地址 我们可以通过ifconfig命令来查看虚拟机的IP地址,如下图所示。 第二步、在Burp Suite上设置代理 打开虚拟机上的Burp Suite,进入到代理模块中,进入到代理设置中心 打开系统代理设置中心之后,将我们虚拟机的地址添加到上面,作为新的代理。 第…