【Spring 篇】深入浅出:用Spring注解开发的奇妙之旅

news2024/11/18 9:48:55

在这里插入图片描述

在编程的世界里,Spring框架如同一位慈祥的导师,为我们打开了无尽可能性的大门。而在Spring的广袤领域中,注解是我们最亲密的伙伴之一。本篇博客将深入浅出地介绍使用Spring注解进行开发的奇妙之旅,为你解开注解的神秘面纱。

前奏:认识Spring框架

首先,让我们简单了解一下Spring框架。Spring是一个全栈式的Java开发框架,它提供了广泛的功能,包括依赖注入、面向切面编程、数据访问等。Spring的核心思想是IoC(控制反转)和AOP(面向切面编程),它使得我们能够更加灵活、模块化地构建应用程序。

注解入门

在过去,我们可能会通过XML配置来使用Spring框架,但是随着时间的推移,注解成为了更为流行的选择。注解是一种元数据,它提供了对类、方法、字段等元素进行标记的能力,通过在代码中添加注解,我们能够告诉Spring框架如何处理我们的类和方法。

让我们从最简单的注解开始:

@Component
public class HelloWorld {
    public void greet() {
        System.out.println("Hello, World!");
    }
}

在这个例子中,@Component注解告诉Spring框架将HelloWorld类注册为一个组件,使得Spring能够管理它的生命周期,并在需要时创建它的实例。

依赖注入的魔法

依赖注入是Spring框架的一项重要特性,通过它,我们能够将一个对象的依赖关系交给Spring来管理。这样一来,我们的代码就变得更加松散耦合,更容易维护和测试。

让我们看一个简单的例子:

@Component
public class Car {
    private Engine engine;

    @Autowired
    public Car(Engine engine) {
        this.engine = engine;
    }

    public void start() {
        engine.start();
        System.out.println("Car started!");
    }
}

@Component
public class Engine {
    public void start() {
        System.out.println("Engine started!");
    }
}

在这个例子中,Car类有一个对Engine的依赖关系。通过在构造方法上加上@Autowired注解,我们告诉Spring框架需要注入一个Engine实例。当我们调用car.start()时,Spring会自动将Engine实例注入到Car中,实现依赖注入的魔法。

切面编程的艺术

面向切面编程是Spring框架的另一项强大功能,它使得我们能够在不修改原有代码的情况下,通过横切关注点(cross-cutting concerns)来增强应用程序的功能。

让我们通过一个日志切面的例子来了解切面编程:

@Aspect
@Component
public class LoggingAspect {

    @Before("execution(* com.example.service.*.*(..))")
    public void logBefore(JoinPoint joinPoint) {
        System.out.println("Before method: " + joinPoint.getSignature().getName());
    }

    @After("execution(* com.example.service.*.*(..))")
    public void logAfter(JoinPoint joinPoint) {
        System.out.println("After method: " + joinPoint.getSignature().getName());
    }
}

在这个例子中,@Aspect注解表示这是一个切面类,通过在方法上使用@Before@After注解,我们定义了在执行某个包中所有方法前后打印日志的逻辑。通过在Spring配置中启用切面,这些日志将自动地被添加到相应的方法中,而无需修改原有的业务逻辑。

注解的默契舞蹈

Spring框架提供了许多内置的注解,它们为我们提供了极大的便利。下面是一些常用的注解及其作用:

  • @Component: 用于标记一个类为Spring组件,由Spring自动管理。
  • @Autowired: 用于进行依赖注入。
  • @Service, @Repository, @Controller: 用于标记分别为服务、仓库和控制器的Spring组件。
  • @Configuration: 用于定义配置类,替代XML配置文件。
  • @Bean: 用于定义Spring Bean。
  • @Scope: 用于指定Bean的作用域。
  • @Value: 用于注入外部配置文件的值。
  • @RequestMapping: 用于处理HTTP请求的映射。

让我们通过一个完整的例子来展示这些注解的默契舞蹈:

