深入理解Spring框架中的AOP、IoC和DI

news/2024/12/2 9:51:30/

目录

AOP(面向切面编程)

核心概念:

AOP示例:

IoC(控制反转)

核心概念:

IoC示例:

DI(依赖注入)

前置:

构造函数注入:

属性注入:

方法注入(Setter方法注入):

总结


Spring框架是一个功能强大且广泛使用的Java应用程序开发框架,它引入了多种关键概念和技术,其中包括AOP(面向切面编程)、IoC(控制反转)和DI(依赖注入)。本文将深入介绍这些概念,希望帮助大家更好地理解Spring框架的核心原理和用途~~😁

AOP(面向切面编程)

AOP是一种编程范式,它允许我们将应用程序的不同关注点分离开来,例如日志记录、事务管理、安全性等。

核心概念:

在Spring中,AOP通过代理机制实现,主要使用以下几个关键概念:

切面(Aspect): 切面是一种模块化的方式来处理横切关注点(cross-cutting concerns),例如日志记录或性能监控。

连接点(Join Point): 连接点是在应用程序执行过程中可以被拦截的点,例如方法调用或异常抛出。

通知(Advice): 通知是在连接点上执行的操作,包括前置通知(在方法执行之前执行)、后置通知(在方法执行之后执行)、异常通知(在方法抛出异常时执行)和环绕通知(在方法执行前后都执行)等。

切点(Pointcut): 切点是一组连接点的集合,它定义了在何处应用通知。

Spring的AOP功能允许我们通过配置将通知与切点关联起来,从而实现横切关注点的模块化管理。


AOP示例:

假设我们有一个简单的Java类 Calculator,它包含两个方法:addsubtract

public class Calculator {public int add(int a, int b) {return a + b;}public int subtract(int a, int b) {return a - b;}
}

现在,我们想要在执行这两个方法之前和之后记录日志,但我们不想修改 Calculator 类的源代码。这就是AOP的用武之地🤩

首先,我们创建一个切面类,该类包含了我们的日志记录逻辑:

public class LoggingAspect {public void logBefore() {System.out.println("Before method execution: Logging started.");}public void logAfter() {System.out.println("After method execution: Logging finished.");}
}

接下来,我们配置AOP,告诉Spring在执行 Calculator 类的方法之前和之后应用我们的切面。这可以通过XML配置或Java注解来完成。以下是使用XML配置的示例:

<aop:config><aop:aspect id="loggingAspect" ref="loggingAspectBean"><aop:before method="logBefore" pointcut="execution(* Calculator.*(..))" /><aop:after method="logAfter" pointcut="execution(* Calculator.*(..))" /></aop:aspect>
</aop:config>

在这里,我们创建了一个切面 loggingAspect,并指定了 logBeforelogAfter 方法分别在 Calculator 类的所有方法执行之前和之后执行。pointcut 属性定义了切入点,指定了应该应用切面的方法。

最后,我们需要在Spring容器中配置 CalculatorLoggingAspect 的bean。然后,当我们调用 Calculator 的方法时,AOP会自动应用日志记录切面,而不需要在 Calculator 类中编写任何日志记录代码。

Calculator calculator = (Calculator) context.getBean("calculator");
int result = calculator.add(5, 3);

输出结果:

Before method execution: Logging started.
After method execution: Logging finished.

这个简单的例子展示了AOP的概念:通过切面和切入点,我们可以将横切关注点(如日志记录)从应用程序的核心业务逻辑中分离出来,从而实现了模块化和松耦合的代码。这使得我们可以更轻松地维护和扩展应用程序。

IoC(控制反转)

IoC是Spring框架的核心原则之一,它是一种设计模式,也称为依赖反转。在传统的开发中,对象通常负责管理其依赖关系,而在IoC中,控制权反转,由容器负责管理对象的生命周期和依赖关系。

核心概念:

容器(Container): Spring的IoC容器是一个负责创建、管理和组装应用程序组件的容器。最常见的容器是BeanFactory和ApplicationContext。

Bean(组件): Bean是Spring管理的应用程序对象。这些对象通过容器的配置来创建和管理,通常被称为IoC容器中的组件。

配置元数据(Configuration Metadata): 配置元数据是指告诉容器如何创建和组装Bean的信息,通常使用XML配置、注解或Java配置方式提供。

依赖注入(DI): DI是IoC的一种具体实现,它指的是容器将依赖关系注入到Bean中,而不是Bean自己负责管理它们的依赖。这可以通过构造函数注入、属性注入或方法注入来实现。


IoC示例:

假设我们有一个简单的Java类 MessageService,它用于发送消息:

public class MessageService {public void sendMessage(String message) {System.out.println("Sending message: " + message);}
}

现在,我们想要在另一个类中使用 MessageService 来发送消息,但我们不想直接在这个类中创建 MessageService 的实例,而是希望通过Spring容器来管理 MessageService

首先,我们需要配置Spring容器。在XML配置文件中,我们可以定义 MessageService 的bean:

<beans xmlns="http://www.springframework.org/schema/beans"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"><bean id="messageService" class="com.example.MessageService" />
</beans>

在这里,我们定义了一个名为 messageService 的bean,它的类是 com.example.MessageService

接下来,我们可以创建一个类,让Spring容器注入 MessageService 的实例。这可以通过在类中声明一个属性并使用 @Autowired 注解来实现:

import org.springframework.beans.factory.annotation.Autowired;public class MyApplication {private MessageService messageService;@Autowiredpublic MyApplication(MessageService messageService) {this.messageService = messageService;}public void sendMessage(String message) {messageService.sendMessage(message);}
}

