Spring学习 基础(二)Bean和AOP

news2024/12/23 18:08:45
3、Spring Bean

Bean 代指的就是那些被 IoC 容器所管理的对象,我们需要告诉 IoC 容器帮助我们管理哪些对象,这个是通过配置元数据来定义的。配置元数据可以是 XML 文件、注解或者 Java 配置类。

Bean的创建方式
1. XML 配置文件: 传统上,使用 XML 文件来定义和配置 beans。
2. 注解(Annotation-based configuration): 使用如 @Component, @Service, @Repository, @Controller 等注解来自动注册 bean。
3. Java 配置类(Java-based configuration): 使用 @Configuration 和 @Bean 注解来定义配置类和方法。
将一个类声明为 Bean 的注解有哪些?
  • @Component :通用的注解,可标注任意类为 Spring 组件。如果一个 Bean 不知道属于哪个层,可以使用@Component 注解标注。
  • @Repository : 对应持久层即 Dao 层,主要用于数据库相关操作。
  • @Service : 对应服务层,主要涉及一些复杂的逻辑,需要用到 Dao 层。
  • @Controller : 对应 Spring MVC 控制层,主要用户接受用户请求并调用 Service 层返回数据给前端页面。
@Component 和 @Bean 的区别是什么?
  • @Component 注解作用于类,而@Bean注解作用于方法。
  • @Component 通常是通过类路径扫描来自动侦测以及自动装配到 Spring 容器中,@Bean 注解通常是我们在标有该注解的方法中定义产生这个 bean,@Bean告诉了 Spring 这是某个类的实例,当我需要用它的时候还给我。
  • @Bean 注解比 @Component 注解的自定义性更强,而且很多地方我们只能通过 @Bean 注解来注册 bean。比如当我们引用第三方库中的类需要装配到 Spring容器时,则只能通过 @Bean来实现。
@Configuration
public class AppConfig {
    @Bean
    public TransferService transferService() {
        return new TransferServiceImpl();
    }

}
Bean 的作用域有哪些?

singleton 单例 : IoC 容器中只有唯一的 bean 实例。Spring 中的 bean 默认都是单例的,是对单例设计模式的应用。

prototype 原型: 每次获取都会创建一个新的 bean 实例。也就是说,连续 getBean() 两次,得到的是不同的 Bean 实例。

request 请求(仅 Web 应用可用): 每一次 HTTP 请求都会产生一个新的 bean(请求 bean),该 bean 仅在当前 HTTP request 内有效。

session 会话(仅 Web 应用可用) : 每一次来自新 session 的 HTTP 请求都会产生一个新的 bean(会话 bean),该 bean 仅在当前 HTTP session 内有效。

## 配置作用域
xml 方式:
<bean id="..." class="..." scope="singleton"></bean>
单例 Bean 的线程安全问题了解吗?

大部分时候我们并没有在项目中使用多线程,所以很少有人会关注这个问题。单例 Bean 存在线程问题,主要是因为当多个线程操作同一个对象的时候是存在资源竞争的。

常见的有两种解决办法:

  1. 在 Bean 中尽量避免定义可变的成员变量。
  2. 在类中定义一个 ThreadLocal 成员变量,将需要的可变成员变量保存在 ThreadLocal 中(推荐的一种方式)。

不过,大部分 Bean 实际都是无状态(没有实例变量)的(比如 Dao、Service),这种情况下, Bean 是线程安全的。

4、Spring AoP