@Controller
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("/{id}")
    public ResponseEntity<User> getUserById(@PathVariable Long id) {
        User user = userService.getUserById(id);
        return ResponseEntity.ok(user);
    }

    @PostMapping
    public ResponseEntity<User> createUser(@RequestBody User user) {
        userService.createUser(user);
        return ResponseEntity.status(HttpStatus.CREATED).body(user);
    }
}

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    public User getUserById(Long id) {
        return userRepository.findById(id).orElse(null);
    }

    public void createUser(User user) {
        userRepository.save(user);
    }
}

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}

在这个例子中,@Controller注解标记UserController为Spring MVC的控制器,通过@RequestMapping指定了映射路径。@Service注解标记UserService为服务组件,而@Repository注解标记UserRepository为Spring的数据仓库。

通过@Autowired注解,我们将UserServiceUserRepository注入到UserControllerUserService中,实现了依赖注入。这种通过注解来声明组件和配置的方式,使得代码更加清晰,减少了样板代码,提高了开发效率。

自定义注解的魔法

除了Spring提供的内置注解外,我们还可以通过自定义注解来实现更灵活的功能。自定义注解为我们提供了在代码中添加自定义元数据的能力,从而实现更加精细的控制和逻辑。

让我们通过一个简单的例子来看看如何自定义注解:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface LogExecutionTime {
}

在这个例子中,我们定义了一个名为LogExecutionTime的注解,它标记在方法上,并在运行时保留。接下来,我们可以使用这个注解来记录方法的执行时间:

@Service
public class MyService {

    @LogExecutionTime
    public void performTimeConsumingOperation() {
        // 执行一些耗时的操作
    }
}

通过结合AOP和自定义注解,我们可以在方法执行前后添加逻辑,实现更加灵活的功能。例如,我们可以在LogAspect切面类中定义在方法执行前后记录时间的逻辑:

@Aspect
@Component
public class LogAspect {

    @Around("@annotation(LogExecutionTime)")
    public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();

        Object proceed = joinPoint.proceed();

        long endTime = System.currentTimeMillis();
        System.out.println(joinPoint.getSignature() + " executed in " + (endTime - startTime) + "ms");

        return proceed;
    }
}

在这个例子中,@Around注解表示在目标方法执行前后都会执行,通过@annotation(LogExecutionTime)指定了切入点为标记有LogExecutionTime注解的方法。通过这种方式,我们成功地在performTimeConsumingOperation方法执行前后记录了执行时间。

注解开发的小白教程

对于初学者而言,注解开发可能会显得有些晦涩难懂。但是只要理解了一些基本概念,就能够轻松地踏入注解的奇妙世界。

1. 注解的基本语法

注解的基本语法相对简单,通常以@符号开头,后面跟着注解的名称和一对圆括号。有些注解还需要在圆括号中添加一些参数。例如:

@AnnotationName(parameter = "value")
public class MyClass {
    // class body
}

2. 注解的作用范围

注解可以标记在类、方法、字段等不同的元素上,具体取决于注解的@Target注解定义。例如,@Target(ElementType.METHOD)表示该注解只能标记在方法上。

3. 注解的生命周期

注解的生命周期由@Retention注解定义,通常有三个生命周期:

  • RetentionPolicy.SOURCE: 注解仅在源代码中存在,编译时会被忽略。
  • RetentionPolicy.CLASS: 注解在源代码和编译后的字节码中存在,但在运行时会被忽略。
  • RetentionPolicy.RUNTIME: 注解在源代码、编译后的字节码和运行时都存在,可以在运行时通过反射获取。

4. 注解的处理方式

Spring框架通过使用AOP(面向切面编程)来处理注解。在底层,Spring通过扫描类路径中的组件,识别并处理标记有特定注解的类和方法。这种方式使得开发者无需手动处理注解,而是通过配置和约定实现自动化。

5. 常用的Spring注解

在Spring中,有一些常用的注解是我们开发中经常会遇到的,例如@Component@Autowired@Service@Repository@Controller等。了解这些注解的作用和用法,能够更好地理解和使用Spring框架。

结语

