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

在这里插入图片描述

在编程的世界里,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;@Autowiredpublic 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 {@Autowiredprivate UserService userService;@GetMapping("/{id}")public ResponseEntity<User> getUserById(@PathVariable Long id) {User user = userService.getUserById(id);return ResponseEntity.ok(user);}@PostMappingpublic ResponseEntity<User> createUser(@RequestBody User user) {userService.createUser(user);return ResponseEntity.status(HttpStatus.CREATED).body(user);}
}@Service
public class UserService {@Autowiredprivate 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 {@LogExecutionTimepublic 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.mzph.cn/news/606942.shtml

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

相关文章

【读书笔记】《白帽子讲web安全》跨站脚本攻击

目录 前言&#xff1a; 第二篇 客户端脚本安全 第3章 跨站脚本攻击&#xff08;XSS&#xff09; 3.1XSS简介 3.2XSS攻击进阶 3.2.1初探XSS Payload 3.2.2强大的XSS Payload 3.2.2.1 构造GET与POST请求 3.2.2.2XSS钓鱼 3.2.2.3识别用户浏览器 3.2.2.4识别用户安装的软…

Qt 使用WINDOWS API读取SMBIOS信息,并通过CMD命令打印相关信息,参考DumpSMBIOS项目

在获取PE系统中的CPU、主板、内存信息时&#xff0c;发现使用WMI部分信息无法获取&#xff0c;通过gitGub上的DumpSMBIOS完全解决了这个问题&#xff0c;并单独做成了个案例&#xff0c;以下示例和代码都是参考DumpSMBIOS项目 SMBIOS这个数据还是用到的比较少。但是DumpSMBIOS项…

01.初识Python

初识Python Python简介 Python的历史 1989年圣诞节&#xff1a;Guido von Rossum开始写Python语言的编译器。1991年2月&#xff1a;第一个Python编译器&#xff08;同时也是解释器&#xff09;诞生&#xff0c;它是用C语言实现的&#xff08;后面&#xff09;&#xff0c;可…

【科技素养题】少儿编程 蓝桥杯青少组科技素养题真题及解析第22套

少儿编程 蓝桥杯青少组科技素养题真题及解析第22套 1、植物的叶子多为绿色,这主要是因为它们含有 A、绿色色素 B、叶绿素 C、花青素 D、细胞 答案:B 考点分析:主要考查小朋友们生物知识的储备;叶绿素是植物叶子中的一种色素,它可以吸收太阳光中的能量并转化为植物所…

原子操作类原理剖析

UC包提供了一系列的原子性操作类&#xff0c;这些类都是使用非阻塞算法CAS实现的&#xff0c;相比使用锁实现原子性操作这在性能上有很大提高。 由于原子性操作类的原理都大致相同&#xff0c;所以只讲解最简单的AtomicLong类的实现原理以及JDK8中新增的LongAdder和LongAccumu…

理论U3 决策树

文章目录 一、决策树算法1、基本思想2、构成1&#xff09;节点3&#xff09;有向边/分支 3、分类步骤1&#xff09;第1步-决策树生成/学习、训练2&#xff09;第2步-分类/测试 4、算法关键 二、信息论基础1、概念2、信息量3、信息熵&#xff1a; 二、ID3 (Iterative Dichotomis…

[论文阅读]4DRadarSLAM: A 4D Imaging Radar SLAM System for Large-scale Environments

目录 1.摘要和引言&#xff1a; 2. 系统框架&#xff1a; 2.1 前端&#xff1a; 2.2 回环检测&#xff1a; 2.3 后端&#xff1a; 3.实验和分析&#xff1a; 4.结论 1.摘要和引言&#xff1a; 这篇论文介绍了一种名为“4DRadarSLAM”的新型4D成像雷达SLAM系统&#xff0…

若依CRUD搬砖开始,Java小白入门(十)

背景 经过囫囵吞枣的学习若依框架&#xff0c;对于ruoyi-framework&#xff0c;common&#xff0c;安全&#xff0c;代码生成等模块都看了一圈&#xff0c;剩余的调度模块&#xff0c;这个暂时不深入&#xff0c;剩余的是ruoyi-system&#xff0c;就是用mybatis完成的&#xf…

063:vue中一维数组与三维数组联动,类似购物车增减

第063个 查看专栏目录: VUE ------ element UI 专栏目标 在vue和element UI联合技术栈的操控下,本专栏提供行之有效的源代码示例和信息点介绍,做到灵活运用。 (1)提供vue2的一些基本操作:安装、引用,模板使用,computed,watch,生命周期(beforeCreate,created,beforeM…

服务发现Discovery

对于注册进eureka里面的微服务&#xff0c;可以通过服务发现来获得该服务的信息 1、 修改cloud-provider-payment8001的controller import com.my.springcloud.utils.RestResponse; import com.my.springcloud.entities.Payment; import com.my.springcloud.service.PaymentSe…

K8S API访问控制之RBAC利用

前言 K8S对于API的访问安全提供了访问控制&#xff0c;主要为4个阶段&#xff0c;本文为第二个阶段——鉴权的RBAC。RBAC是基于角色的访问控制&#xff0c;使用kubeadm安装集群1.6版本以上的都默认开启了RBAC。本文主要研究集群可能存在的利用点及相对应的利用手法。 API访问…

【JAVA】final、finally、finalize 有什么区别?

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a; JAVA ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 final&#xff1a; finally&#xff1a; finalize&#xff1a; 结语 我的其他博客 前言 在Java中&#xff0c;final、f…

使用flet创建todo应用

使用 Flet 在 Python 中创建待办事项应用 Create To-Do app in Python with Flet 翻译官网教程https://flet.dev/docs/tutorials/python-todo&#xff0c;对一些地方进行了注释和修改。 安装flet Python版本需要3.8及以上&#xff0c;使用pip安装&#xff1a; pip install…

test fuzz-01-模糊测试(Fuzz Testing)入门 Atheris、Jazzer、jqf、kelinci、FLA、libfuzzer 对比

拓展阅读 开源 Auto generate mock data for java test.(便于 Java 测试自动生成对象信息) 开源 Junit performance rely on junit5 and jdk8.(java 性能测试框架。性能测试。压测。测试报告生成。) test fuzz-01-模糊测试&#xff08;Fuzz Testing&#xff09; test fuzz-…

代码随想录算法训练营day6|242.有效的字母异位词、349.两个数组的交集、202.快乐数

哈希表理论基础 建议&#xff1a;大家要了解哈希表的内部实现原理&#xff0c;哈希函数&#xff0c;哈希碰撞&#xff0c;以及常见哈希表的区别&#xff0c;数组&#xff0c;set 和map。 什么时候想到用哈希法&#xff0c;当我们遇到了要快速判断一个元素是否出现集合里的时…

Unity Urp 渲染管线 创建透明材质球

按照以上方式设置后就可以得到一个透明的材质球 Tips&#xff1a;Blending mode &#xff1a; alpha 和 Blending mode &#xff1a; additive都是完全透明效果具体差异暂时不知道

模型创建与nn.Module

一、网络模型创建步骤 二、nn.Module 下面描述了在 PyTorch 中常见的一些属性和功能&#xff0c;用于存储和管理神经网络模型的参数、模块、缓冲属性和钩子函数。 parameters&#xff1a;用于存储和管理 nn.Parameter 类的属性。nn.Parameter 是一种特殊的张量&#xff0c;它被…

在做题中学习(44):无重复字符的最长字串

3. 无重复字符的最长子串 - 力扣&#xff08;LeetCode&#xff09; 解法&#xff1a;同向双指针————“滑动窗口” 思路&#xff1a;如下图&#xff0c;当right进窗口后&#xff0c;就出现了a重复&#xff0c;所以在left出窗口时时&#xff0c;需要跳到第一个a 后面的位置&…

【QML COOK】- 004-添加动画

1. 编辑main.qml import QtQuickWindow {width: 800height: 800visible: truetitle: qsTr("Hello World")Image {id: backgroudanchors.fill: parentsource: "qrc:/Resources/Images/arrow.png"Behavior on rotation {NumberAnimation {duration: 1000}}}…

Master01节点免密钥登录其他节点

1、执行命令 ssh-keygen -t rsa&#xff0c;一直敲回车 2、for i in k8s-master01 k8s-node01 k8s-node02;do ssh-copy-id -i .ssh/id_rsa.pub $i;done 输入yes和对应节点密码