Spring笔记

AOP底层实现原理:

首先定义一个接口Vehicle
1
2
3
4
5
6
7
8
9
10
11
public class Car implements Vehicle{
@Override
public void run() {
System.out.println("Car正在run~~~");
}

@Override
public String fly(int height) {
return "Car飞行的高度为:" + height;
}
}
然后定义两个Car和Ship类去实现Vehicle接口
1
2
3
4
5
6
7
8
9
10
11
public class Car implements Vehicle{
@Override
public void run() {
System.out.println("Car正在run~~~");
}

@Override
public String fly(int height) {
return "Car飞行的高度为:" + height;
}
}
1
2
3
4
5
6
7
8
9
10
11
public class Ship implements Vehicle{
@Override
public void run() {
System.out.println("Ship正在run~~~");
}

@Override
public String fly(int height) {
return "Ship飞行的高度为:" + height;
}
}
最后定义VehicleProxyProvider返回一个代理对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
public class VehicleProxyProvider {
//定义一个属性
//target_vehicle表示真正执行的对象
//该对象需要实现了Vehicle接口
private Vehicle target_vehicle;

public VehicleProxyProvider(Vehicle target_vehicle) {
this.target_vehicle = target_vehicle;
}

//编写一个可以返回代理对象的方法,
// 该代理对象可以通过反射机制调用到被代理对象的方法
public Vehicle getProxy(){

//得到类的加载器
ClassLoader classLoader =
target_vehicle.getClass().getClassLoader();

//得到要代理的对象/被执行对象的接口信息,底层是通过接口来完成调用
Class<?>[] interfaces =
target_vehicle.getClass().getInterfaces();

//创建InvocationHandler对象
//因为InvocationHandler是接口,
// 所有我们可以通过局部内部类的方式来创建该对象
/**
* public interface InvocationHandler {
* public Object invoke(Object proxy, Method method, Object[] args)
* throws Throwable;
* }
* invoke方法是将来执行我们的target_vehicle的方法时,会调用到
*/
InvocationHandler invocationHandler =
new InvocationHandler() {
/**
* invoke方法是将来执行我们的target_vehicle的方法时,会调用
*
* @param proxy 表示代理对象
*
* @param method 就是通过代理对象调用方法时去掉的那个方法,
* 如:代理对象.run() 或者 代理对象.fly(100)
*
* @param args 表示调用代理对象来执行方法时需要传入的参数,
* 如:代理对象.fly(xxx) xxx就是传入的参数
*
* @return 表示代理对象.run()执行后的结果
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("全部开始运作咯~~~");
//这里method 是public abstract void com.belly.spring.proxy1.Vehicle.run()
// 或是public abstract void com.belly.spring.proxy1.Vehicle.fly(xxx)
//target_vehicle 是需要代理的对象
//args 是代理对象调用的方法里的参数,如:fly(xxx)方法参数为xxx、
// run()方法没有参数所有args为null
Object result = method.invoke(target_vehicle, args);
System.out.println("全部停止运作咯~~~");
return result;
}
};

/**
* public static Object newProxyInstance(ClassLoader loader,
* Class<?>[] interfaces,
* InvocationHandler h)
* newProxyInstance()方法说明:
* 1.newProxyInstance()方法可以返回一个代理对象
* 2.ClassLoader loader 类的加载器
* 3.Class<?>[] interfaces 就是将来要代理的对象的接口信息
* 4.InvocationHandler h 调用处理器/对象 其中它里面有一个非常重要的方法invoke
*/
Vehicle proxy =
(Vehicle) Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);

return proxy;
}

这样我们就能够通过给VehicleProxyProvider传入一个Car对象或则Ship对象来返回一个代理对象,AOP就是在反射调用目标方法的前后去执行你所定义的代码,如图:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
try {

System.out.println("方法执行前-日志-方法名-" + method.getName() + "-参数"
+ Arrays.asList(args));//这里从AOP角度看,就是一个横切关注点-前置通知
BellyAOP.before(proxy, method, args);

//使用反射调用方法
result = method.invoke(target_obj, args);

System.out.println("方法执行正常结束-日志-方法名-" + method.getName()
+ "-结果result=" + result);//从AOP角度看,这也是横切关注点-返回通知

} catch (Exception e) {

System.out.println("方法执行异常-日志-方法名-" + method.getName()
+ "-异常类型=" + e.getClass().getName());//从AOP角度看,也是横切关注点-异常通知
throw new RuntimeException(e);

} finally {

//从AOP的角度看,也是一个横切关注点-最终通知
System.out.println("方法最终结束-日志-方法名-" + method.getName());

}
return result;
}