Skip to content

Commit 2421f3d

Browse files
更新动态代理,更新动态代理实现AOP的例子
1 parent b6cf674 commit 2421f3d

File tree

6 files changed

+203
-15
lines changed

6 files changed

+203
-15
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ Java相关Demo代码实现
2727
- [ ] 同步与协作
2828

2929
### F 动态与函数式编程
30-
- [ ] 反射
31-
- [ ] 注解
32-
- [ ] 动态代理
30+
- [x] 反射
31+
- [x] 注解
32+
- [x] 代理(静态代理、JDK动态代理、CGlib动态代理)
3333
- [ ] 类加载机制
3434
- [ ] 函数式编程
3535

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package FDynamic.Proxy.AOP;
2+
3+
4+
public class AOPMain {
5+
6+
public static void main(String[] args) {
7+
8+
ServiceA a = CGLibContainer.getInstance(ServiceA.class);
9+
a.callB();
10+
11+
}
12+
}
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
package FDynamic.Proxy.AOP;
2+
3+
import net.sf.cglib.proxy.Enhancer;
4+
import net.sf.cglib.proxy.MethodInterceptor;
5+
import net.sf.cglib.proxy.MethodProxy;
6+
7+
import java.lang.reflect.Field;
8+
import java.lang.reflect.Method;
9+
import java.util.*;
10+
11+
public class CGLibContainer {
12+
public static enum InterceptPoint {
13+
BEFORE, AFTER, EXCEPTION
14+
}
15+
16+
//CGLibContainer在初始化的时候,会分析带有@Aspect注解的类,分析出每个类的方法在
17+
//调用前、调用后、出现异常时该调用哪些方法,在创建该类的对象时,如果有需要被调用的方法,
18+
//则创建一个动态代理对象。
19+
static Class<?>[] aspects = new Class<?>[] { LogAspect.class, ExceptionAspect.class };
20+
21+
static Map<Class<?>, Map<InterceptPoint, List<Method>>> interceptMethodsMap = new HashMap<>();
22+
23+
static {
24+
init();
25+
}
26+
27+
/**
28+
* 对每个切面,即带有@Aspect注解的类cls,查找其before/after/exception方法,
29+
* 调用方法addInterceptMethod将其加入目标类的切点方法列表中
30+
*/
31+
private static void init() {
32+
for (Class<?> cls : aspects) {
33+
Aspect aspect = cls.getAnnotation(Aspect.class);
34+
if (aspect != null) {
35+
Method before = getMethod(cls, "before", new Class<?>[] { Object.class, Method.class, Object[].class });
36+
Method after = getMethod(cls, "after",
37+
new Class<?>[] { Object.class, Method.class, Object[].class, Object.class });
38+
Method exception = getMethod(cls, "exception",
39+
new Class<?>[] { Object.class, Method.class, Object[].class, Throwable.class });
40+
Class<?>[] intercepttedArr = aspect.value();
41+
for (Class<?> interceptted : intercepttedArr) {
42+
addInterceptMethod(interceptted, InterceptPoint.BEFORE, before);
43+
addInterceptMethod(interceptted, InterceptPoint.AFTER, after);
44+
addInterceptMethod(interceptted, InterceptPoint.EXCEPTION, exception);
45+
}
46+
}
47+
}
48+
}
49+
50+
private static Method getMethod(Class<?> cls, String name, Class<?>[] paramTypes) {
51+
try {
52+
return cls.getMethod(name, paramTypes);
53+
} catch (NoSuchMethodException e) {
54+
return null;
55+
}
56+
}
57+
58+
/**
59+
*
60+
* @param cls
61+
* @param point
62+
* @param method
63+
*/
64+
private static void addInterceptMethod(Class<?> cls, InterceptPoint point, Method method) {
65+
if (method == null) {
66+
return;
67+
}
68+
Map<InterceptPoint, List<Method>> map = interceptMethodsMap.get(cls);
69+
if (map == null) {
70+
map = new HashMap<>();
71+
interceptMethodsMap.put(cls, map);
72+
}
73+
List<Method> methods = map.get(point);
74+
if (methods == null) {
75+
methods = new ArrayList<>();
76+
map.put(point, methods);
77+
}
78+
methods.add(method);
79+
}
80+
81+
/**
82+
* 得到响应的切面
83+
* @param cls
84+
* @param point
85+
* @return
86+
*/
87+
static List<Method> getInterceptMethods(Class<?> cls,
88+
InterceptPoint point) {
89+
Map<InterceptPoint, List<Method>> map = interceptMethodsMap.get(cls);
90+
if (map == null) {
91+
return Collections.emptyList();
92+
}
93+
List<Method> methods = map.get(point);
94+
if (methods == null) {
95+
return Collections.emptyList();
96+
}
97+
return methods;
98+
}
99+
100+
/**
101+
* 根据原始类的实际类型查找应该执行的before/after/exception方法列表,在调用原始方法前
102+
* 执行before方法,
103+
*/
104+
static class AspectInterceptor implements MethodInterceptor {
105+
@Override
106+
public Object intercept(Object object, Method method,
107+
Object[] args, MethodProxy proxy) throws Throwable {
108+
//执行before方法
109+
List<Method> beforeMethods = getInterceptMethods(
110+
object.getClass().getSuperclass(), InterceptPoint.BEFORE);
111+
for (Method m : beforeMethods) {
112+
m.invoke(null, new Object[] { object, method, args });
113+
}
114+
115+
try {
116+
// 调用原始方法
117+
Object result = proxy.invokeSuper(object, args);
118+
119+
// 执行after方法
120+
List<Method> afterMethods = getInterceptMethods(
121+
object.getClass().getSuperclass(), InterceptPoint.AFTER);
122+
for (Method m : afterMethods) {
123+
m.invoke(null, new Object[] { object, method, args, result });
124+
}
125+
return result;
126+
} catch (Throwable e) {
127+
//执行exception方法
128+
List<Method> exceptionMethods = getInterceptMethods(
129+
object.getClass().getSuperclass(), InterceptPoint.EXCEPTION);
130+
for (Method m : exceptionMethods) {
131+
m.invoke(null, new Object[] { object, method, args, e });
132+
}
133+
throw e;
134+
}
135+
}
136+
}
137+
138+
/**
139+
* 如果类型cls不需要增强,则直接调用cls.newInstance(),否则使用cglib创建动态代理,
140+
* callback为AspectInterceptor
141+
* @param cls
142+
* @param <T>
143+
* @return
144+
* @throws InstantiationException
145+
* @throws IllegalAccessException
146+
*/
147+
private static <T> T createInstance(Class<T> cls)
148+
throws InstantiationException, IllegalAccessException {
149+
if (!interceptMethodsMap.containsKey(cls)) {
150+
return (T) cls.newInstance();
151+
}
152+
Enhancer enhancer = new Enhancer();
153+
enhancer.setSuperclass(cls);
154+
enhancer.setCallback(new AspectInterceptor());
155+
return (T) enhancer.create();
156+
}
157+
158+
/**
159+
* getInstance方法调用createInstance创建实例
160+
* @param cls
161+
* @param <T>
162+
* @return
163+
*/
164+
public static <T> T getInstance(Class<T> cls) {
165+
try {
166+
T obj = createInstance(cls);
167+
Field[] fields = cls.getDeclaredFields();
168+
for (Field f : fields) {
169+
if (f.isAnnotationPresent(SimpleInject.class)) {
170+
if (!f.isAccessible()) {
171+
f.setAccessible(true);
172+
}
173+
Class<?> fieldCls = f.getType();
174+
f.set(obj, getInstance(fieldCls));
175+
}
176+
}
177+
return obj;
178+
} catch (Exception e) {
179+
throw new RuntimeException(e);
180+
}
181+
}
182+
}

src/FDynamic/Proxy/AOP/ExceptionAspect.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
import java.lang.reflect.Method;
44
import java.util.Arrays;
55

6+
/**
7+
* ExceptionAspect是一个切面,负责ServiceB的异常切面
8+
*/
69
@Aspect({ ServiceB.class })
710
public class ExceptionAspect {
811
public static void exception(Object object,

src/FDynamic/Proxy/AOP/LogAspect.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
import java.lang.reflect.Method;
44
import java.util.Arrays;
55

6+
/**
7+
* LogAspect就是一个切面,负责ServiceA和ServiceB的日志切面,即为这两个类增加日志功能
8+
*/
69
@Aspect({ ServiceA.class, ServiceB.class })
710
public class LogAspect {
811

src/FDynamic/Proxy/AOP/SimpleSingleton.java

Lines changed: 0 additions & 12 deletions
This file was deleted.

0 commit comments

Comments
 (0)