在这里,我们在 MyApplication 类的构造函数中接受了一个 MessageService 的参数,并使用 @Autowired 注解将它注入到属性中。

最后,我们可以使用Spring容器来创建 MyApplication 的实例并调用 sendMessage 方法:

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class Main {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");MyApplication app = context.getBean(MyApplication.class);app.sendMessage("Hello, Spring!");}
}

在这个IoC示例中,我们通过Spring容器配置了 MessageService 的bean,然后让Spring容器自动将它注入到 MyApplication 类中。这样,我们实现了控制反转,将对象的创建和依赖管理交给了Spring框架,使我们的代码更加松耦合、可维护和可测试~~😎

DI(依赖注入)

DI是IoC的一种具体实现,它是指容器负责将组件的依赖关系注入到组件中,而不是由组件自己创建或查找依赖。DI可以通过以下三种方式实现:

前置:

首先我们准备一个StudentService类

@Service
public class StudentService {public void sayHi(){System.out.println("do student service sayHi()");}
}

我们还得准备一个启动类:

public class App {public static void main(String[] args) {//1,获取Spring上下文ApplicationContext applicationContext =new ClassPathXmlApplicationContext("spring-config.xml");//2,得到Bean对象MyService myService=applicationContext.getBean("StudentService",StudentService.class);//3,使用Bean对象myService.sayHi();}}

 

构造函数注入:

通过Bean的构造函数来注入依赖。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class MyService {private final StudentService studentService;@Autowiredpublic MyService(StudentService studentService) {this.studentService = studentService;}
}

属性注入:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class MyService {@Autowiredprivate StudentService studentService;
}

方法注入(Setter方法注入):

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class MyService {private StudentService studentService;@Autowiredpublic void setStudentService(StudentService studentService) {this.studentService = studentService;}
}

然后我们使用其中一种注入之后,我们启动启动类,就会显示如下运行结果:

do student service sayHi()

总结

Spring框架的AOP(面向切面编程)允许有效地处理横切关注点,如日志和事务,提高了代码的模块化性。IoC(控制反转)将对象创建和依赖关系管理交给Spring容器,提高了代码的可扩展性和可维护性。DI(依赖注入)则是IoC的实现方式之一,使依赖关系通过构造函数、属性或方法注入,降低了组件之间的耦合度。这些核心概念共同构成了Spring框架的基础,为构建灵活、可维护的应用程序提供了强大的工具。🤗


http://www.ppmy.cn/news/1082181.html

相关文章

【ROS 04】ROS运行管理

ROS是多进程(节点)的分布式框架&#xff0c;一个完整的ROS系统实现&#xff1a; 可能包含多台主机&#xff1b; 每台主机上又有多个工作空间(workspace)&#xff1b; 每个的工作空间中又包含多个功能包(package)&#xff1b; 每个功能包又包含多个节点(Node)&#xff0c;不同的…

【C++】一文解析std::binary_function、std::bind1st、std::bind2nd、std::bind

STL中有一个叫做“适配器”的概念&#xff0c;它指的是某些函数可能定义了两个形参&#xff0c;但是某些算法需要的函数却有时候需要一个形参&#xff0c;那么就需要对其进行适配&#xff0c;将原本只需要两个参数的函数转变成需要1和参数就能正常运行的函数。就像你为你的笔记…

海格里斯HEGERLS高密度料箱式四向穿梭车存储系统有哪些显著优势?

近些年仓储货架向着自动化、智能化发展&#xff0c;因此市面上出现很多不同类型的智能自动化仓储货架。其中&#xff0c;最受企业青睐的便是四向穿梭车货架。四向穿梭车货架根据其载重不同可分为托盘式和料箱式两大类。这两种不同类型的四向穿梭车货架在结构形式和控制方式上基…

一文1800字从0到1使用Python Flask实战构建Web应用

Python Flask是一个轻量级的Web框架&#xff0c;它简单易用、灵活性高&#xff0c;适用于构建各种规模的Web应用。本文将介绍如何使用Python Flask框架来实战构建一个简单的Web应用&#xff0c;并展示其基本功能和特性。 第一部分&#xff1a;搭建开发环境 在开始之前我们需要…

Python入门教程 - 循环语句 (三)

目录 一、while循环 二、for循环 三、range函数 四、for循环变量的作用域 五、continue 和 break 一、while循环 i 1 while i < 100:print("循环执行中")print("当前循环第 %s 次" % i)i 1 print("循环执行完成") 循环执行中 当前循…

安防监控/视频存储/视频汇聚平台EasyCVR接入海康Ehome车载设备出现收流超时的原因排查

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。视频汇聚平台既具…

vxe table虚拟滚动

需求背景: 表格涉及手工录入&#xff0c;当数据量超过30条时&#xff0c;编辑会有明显卡顿&#xff0c;数据量越大&#xff0c;卡顿时间越久。 产品框架&#xff1a; vue2.5.2 view-design4.7.0 PS&#xff1a;前端基本没人管的老项目。。 原因: 1、组件实例过多 2、v…

剪枝基础与实战(5): 剪枝代码详解

对模型进行剪枝,我们只对有参数的层进行剪枝,我们基于BatchNorm2d对通道重要度 γ \gamma γ参数进行稀释训练。对BatchNorm2d及它的前后层也需要进行剪枝。主要针对有参数的层:Conv2d、BatchNorm2d、Linear。但是我们不会对Pool2d 层进行剪枝,因为Pool2d只用来做下采样,没…