AOP(Aspect-Oriented Programming:面向切面编程)能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。

  • AOP组成结构:

  • 切面(Aspect): 一个关注点的模块化,这个关注点可能会横切多个对象。切面可以包含通知和切点。

  • 连接点(Join Point): 程序执行的某个特定位置,如方法调用或异常抛出的地方。在 Spring AOP 中,一个连接点总是表示一个方法的执行。

  • 通知(Advice):

    切面在特定连接点上执行的动作。主要有以下类型:

    • 前置通知(Before advice):在某连接点之前执行(但不影响连接点的执行)。
    • 后置通知(After returning advice):在某连接点正常完成后执行。
    • 异常通知(After throwing advice):在方法抛出异常退出时执行。
    • 最终通知(After advice):无论连接点退出的方式如何都将执行的通知。
    • 环绕通知(Around advice):围绕一个连接点的通知,可以在方法调用前后自定义行为,甚至可以完全替换方法。
  • 切点(Pointcut): 匹配连接点的断言,在 AOP 语法中,通知与一个切点表达式关联,并在满足切点的连接点上运行。

  • 目标对象(Target Object): 被一个或多个切面所通知的对象。

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {

    // 定义切点:匹配com.example.service包下所有类的所有方法
    @Pointcut("execution(* com.example.service.*.*(..))")
    public void serviceLayer() {
    }

    // 前置通知:在目标方法执行前调用
    @Before("serviceLayer()")
    public void logBefore(JoinPoint joinPoint) {
        System.out.println("前置通知:即将执行方法: " + joinPoint.getSignature().getName());
    }

    // 后置通知:在目标方法正常执行后调用
    @AfterReturning(pointcut = "serviceLayer()", returning = "result")
    public void logAfterReturning(JoinPoint joinPoint, Object result) {
        System.out.println("后置通知:方法执行完成: " + joinPoint.getSignature().getName() + ", 返回值:" + result);
    }

    // 异常通知:在目标方法抛出异常后调用
    @AfterThrowing(pointcut = "serviceLayer()", throwing = "error")
    public void logAfterThrowing(JoinPoint joinPoint, Throwable error) {
        System.out.println("异常通知:方法执行异常: " + joinPoint.getSignature().getName() + ", 异常信息:" + error.getMessage());
    }

    // 最终通知:无论目标方法如何结束都会执行
    @After("serviceLayer()")
    public void logAfter(JoinPoint joinPoint) {
        System.out.println("最终通知:无论方法如何执行完毕都会调用");
    }

    // 环绕通知:可以在目标方法前后自定义行为,也可以阻止方法的执行
    @Around("serviceLayer()")
    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("环绕通知开始:方法名:" + joinPoint.getSignature().getName());
        try {
            Object result = joinPoint.proceed();
            System.out.println("环绕通知成功结束,结果是:" + result);
            return result;
        } catch (Throwable e) {
            System.out.println("环绕通知捕获到异常:" + e.getMessage());
            throw e; // 可以决定是否重新抛出异常
        } finally {
            System.out.println("环绕通知结束");
        }
    }
}

Spring AOP 就是基于动态代理的,如果要代理的对象,实现了某个接口,那么 Spring AOP 会使用 JDK Proxy,去创建代理对象,而对于没有实现接口的对象,, Spring AOP 会使用 Cglib 生成一个被代理对象的子类来作为代理

img

术语含义
目标(Target)被通知的对象
代理(Proxy)向目标对象应用通知之后创建的代理对象
连接点(JoinPoint)目标对象的所属类中,定义的所有方法均为连接点
切入点(Pointcut)被切面拦截 / 增强的连接点(切入点一定是连接点,连接点不一定是切入点)
通知(Advice)增强的逻辑 / 代码,也即拦截到目标对象的连接点之后要做的事情
切面(Aspect)切入点(Pointcut)+通知(Advice)
Spring AOP 和 AspectJ AOP 有什么区别?

Spring AOP 属于运行时增强,而 AspectJ 是编译时增强。 Spring AOP 基于代理(Proxying),而 AspectJ 基于字节码操作(Bytecode Manipulation)。如果我们的切面比较少,那么两者性能差异不大。但是,当切面太多的话,最好选择 AspectJ ,它比 Spring AOP 快很多。

AspectJ 定义的通知类型有哪些?
  • Before(前置通知):目标对象的方法调用之前触发
  • After (后置通知):目标对象的方法调用之后触发
  • AfterReturning(返回通知):目标对象的方法调用完成,在返回结果值之后触发
  • AfterThrowing(异常通知) :目标对象的方法运行中抛出 / 触发异常后触发。AfterReturning 和 AfterThrowing 两者互斥。如果方法调用成功无异常,则会有返回值;如果方法抛出了异常,则不会有返回值。
  • Around: (环绕通知)编程式控制目标对象的方法调用。环绕通知是所有通知类型中可操作范围最大的一种,因为它可以直接拿到目标对象,以及要执行的方法,所以环绕通知可以任意的在目标对象的方法调用前后搞事,甚至不调用目标对象的方法
