【Java】面向小白的Spring Framework注解开发学习笔记

目录

简介

IoC&DI

纯注解实现

定义 Bean

Bean 的作用范围和生命周期管理

依赖注入

管理第三方 Bean

为第三方 Bean 注入资源(例如数据库连接池)

AOP

纯注解实现

工作流程

切面示例

切入点表达式示例

通知类型示例

@Before(前置通知)

@After(后置通知)

@AfterReturning(返回通知)

@AfterThrowing(异常通知)

@Around(环绕通知)


简介

Spring Framework 是一个开源的 Java 企业级应用程序开发框架,它提供了一系列的库和工具,帮助开发人员构建高效、可维护、易扩展的企业级应用程序。Spring 框架是由 Rod Johnson 和 Juergen Hoeller 等人创建的,第一个版本发布于2002年。

Spring Framework 的核心是 IoC(Inversion of Control)容器和 AOP(Aspect Oriented Programming)框架。IoC 容器用于管理 Java 对象(即 Bean),通过依赖注入的方式实现对象之间的解耦。AOP 框架提供了对切面编程的支持,允许开发人员在不修改核心代码的情况下,通过切面技术实现横切关注点的功能,例如事务管理、安全检查等。

IoC&DI

IoC(Inversion of Control,控制反转)和 DI(Dependency Injection,依赖注入)是 Spring Framework 的核心概念之一,它们是通过解耦来提高代码的可维护性和可扩展性。

IoC 意味着对于一个对象的创建和管理不再由该对象自己来决定,而是由外部容器来控制。换句话说,控制权被反转了。在 Spring 中,IoC 通常指的是 Spring IoC 容器,它管理了应用程序中的 Java 对象,并负责调用它们的生命周期方法。

DI 是 IoC 的一种实现方式,它是指将依赖关系从代码中移除,通过容器来注入所需的依赖项。依赖项可以是其他对象、配置属性或者资源等。Spring 中的 DI 通常是通过构造函数注入、Setter 方法注入或者字段注入来实现的。

举例:

