1. 引子
本文总结自知乎文章,本人遇到了与其几乎相似的经历,特转载记录下,并再补充一点切面编程的知识。我其实也很纳闷,到底有多少面向xxxx编程的说法。
知乎文章传送门——千万不要在方法上打断点!有坑!
2. 什么是面向切面编程?
这里我们直接举出一个例子。在面向切面编程(AOP)中,一个典型的例子是日志记录。通过AOP,可以将日志记录的逻辑从核心业务逻辑中分离出来,提高代码的模块性和可维护性。以下是一个简单的Java示例,使用Spring AOP实现方法级别的日志记录:
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.service.*.*(..))")
public void logBefore(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
String className = joinPoint.getTarget().getClass().getName();
System.out.println("Before executing " + className + "." + methodName);
}
}
在上述例子中:
@Aspect
注解标志着这是一个切面类。@Before
注解标志着这是一个前置通知,在目标方法执行之前执行。- 切点表达式
"execution(* com.example.service.*.*(..))"
指定了哪些方法会触发这个切面,这里表示匹配com.example.service
包下的所有类的所有方法。
然后,我们假设有一个服务类 ExampleService
:
package com.example.service;
import org.springframework.stereotype.Service;
@Service
public class ExampleService {
public void doSomething() {
System.out.println("Doing something...");
}
}
当调用 ExampleService
中的方法时,切面中的 logBefore
方法将在方法执行前被调用,输出类似于 “Before executing com.example.service.ExampleService.doSomething” 的日志信息。
这个例子展示了如何使用AOP将横切关注点(日志记录)与核心业务逻辑(ExampleService
中的 doSomething
方法)分离开来,以提高代码的可维护性。
简单来说就是@Before
, @After
在某个已经写好的方法之前之前都要干些什么事,在之后又要都干些什么事,还有其他的:下面详细介绍下看:
通知(Advice): 通知是切面中具体的操作或功能。通知定义了在程序的哪个位置执行什么样的代码。常见的通知类型包括前置通知(Before)、后置通知(After)、返回通知(After Returning)、异常通知(After Throwing)和环绕通知(Around)。
我们好像在测试文件中会经常使用这么个注解。
3. 编程范式:面向xx编程大杂烩
每种编程范式都代表了一种不同的思考和解决问题的方式。以下是一些主要的编程范式的详细介绍:
-
面向对象编程(Object-Oriented Programming,OOP):
- 核心概念: 基于对象的概念,将数据和对数据的操作封装在对象中。
- 特点: 封装、继承、多态。
- 优势: 提高代码的可维护性、可扩展性,支持代码重用。
-
面向过程编程(Procedural Programming,POP):
- 核心概念: 将程序看作一系列的过程或函数,依次执行。
- 特点: 侧重于过程和函数的调用。
- 优势: 简单直观,适用于较小规模的任务。
-
面向切面编程(Aspect-Oriented Programming,AOP):
- 核心概念: 将横切关注点(如日志、事务、安全性检查)与核心业务逻辑分离。
- 特点: 强调关注点的模块化和可重用性。
- 优势: 提高代码的模块性、可维护性,减少重复代码。
-
函数式编程(Functional Programming,FP):
- 核心概念: 强调函数是一等公民,函数是不可变的,避免共享状态和可变数据。
- 特点: 不可变性、纯函数、高阶函数、递归。
- 优势: 易于并发编程,适用于处理大规模数据和并行计算。
-
面向服务编程(Service-Oriented Programming,SOP):
- 核心概念: 将系统划分为独立的服务单元,通过通信进行协作。
- 特点: 服务的独立性、松散耦合。
- 优势: 支持分布式系统、提高系统的灵活性和可扩展性。
-
逻辑编程(Logic Programming):
- 核心概念: 通过一组逻辑规则进行问题求解。
- 特点: 程序是一组逻辑语句,系统基于逻辑规则进行推理和搜索。
- 优势: 适用于专业推理和问题求解,例如Prolog。
-
并发编程(Concurrent Programming):
- 核心概念: 处理多任务执行,通过并发处理提高程序性能。
- 特点: 线程、进程、锁、同步、异步。
- 优势: 提高程序的性能和响应性。
-
领域特定语言(Domain-Specific Language,DSL):
- 核心概念: 针对特定问题领域设计的编程语言。
- 特点: 注重解决特定问题,通常具有高度抽象性。
- 优势: 提高领域专家的生产力,减少开发复杂性。
-
面向事件编程(Event-Driven Programming,EDP): 面向事件编程是一种基于事件和事件处理的编程范式。程序的执行流程由事件的发生和相应事件处理器的执行来驱动。这种编程范式常见于图形用户界面(GUI)开发和异步编程中。
-
面向数据编程(Data-Oriented Programming,DOP): 面向数据编程强调数据的处理和操作,以及数据之间的关系。这种范式常用于处理大规模数据集或涉及大量数据操作的应用程序。
-
面向流编程(Reactive Programming): 面向流编程是一种处理数据流和变化的编程范式。它强调响应性和异步编程,通常用于处理实时数据、事件处理和交互式应用程序。
-
面向协议编程(Protocol-Oriented Programming,POP): POP是一种编程范式,它将协议(protocol)作为一等公民,强调协议的组合和实现。这种范式在一些编程语言中,如Swift,得到了一定的支持。
-
面向表达式编程(Expression-Oriented Programming): 这是一种强调使用表达式来构建程序的编程风格,关注代码的简洁性和表达能力。
-
面向测试编程(Test-Driven Development,TDD): TDD并不是一种传统的编程范式,而是一种开发方法论。它强调在编写实际代码之前先编写测试,并通过测试驱动开发的方式逐步完善代码。