多个切面的执行顺序如何控制?
// 通常使用@Order 注解直接定义切面顺序,值越小优先级越高
@Order(3)
@Component
@Aspect
public class LoggingAspect implements Ordered {

// 实现Ordered 接口重写 getOrder 方法
@Component
@Aspect
public class LoggingAspect implements Ordered {

    // ....

    @Override
    public int getOrder() {
        // 返回值越小优先级越高
        return 1;
    }
}

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

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

相关文章

Learn OpenGL 02 你好,三角形

图形渲染管线 图形渲染管线的每个阶段的抽象展示。要注意蓝色部分代表的是我们可以注入自定义的着色器的部分 首先&#xff0c;我们以数组的形式传递3个3D坐标作为图形渲染管线的输入&#xff0c;用来表示一个三角形&#xff0c;这个数组叫做顶点数据(Vertex Data)。 顶点着色…

最新2024年阿里云服务器地域和可用区全球分布表,不只是中国

2024年最新阿里云服务器地域分布表&#xff0c;地域指数据中心所在的地理区域&#xff0c;通常按照数据中心所在的城市划分&#xff0c;例如华北2&#xff08;北京&#xff09;地域表示数据中心所在的城市是北京。阿里云地域分为四部分即中国、亚太其他国家、欧洲与美洲和中东&…

superset连接Apache Spark SQL(hive)过程中的各种报错解决

superset连接数据库官方文档&#xff1a;Installing Database Drivers | Superset 我们用的是Apache Spark SQL&#xff0c;所以首先需要安装下pyhive #命令既下载了pyhive也下载了它所依赖的其他安装包 pip install pyhive#多个命令也可下载 pip install sasl pip install th…

设计模式-结构型模式-代理模式

代理模式&#xff08;Proxy&#xff09;&#xff0c;为其他对象提供一种代理以控制对这个对象的访问。[DP] // 定义接口 interface Subject {void request(); }// 真实主题对象 class RealSubject implements Subject {Overridepublic void request() {System.out.println(&quo…

App自动化测试笔记(十一):综合案例

短信案例 需求 在《短信》应用中&#xff0c;进入发送短信页面&#xff0c;在姓名和内容栏中&#xff0c;输入对应的数据&#xff0c;并点击发送。 包名界面名&#xff1a;com.android.mms/.ui.ConversationList 发送短信页面标识&#xff1a;resource-id&#xff0c;com.and…

乐得瑞 1C to 2C快充线:引领充电数据线新潮流,高效快充解决接口难题

随着科技的不断进步&#xff0c;数据线的接口种类也日渐繁多&#xff0c;但在早些时候&#xff0c;三合一和二合一的数据线因其独特的设计而备受欢迎。这类数据线通常采用USB-A口作为输入端&#xff0c;并集成了Micro USB、Lightning以及USB-C三种接口&#xff0c;满足了当时市…

【二】【算法分析与设计】编程练习

数字三角形 链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 来源&#xff1a;牛客网 时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 32768K&#xff0c;其他语言65536K 64bit IO Format: %lld 题目描述 KiKi学习了循环&#xff0c;BoBo…

2024年AI辅助研发趋势深度分析

随着人工智能&#xff08;AI&#xff09;技术的飞速发展&#xff0c;其在各个行业领域中的应用也日益广泛。特别是在研发领域&#xff0c;AI已经成为变革的先锋&#xff0c;极大地推动了科技进步的步伐。本文将从技术进展、行业应用案例、面临的挑战与机遇、未来趋势预测、法规…

JavaScript实现小球移动(二)

这次采用了封装函数的方法&#xff0c;将小球向左向右移动封装在同一个函数内。 代码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-wi…

接雨水(leetcode hot100)

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 示例 1&#xff1a; 输入&#xff1a;height [0,1,0,2,1,0,1,3,2,1,2,1] 输出&#xff1a;6 解释&#xff1a;上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] …

‘ jupyter ‘ 不是内部或外部命令,也不是可运行的程序或批处理文件。

安装anaconda后&#xff0c;在 Dos黑窗口 运行 jupyter notebook 的两个问题 原因&#xff1a;没配置环境变量 解决方法&#xff1a; 在 系统环境变量Path 中 添加两个地址 这里以anaconda安装在 D:\anaconda\install 下为例 &#xff08;根据个人安装具体位置而定&#xff…

Centos7.9安装glibc2.18后回滚到glibc2.17

对glibc的操作非常危险&#xff0c;如果您对Linux操作系统的操作仅限于查看别人的资料来解决问题的话&#xff0c;我还是比较真诚的劝退你了。只所以还是写下这篇博文&#xff0c;一是为了记录自己排错的过程&#xff0c;二是更正目前网络中一些不太正确的博文&#xff0c;防止…

史上最全AP/mAP通用代码实现(yolov5 txt版本)-下

提示&#xff1a;通用map指标框架代码介绍&#xff0c;直接使用yolov5数据格式&#xff0c;实现论文map指标计算代码解读 文章目录 前言该版本是直接使用yolo数据格式实现map计算&#xff0c;集成txt转json格式内容。 一、map模块整体认识二、map计算应用代码解读三、通用map计…

指针进阶(4)看一下这些与指针有关的题你都会做吗?

c语言中的小小白-CSDN博客c语言中的小小白关注算法,c,c语言,贪心算法,链表,mysql,动态规划,后端,线性回归,数据结构,排序算法领域.https://blog.csdn.net/bhbcdxb123?spm1001.2014.3001.5343 给大家分享一句我很喜欢我话&#xff1a; 知不足而奋进&#xff0c;望远山而前行&am…

JVM-垃圾收集器G1

G1垃圾回收器 概述&#xff1a; 是一款面向服务器的垃圾收集器,主要针对配备多个处理器及大容量内存的机器. 以极高效率满足GC停顿时间要求的同时,还具备高吞吐量性能特征.G1保留了年轻代和老年代的概念&#xff0c;但不再是物理隔阂了&#xff0c;它们都是&#xff08;可以不连…

供应链管理系统(SCM):得供应链得天下不是空话。

2023-08-26 15:51贝格前端工场 Hi&#xff0c;我是贝格前端工场&#xff0c;优化升级各类管理系统的界面和体验&#xff0c;是我们核心业务之一&#xff0c;欢迎老铁们评论点赞互动&#xff0c;有需求可以私信我们 一、供应链对于企业的重要性 供应链对企业经营的重要性不可…

在外包公司搞了2年,出来技术都没了...

先说情况&#xff0c;大专毕业&#xff0c;18年通过校招进入湖南某软件公司&#xff0c;干了接近6年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落&#xff01;而我已经在一个企业干了2年的的功能…

O2O:Sample Efficient Offline-to-Online Reinforcement Learning

IEEE TKDE 2024 paper Introduction O2O存在策略探索受限以及分布偏移问题&#xff0c;进而导致在线微调阶段样本效率低。文章提出OEMA算法首先使用离线数据训练乐观的探索策略&#xff0c;然后提出基于元学习的优化方法&#xff0c;减少分布偏移并提高O2O的适应过程。 Meth…

Java零基础 - 数组的定义和声明

哈喽&#xff0c;各位小伙伴们&#xff0c;你们好呀&#xff0c;我是喵手。 今天我要给大家分享一些自己日常学习到的一些知识点&#xff0c;并以文字的形式跟大家一起交流&#xff0c;互相学习&#xff0c;一个人虽可以走的更快&#xff0c;但一群人可以走的更远。 我是一名后…

React-Redux中actions

一、同步actions 1.概念 说明&#xff1a;在reducers的同步修改方法中添加action对象参数&#xff0c;在调用actionCreater的时候传递参数&#xff0c;数会被传递到action对象payload属性上。 2.reducers对象 说明&#xff1a;声明函数同时接受参数 const counterStorecre…