通过本篇博客,我们深入浅出地探索了使用Spring注解进行开发的奇妙之旅。从最基础的注解入门,到依赖注入、切面编程、内置注解、自定义注解,一步步揭开了注解的神秘面纱。希望通过这篇博客,你能更好地理解和运用Spring注解,为自己的项目注入更多灵活和强大的功能。在注解的世界里,让我们一起跳起默契的舞蹈,创造出更加优雅的代码!

作者信息

作者 : 繁依Fanyi
CSDN: https://techfanyi.blog.csdn.net
掘金:https://juejin.cn/user/4154386571867191

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

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

相关文章

游泳时用什么耳机听歌好? 口碑最好的游泳耳机分享

在游泳的律动中&#xff0c;欣赏动感音乐或沉浸在激励的声音中&#xff0c;无疑是一种愉悦的体验。因此&#xff0c;在选择一款适合游泳的耳机时&#xff0c;不仅需要考虑音质和舒适度&#xff0c;还要兼顾防水性能&#xff0c;确保在水中也能畅快聆听。本文将为您介绍一些备受…

jupyter内核错误

1、在dos窗口输入以下命令激活环境&#xff1a;anaconda activate 【py环境名&#xff0c;比如py37】&#xff08;目的是新家你一个虚拟环境&#xff09; 2、在虚拟环境py37下安装jupyter notebook&#xff0c;命令&#xff1a;pip install jupyter notebook 3、安装ipykerne…

强化学习的数学原理学习笔记 - 值函数近似(Value Function Approximation)

文章目录 概览&#xff1a;RL方法分类值函数近似&#xff08;Value function approximation&#xff09;Basic idea目标函数&#xff08;objective function&#xff09;优化算法&#xff08;optimization algorithm&#xff09; Sarsa / Q-learning with function approximati…

Windows中处理PySpark报错:SparkException: Python worker failed to connect back

Windows中处理PySpark报错&#xff1a;SparkException: Python worker failed to connect back 这个问题可能是发送在windows10以上的版本&#xff0c;使用datafram的方法是没问题&#xff0c;但是使用rdd算子出现这个问题&#xff0c;报错SparkException: Python worker fail…

企业常用的几种实用的加速FTP传输方式

FTP作为互联网上最早应用的文件传输协议之一&#xff0c;同时也是企业内外常用的文件和数据交换方式。然而&#xff0c;随着数据量的增加和对传输速度、稳定性、安全性等要求的提高&#xff0c;FTP传输面临一系列挑战&#xff0c;给企业的业务效率和数据安全带来了困扰。本文将…

大数据深度学习长短时记忆网络(LSTM):从理论到PyTorch实战演示

文章目录 大数据深度学习长短时记忆网络&#xff08;LSTM&#xff09;&#xff1a;从理论到PyTorch实战演示1. LSTM的背景人工神经网络的进化循环神经网络&#xff08;RNN&#xff09;的局限性LSTM的提出背景 2. LSTM的基础理论2.1 LSTM的数学原理遗忘门&#xff08;Forget Gat…

【软考中级-软件设计师】day4:数据结构-线性表、单链表、栈和队列、串

大纲 线性结构 顺序存储和链式存储区别 单链表的插入和删除 真题 栈和队列 真题 串

python匹配问题

脏数据匹配 一般数据建模步骤中&#xff0c;数据清洗耗时占比80%以上&#xff0c;因为现实中接触到的数据相当脏&#xff0c;无法直接简单的用pandas的merge函数解决。下面以QS大学排名的匹配为例&#xff0c;简单介绍脏数据匹配中会遇到的问题和主要步骤。 1 问题描述 给定…

PyQT5实现图像处理应用(含Windows7下完整打包方案)

目录 1、任务概述2、环境安装2.1 创建虚拟环境2.2 安装依赖库 3、程序开发3.1 框架搭建3.2 读取图像3.3 图像处理 4、打包部署5、小结 1、任务概述 本篇博文将通过PyQT5来实现一个简单的图像处理应用&#xff0c;并完成打包部署。 本文开发平台&#xff1a;Windows10 64位系统…

【Vue3】2-6 : 计算属性与侦听器区别与原理(一)