// 定义数据访问接口 UserDao,使用 @Repository 注解标记为持久化层组件
@Repository
public interface UserDao {void saveUser(User user);
}// 实现 UserDao 接口,使用 @Repository 注解标记为持久化层组件
@Repository
public class UserDaoImpl implements UserDao {@Overridepublic void saveUser(User user) {// 实现具体的数据库保存逻辑System.out.println("Save user: " + user.getName());}
}// 定义服务类 UserService,使用 @Service 注解标记为业务层组件
@Service
public class UserService {// 使用 @Autowired 注解自动装配 UserDao 对象@Autowiredprivate UserDao userDao;public void saveUser(User user) {userDao.saveUser(user);}
}// 创建 Spring 配置类 AppConfig,用于配置 IoC 容器和依赖注入
@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {// 无需手动定义 bean,因为使用了 @ComponentScan 注解自动扫描并注册组件
}// 编写测试代码,验证 IoC 和 DI 的效果
public class Main {public static void main(String[] args) {// 创建 Spring IoC 容器,并加载 AppConfig 配置类AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);// 从容器中获取 UserService beanUserService userService = context.getBean(UserService.class);// 创建一个 User 对象User user = new User("John Doe");// 调用 UserService 的方法保存用户userService.saveUser(user);}
}

纯注解实现

定义 Bean

@Component // 使用 @Component 注解将该类标记为 Spring 管理的组件
public class UserService {// 类的具体实现...
}

Bean 的作用范围和生命周期管理

@Component // 默认为单例作用域,相当于 @Scope("singleton")
public class MySingletonBean {// 类的具体实现...
}@Component
@Scope("prototype") // 指定为原型(多例)作用域
public class MyPrototypeBean {// 类的具体实现...
}@Component
public class MyBeanLifecycle implements InitializingBean, DisposableBean {// 在初始化之前执行的方法@PostConstructpublic void init() {// 初始化操作...}// 在销毁之前执行的方法@PreDestroypublic void destroy() {// 销毁操作...}// 实现 InitializingBean 接口的方法@Overridepublic void afterPropertiesSet() throws Exception {// 初始化操作...}// 实现 DisposableBean 接口的方法@Overridepublic void destroy() throws Exception {// 销毁操作...}
}

依赖注入

@Component
public class UserService {@Autowired // 自动装配依赖对象private UserRepository userRepository;// 类的具体实现...
}

管理第三方 Bean

@Configuration
public class MyConfig {@Bean // 将第三方类库的对象声明为一个 Spring 管理的 beanpublic ThirdPartyService thirdPartyService() {return new ThirdPartyService();}
}@Component
public class MyComponent {@Autowiredprivate ThirdPartyService thirdPartyService;// 类的具体实现...
}

为第三方 Bean 注入资源(例如数据库连接池)

@Configuration
public class DataSourceConfig {@Beanpublic DataSource dataSource() {// 创建和配置数据源对象...}@Beanpublic JdbcTemplate jdbcTemplate(DataSource dataSource) {// 使用第三方 bean,并注入资源return new JdbcTemplate(dataSource);}
}

AOP

Spring 的 AOP(面向切面编程)是一种基于代理机制的编程方式,它可以在不改变原有代码逻辑的情况下,通过动态地将额外的行为织入到程序中。这些额外的行为通常包括日志记录、性能监控、事务管理等与业务功能无关的横切关注点。

在 Spring 中,AOP 可以通过配置或注解来实现。其核心是定义切面(Aspect),切面定义了哪些方法需要被拦截,以及拦截后要执行什么逻辑。而切面具体实现的逻辑则由通知(Advice)来完成。通知可以在目标方法执行前、执行后或者抛出异常时执行,通常采用环绕、前置、后置和异常拦截四种类型。

举例:

@Aspect // 声明该类为切面
@Component
public class LogAspect {@Pointcut("execution(* com.example.service.*.*(..))")private void serviceMethod() {} // 定义切点,匹配 com.example.service 包下的所有方法@Before("serviceMethod()")public void logBefore(JoinPoint joinPoint) {String methodName = joinPoint.getSignature().getName();System.out.println("[LogAspect] Before method: " + methodName);}@AfterReturning("serviceMethod()")public void logAfterReturning(JoinPoint joinPoint) {String methodName = joinPoint.getSignature().getName();System.out.println("[LogAspect] AfterReturning method: " + methodName);}
}

纯注解实现

工作流程

1. 定义切面(Aspect):通过使用 @Aspect 注解声明一个类为切面,并在该类中定义切入点和通知。
2. 定义切入点(Pointcut):使用 @Pointcut 注解定义一个切入点表达式,指定哪些方法需要被拦截。
3. 定义通知(Advice):使用 @Before、@After、@AfterReturning、@AfterThrowing 或       @Around 注解定义通知类型,并编写相应的逻辑。
4. 将切面和目标对象进行织入:Spring 容器会自动检测并织入切面到匹配的目标对象中。
5.执行增强逻辑:在目标方法执行前、执行后或抛出异常时,触发相应的通知进行增强处理

切面示例

@Aspect
@Component
public class LoggingAspect {@Pointcut("execution(* com.example.service.*.*(..))")private void serviceMethod() {}@Before("serviceMethod()")public void beforeAdvice(JoinPoint joinPoint) {System.out.println("Before executing method: " + joinPoint.getSignature().getName());}@After("serviceMethod()")public void afterAdvice(JoinPoint joinPoint) {System.out.println("After executing method: " + joinPoint.getSignature().getName());}
}

切入点表达式示例

@Pointcut("execution(* com.example.service.UserService.*(..))")
private void userServiceMethods() {}@Pointcut("within(com.example.repository.*)")
private void repositoryMethods() {}

通知类型示例

@Before(前置通知)

@Before("execution(* com.example.service.UserService.createUser(String, int))")
public void beforeCreateUserAdvice(JoinPoint joinPoint) {Object[] args = joinPoint.getArgs();System.out.println("Before creating user... Name: " + args[0] + ", Age: " + args[1]);
}

功能:在执行 com.example.service.UserService.createUser() 方法之前触发该通知,可以用于进行一些预处理操作,例如权限检查、参数校验等。

@After(后置通知)

@After("execution(* com.example.service.UserService.deleteUser(..))")
public void afterDeleteUserAdvice() {System.out.println("After deleting user...");
}

功能:在执行 com.example.service.UserService.deleteUser() 方法之后触发该通知,无论方法是否抛出异常都会执行。可以用于进行一些清理操作,例如资源释放、日志记录等。

@AfterReturning(返回通知)

@AfterReturning(pointcut = "execution(* com.example.service.UserService.updateUser(..))", returning = "result")
public void afterUpdateUserAdvice( Object result) {System.out.println("After updating user... Result: " + result);
}

功能:在执行 com.example.service.UserService.updateUser() 方法并且方法正常返回后触发该通知。可以用于获取方法的返回值并进行相应的处理,例如记录返回结果、统计信息等。

@AfterThrowing(异常通知)

@AfterThrowing(pointcut = "execution(* com.example.service.UserService.getUser(..))", throwing = "ex")
public void afterThrowingGetUserAdvice(Exception ex) {System.out.println("After throwing exception in getUser() method: " + ex.getMessage());
}

功能:在执行 com.example.service.UserService.getUser() 方法抛出异常时触发该通知。可以用于捕获方法抛出的异常并进行相应的处理,例如记录异常信息、进行异常处理等。

@Around(环绕通知)

@Around("execution(* com.example.service.UserService.getAllUsers())")
public Object aroundGetAllUsersAdvice(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println("Before executing getAllUsers() method...");Object result = null;try {result = joinPoint.proceed();} catch (Exception ex) {System.out.println("Exception occurred: " + ex.getMessage());}System.out.println("After executing getAllUsers() method... Result: " + result);return result;
}

功能:在执行 com.example.service.UserService.getAllUsers() 方法前后都触发该通知,并且可以控制目标方法的执行。可以用于在方法执行前后进行一些额外的处理,例如性能监控、事务管理等。

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

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

相关文章

谷粒商城【成神路】-【3】——三级分类

目录 🍿1.查询三级分类 🧂2.前端页面搭建 🍟3.添加网关 🍳4.解决跨域 🧇5.显示分类 🥞6.显示复选框 1.查询三级分类 1.controller 直接调用service层的接口 RequestMapping("/list/tree&qu…

营养之源:新生儿补充烟酸的关键知识

引言: 烟酸,作为维生素B族的一员,对新生儿的生长发育和健康至关重要。它在细胞的新陈代谢、能量的产生等方面发挥着重要作用。本文将深入探讨烟酸的作用、新生儿补充的必要性,以及在补充烟酸时应该注意的事项,为父母提…

力扣热门100题刷题笔记 - 3.无重复字符的最长子串

力扣热门100题 - 3.无重复字符的最长子串 题目链接:3. 无重复字符的最长子串 题目描述: 给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。示例: 输入: s "abcabcbb" 输出: 3 解释: 因为无重复字…

ROS2 Humble学习笔记 (2)

本文发表于个人的github pages。因csdn本身显示插件和转载过程中导致显示不太友好。建议大家阅读原文。想查看完整内容,请移步到ROS2 Humble学习笔记2。 本文篇幅较长,可抽空按照章节阅读。本文只作为对入门教程的一种浮现和提升。 一、前言 在上一篇…

速盾:服务器接入免备案CDN节点的好处有哪些

本文将探讨服务器接入免备案CDN节点的好处,包括提高网站的访问速度、增加网站的稳定性和可靠性、降低带宽成本等方面的优势。同时,还将提供一些相关问题的解答,帮助读者更好地了解这一技术。 随着互联网的迅猛发展,网站的访问速度…

LC 365. 水壶问题

365. 水壶问题 难度: 中等 题目大意: 有两个水壶,容量分别为 jug1Capacity 和 jug2Capacity 升。水的供应是无限的。确定是否有可能使用这两个壶准确得到 targetCapacity 升。 如果可以得到 targetCapacity 升水,最后请用以上水壶中的一或…

中国传媒网CEO:媒体融合发展业态新媒体年后在沪召开

近日,在“坚守媒体初心,拥抱AI时代”2023外滩新媒体年会上,有多项合作达成。 在当前竞争激烈的市场环境中,媒体宣传已经成为企业品牌推广不可或缺的一环。对于很多企业来说往往会犯一个错误,就是默默地参加了展会,并没有进行媒体营销。展会是一种非常有力的宣传和推广方式,可以…

LabVIEW汽车自燃监测预警系统

LabVIEW汽车自燃监测预警系统 随着汽车行业的飞速发展,汽车安全问题日益受到公众的关注。其中,汽车自燃现象因其突发性和破坏性,成为一个不可忽视的安全隐患。为了有效预防和减少自燃事故的发生,提出了LabVIEW的汽车自燃监测预警…

android 网络拦截器统一处理请求参数和返回值加解密实现

前言 项目中遇到参数加密和返回结果加密的业务 这里写一下实现 一来加深记忆 二来为以后参考铺垫 需求 项目在开发中涉及到 登陆 发验证码 认证 等前期准备接口 这些接口需要单独处理 比如不加密 或者有其他的业务需求 剩下的是登陆成功以后的业务需求接口 针对入参和返回值…

mysql 中sql 语句查询今天、昨天、近7天、近30天、一个月内、上一月数据

1、几个小时内的数据 DATE_SUB(NOW(), INTERVAL 5 HOUR) 2、今天 select * from 表名 where to_days(时间字段名) to_days(now()); 3、昨天 select * from 表名 WHERE TO_DAYS( NOW( ) ) - TO_DAYS( 时间字段名) < 1; 4、7天 select * from 表名 where DATE_SUB(CUR…

Iceberg从入门到精通系列之二十三:Spark查询

Iceberg从入门到精通系列之二十三&#xff1a;Spark查询 一、使用 SQL 查询二、使用 DataFrame 进行查询三、Time travel四.Incremental read五、检查表六、History七、元数据日志条目八、Snapshots九、Files十、Manifests十一、Partitions十二、所有元数据表十三、参考十四、使…

【SpringBoot】application配置文件(4)

freemarker:cache: false 这是关于 freemarker 模板引擎的一个配置&#xff0c;用于控制模板的缓存行为 当cache 设置为 false 时&#xff0c;意味着每次请求时都会重新加载和编译模板&#xff0c;而不是从缓存中获取 编译模板。 将 cache 设置为 false 是为了在开发过程中获…

Java 基于 SpringBoot+Vue 的考研论坛管理系统

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

三.Linux权限管控 1-5.Linux的root用户用户和用户组查看权限控制信息chmod命令chown命令

目录 三.Linux权限管控 1.Linux的root用户 root用户&#xff08;超级管理员&#xff09; su和exit命令 sudo命令 为普通用户配置sudo认证 三.Linux权限管控 2.用户和用户组 用户&#xff0c;用户组 用户组管理 用户管理 getent---查看系统中的用户 三.Linux权限管控…

地理坐标系、空间坐标系、epsg查询网站

坐标系可用范围和详细信息的查询网站 简介 epsg.ruiduobao.com是一个可以查询gdal中所有坐标系信息的网站&#xff0c;可查询到坐标系的基准面、椭球体、中央子午线等相关信息&#xff0c;并对每个坐标系的可用范围在地图中进行了显示。详细信息可以看操作视频&#xff1a; e…

MySQL知识点总结(四)——MVCC

MySQL知识点总结&#xff08;四&#xff09;——MVCC 三个隐式字段row_idtrx_idroll_pointer undo logread viewMVCC与隔离级别的关系快照读和当前读 MVCC全称是Multi Version Concurrency Control&#xff0c;也就是多版本并发控制。它的作用是提高事务的并发度&#xff0c;通…

03 计算机的组成

CPU是计算机的核心部件&#xff0c;它控制整个计算机的运作并进行计算&#xff0c;要想让CPU工作&#xff0c;就必须向他提供指令和数据 指令和数据的表示 计算机中的数据和指令&#xff0c;存储在内存或磁盘上。 数据和指令&#xff0c;都是二进制信息。 计算机中的存储单…

虹科技术丨一文详解IO-Link Wireless技术如何影响工业无线自动化

来源&#xff1a;虹科工业智能互联 虹科技术丨一文详解IO-Link Wireless技术如何影响工业无线自动化 原文链接&#xff1a;https://mp.weixin.qq.com/s/qVIkdeI5zzzagPd0UEkfDg 欢迎关注虹科&#xff0c;为您提供最新资讯&#xff01; #工业自动化 #IO-Link Wireless #工业无…

【ES6】一个页面上需要等两个或多个ajax的数据请求成功以后才正常显示(使用Promise.all和Promise.race)

【ES6】一个页面上需要等两个或多个ajax的数据请求成功以后才正常显示&#xff08;使用Promise.all和Promise.race&#xff09; PomisePomise.allPromise.race Pomise Pomise.all Promise.all将多个Promise实例聚合成一个新的Promise实例。请求成功的时候返回的是一个结果数组…

C语言指针学习 之 指针变量

前言&#xff1a; 通过学习我们认识了什么是指针&#xff0c;就让我们一起来分析一个例子。 #include<stdio.h> int main() {int a100;int * hz; hz &a;printf("a%d \n",a);printf("*hz%d \n",*hz);return 0; }a100 *hz100 PS C:\csay\cyuya…