Skip to content

Commit 0abb6f7

Browse files
committed
update comment
1 parent fe6b7eb commit 0abb6f7

File tree

12 files changed

+1110
-218
lines changed

12 files changed

+1110
-218
lines changed

programming-paradigm/aop/go/aop.go

Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,14 @@ package main
22

33
import (
44
"fmt"
5+
"reflect"
56
)
67

78
/*
89
AOP(面向切面编程)是一种编程范式,通过分离横切关注点来提高模块性。
910
横切关注点是跨越应用程序多个部分的功能,比如日志记录、事务管理等。
10-
Go语言没有直接的动态代理机制,但可以通过接口和函数包装实现AOP。
11-
Go这种机构相比动态代理更加巧妙和高性能,但代码会比较啰嗦,每个类都要单独写
11+
Go语言没有直接的动态代理机制,但可以反射来达成动态代理。
1212
*/
13-
1413
// 1. 定义业务接口
1514
type UserService interface {
1615
AddUser(username string)
@@ -39,32 +38,48 @@ func (l *LoggingAspect) After() {
3938
fmt.Println("后置通知: 操作执行完成")
4039
}
4140

42-
// 4. 创建动态代理类
43-
type UserServiceProxy struct {
44-
target UserService
45-
aspect *LoggingAspect
41+
// 通用代理函数
42+
func createProxy(target interface{}, aspect *LoggingAspect, methodName string, args ...interface{}) {
43+
// 前置通知
44+
aspect.Before()
45+
46+
// 获取目标对象的反射值
47+
targetValue := reflect.ValueOf(target)
48+
49+
// 获取目标方法
50+
method := targetValue.MethodByName(methodName)
51+
52+
if method.IsValid() {
53+
// 准备参数
54+
in := make([]reflect.Value, len(args))
55+
for i, arg := range args {
56+
in[i] = reflect.ValueOf(arg)
57+
}
58+
59+
// 调用目标方法
60+
method.Call(in)
61+
}
62+
63+
// 后置通知
64+
aspect.After()
4665
}
4766

48-
// 代理类构造函数,传入目标对象和切面对象
49-
func NewUserServiceProxy(target UserService, aspect *LoggingAspect) UserService {
50-
return &UserServiceProxy{target: target, aspect: aspect}
67+
// 4. 创建动态代理结构体
68+
type DynamicServiceProxy struct {
69+
target interface{}
70+
aspect *LoggingAspect
5171
}
5272

53-
// 每个函数都实现相一遍,增加前后调用
54-
func (p *UserServiceProxy) AddUser(username string) {
55-
p.aspect.Before()
56-
p.target.AddUser(username)
57-
p.aspect.After()
73+
// 代理结构体构造函数
74+
func NewDynamicServiceProxy(target interface{}, aspect *LoggingAspect) *DynamicServiceProxy {
75+
return &DynamicServiceProxy{target: target, aspect: aspect}
5876
}
5977

60-
// 每个函数都实现相一遍,增加前后调用
61-
func (p *UserServiceProxy) DeleteUser(userId int) {
62-
p.aspect.Before()
63-
p.target.DeleteUser(userId)
64-
p.aspect.After()
78+
// 通用方法调用代理
79+
func (p *DynamicServiceProxy) Call(methodName string, args ...interface{}) {
80+
createProxy(p.target, p.aspect, methodName, args...)
6581
}
6682

67-
// 5. 测试AOP
6883
func main() {
6984
// 创建目标对象
7085
userService := &UserServiceImpl{}
@@ -73,11 +88,11 @@ func main() {
7388
aspect := &LoggingAspect{}
7489

7590
// 创建代理对象
76-
proxy := NewUserServiceProxy(userService, aspect)
91+
proxyService := NewDynamicServiceProxy(userService, aspect)
7792

7893
// 通过代理对象调用方法
79-
proxy.AddUser("张三")
80-
proxy.DeleteUser(101)
94+
proxyService.Call("AddUser", "张三")
95+
proxyService.Call("DeleteUser", 101)
8196
}
8297

8398
/*
Lines changed: 66 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,98 +1,111 @@
11
import java.lang.reflect.InvocationHandler;
22
import java.lang.reflect.Method;
33
import java.lang.reflect.Proxy;
4-
4+
import java.util.ArrayList;
5+
import java.util.List;
56
/*
67
AOP(面向切面编程)是一种编程范式,通过分离横切关注点来提高模块性。
78
横切关注点是跨越应用程序多个部分的功能,比如日志记录、事务管理等。
89
在 Java 中,主要是通过 Java 的反射机制和动态代理来实现 AOP 。
910
态代理允许在运行时创建一个实现了特定接口的代理对象,我们可以在代理对象的方法调用前后插入额外的逻辑,从而实现 AOP 的功能。
1011
*/
1112

12-
// 1. 定义业务接口
13-
interface UserService {
14-
void addUser(String username);
13+
// 1. 定义通用的切面接口(可扩展)
14+
interface Aspect {
15+
void before(Method method, Object[] args);
1516

16-
void deleteUser(int userId);
17+
void after(Method method, Object result);
1718
}
1819

19-
// 2. 实现业务接口
20-
class UserServiceImpl implements UserService {
20+
// 2. 日志切面实现
21+
class LoggingAspect implements Aspect {
2122
@Override
22-
public void addUser(String username) {
23-
System.out.println("添加用户: " + username);
23+
public void before(Method method, Object[] args) {
24+
System.out.println("前置通知: 调用 " + method.getName() + ",参数: " + java.util.Arrays.toString(args));
2425
}
2526

2627
@Override
27-
public void deleteUser(int userId) {
28-
System.out.println("删除用户: " + userId);
28+
public void after(Method method, Object result) {
29+
System.out.println("后置通知: " + method.getName() + " 执行完成,返回值: " + result);
2930
}
3031
}
3132

32-
// 3. 定义切面类
33-
class LoggingAspect {
34-
public void before() {
35-
System.out.println("前置通知: 准备执行操作");
33+
// 3. 通用动态代理类
34+
class DynamicProxy implements InvocationHandler {
35+
private final Object target; // 目标对象
36+
private final List<Aspect> aspects; // 切面列表
37+
38+
public DynamicProxy(Object target, List<Aspect> aspects) {
39+
this.target = target;
40+
this.aspects = aspects;
41+
}
42+
43+
@Override
44+
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
45+
for (Aspect aspect : aspects) {
46+
aspect.before(method, args);
47+
}
48+
Object result = method.invoke(target, args); // 调用目标方法
49+
for (Aspect aspect : aspects) {
50+
aspect.after(method, result);
51+
}
52+
return result;
3653
}
3754

38-
public void after() {
39-
System.out.println("后置通知: 操作执行完成");
55+
// 创建代理对象的通用方法
56+
@SuppressWarnings("unchecked")
57+
public static <T> T createProxy(T target, List<Aspect> aspects) {
58+
return (T) Proxy.newProxyInstance(
59+
target.getClass().getClassLoader(),
60+
target.getClass().getInterfaces(),
61+
new DynamicProxy(target, aspects));
4062
}
4163
}
4264

43-
// 4. 创建动态代理类
44-
class UserServiceProxy implements InvocationHandler {
45-
private Object target; // 目标对象(被代理的对象)
46-
private LoggingAspect aspect; // 切面对象(包含横切逻辑)
65+
// 4. 业务接口
66+
interface UserService {
67+
void addUser(String username);
4768

48-
// 构造函数,传入目标对象和切面对象
49-
public UserServiceProxy(Object target, LoggingAspect aspect) {
50-
this.target = target;
51-
this.aspect = aspect;
69+
void deleteUser(int userId);
70+
}
71+
72+
// 5. 业务实现类
73+
class UserServiceImpl implements UserService {
74+
@Override
75+
public void addUser(String username) {
76+
System.out.println("添加用户: " + username);
5277
}
5378

54-
// 实现 InvocationHandler 接口的 invoke 方法
5579
@Override
56-
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
57-
aspect.before(); // 前置通知:在目标方法执行前调用
58-
Object result = method.invoke(target, args); // 调用目标方法
59-
aspect.after(); // 后置通知:在目标方法执行后调用
60-
return result; // 返回目标方法的执行结果
80+
public void deleteUser(int userId) {
81+
System.out.println("删除用户: " + userId);
6182
}
6283
}
6384

64-
// 5. 测试AOP
85+
// 6. 测试 AOP 代理
6586
public class AOP {
6687
public static void main(String[] args) {
6788
// 创建目标对象
6889
UserService userService = new UserServiceImpl();
6990

70-
// 创建切面对象
71-
LoggingAspect aspect = new LoggingAspect();
91+
// 创建切面列表
92+
List<Aspect> aspects = new ArrayList<>();
93+
aspects.add(new LoggingAspect()); // 可以添加多个切面
7294

73-
// 通过动态代理创建代理对象
74-
UserService proxy = (UserService) Proxy.newProxyInstance(
75-
userService.getClass().getClassLoader(), // 目标类的类加载器
76-
userService.getClass().getInterfaces(), // 目标类实现的接口
77-
new UserServiceProxy(userService, aspect) // InvocationHandler 实现类
78-
);
95+
// 通过动态代理创建 UserService 代理对象
96+
UserService proxy = DynamicProxy.createProxy(userService, aspects);
7997

80-
// 通过代理对象调用 UserService 的方法
81-
// 调用 addUser 方法时,会先执行前置通知,再执行目标方法,最后执行后置通知
98+
// 调用代理方法,自动执行 AOP 逻辑
8299
proxy.addUser("张三");
83-
84-
// 调用 deleteUser 方法时,同样会先执行前置通知,再执行目标方法,最后执行后置通知
85100
proxy.deleteUser(101);
86101
}
87102
}
88-
89103
/*
90-
* jarry@Mac java % javac AOP.java
91-
* jarry@Mac java % java AOP
92-
* 前置通知: 准备执行操作
93-
* 添加用户: 张三
94-
* 后置通知: 操作执行完成
95-
* 前置通知: 准备执行操作
96-
* 删除用户: 101
97-
* 后置通知: 操作执行完成
104+
jarry@MacBook-Pro java % java AOP.java
105+
前置通知: 调用 addUser,参数: [张三]
106+
添加用户: 张三
107+
后置通知: addUser 执行完成,返回值: null
108+
前置通知: 调用 deleteUser,参数: [101]
109+
删除用户: 101
110+
后置通知: deleteUser 执行完成,返回值: null
98111
*/

programming-paradigm/aop/rust/aop

437 KB
Binary file not shown.

0 commit comments

Comments
 (0)