本书目录&#xff1a;点击进入 一、计算属性 - computed:{} 1.1 目的 1.2 写法 代码 二、特征 2.1 调用时当属性调用 2.2 缓存 2.3 默认只读 2.4 可赋值&#xff1a;需要定义成对象&#xff0c;并写get&#xff0c;set方法 &#xff08;类似于java&#xff09; 三、原…

《More Effective C++》学习

条款1&#xff1a;仔细区别 pointers 和 references 引用应该被初始化&#xff0c;指针可以不被初始化。不存在指向空值的引用这个事实意味着使用引用的代码效率比使用指针的要高。因为在使用引用之前不需要测试它的合法性。指针与引用的另一个重要的不同是指针可以被重新赋值…

IDC MarketScape 低/无代码厂商评估:得帆信息被评为领导者

《IDC MarketScape:中国低代码/无代码开发平台2023年厂商评估 》报告正式发布。报告从战略与能力两大方向&#xff0c;在产品和功能、客户交付服务能力、营销和销售能力、伙伴与生态、商业战略模式等多个维度对国内低/无代码厂商进行全面评估。 得帆信息凭借战略与能力双项领先…

电子电器架构网络演化 —— 车载以太网TSN

电子电器架构网络演化 —— 车载以太网TSN 我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 屏蔽力是信息过载时代一个人的特殊竞争力&#xff0c;任何消…

VBA中类的解读及应用第八讲:实现定时器功能的自定义类事件

《VBA中类的解读及应用》教程【10165646】是我推出的第五套教程&#xff0c;目前已经是第一版修订了。这套教程定位于最高级&#xff0c;是学完初级&#xff0c;中级后的教程。 类&#xff0c;是非常抽象的&#xff0c;更具研究的价值。随着我们学习、应用VBA的深入&#xff0…

uniapp微信小程序投票系统实战 (SpringBoot2+vue3.2+element plus ) -用户信息修改实现

锋哥原创的uniapp微信小程序投票系统实战&#xff1a; uniapp微信小程序投票系统实战课程 (SpringBoot2vue3.2element plus ) ( 火爆连载更新中... )_哔哩哔哩_bilibiliuniapp微信小程序投票系统实战课程 (SpringBoot2vue3.2element plus ) ( 火爆连载更新中... )共计21条视频…

如何通过bat文件启动应用程序

说明&#xff1a;在windows上&#xff0c;任何应用程序都是通过.exe启动的。我们可以通过配置环境的方式&#xff0c;将应用程序的路径配置到环境变量path变量里&#xff0c;这样就可以使用cmd窗口&#xff0c;敲应用程序的名称来启动应用程序。 如下&#xff0c;可启动wps应用…

Vue-8、Vue事件处理

1、点击事件 <!DOCTYPE html> <html lang"en" xmlns:v-model"http://www.w3.org/1999/xhtml" xmlns:v-bind"http://www.w3.org/1999/xhtml"xmlns:v-on"http://www.w3.org/1999/xhtml"> <head><meta charset&quo…

Nginx location 配置 - Part 2

接上文 链接: Nginx 简介和入门 - part1 上文 我们简单地在 nginx 创建了3个虚拟主机&#xff0c; 虽然这个3个主机都是用占用80端口 但是我们可以用不同的域名来实现区分访问3台虚拟主机。 但是&#xff0c; 实际项目上&#xff0c; 我们更加多地会使用location 配置而不是…

Docker实战08|Docker管道及环境变量识别

上一篇文章中&#xff0c;讲解了如何通过Go语言实现对Docker Cgroup的资源限制 具体文章可见《Docker就应该这么学-07》 有需要的小伙伴可以回顾一下。 接下来本文会详细介绍一下Docker 管道及环境变量识别 管道及环境变量识别 获取代码 git clone https://gitee.com/mjr…

物理机部署三节点Kafka集群

一、部署Kafka集群 官方下载地址&#xff1a;http://kafka.apache.org/downloads.html上传安装包到102的/opt/software目录下 解压安装包到/opt/module/目录下&#xff0c;修改解压包名为kafka 修改config目录下的配置文件server.properties内容 #broker的全局唯一编号&#…