架构探险-从零开始写Javaweb框架读书笔记(5)

时间:2022-12-02 13:13:21

AOP实现

AOP(Aspect Oriented Programming,面向切面编程);用来不改变代码的情况下在方法前后加入性能监控,日志打印等等。

首先请转到代理模式介绍

依照惯例,有时spring aop的实现过程

advice 直译为通知
黄勇老师说这是不可以的
要译为增强
so
Before Advice 前置增强
After Advice 后置增强
Around Advice 环绕增强
Introduction Advice 引入增强

源码分析

//AspectJAfterAdvice.java
//方法执行
public Object invoke(MethodInvocation mi) throws Throwable {
Object var2;
try {
var2 = mi.proceed();
} finally {
this.invokeAdviceMethod(this.getJoinPointMatch(), (Object)null, (Throwable)null);
}

return var2;
}
//Joinpoint.java
public interface Joinpoint {
Object proceed() throws Throwable;

Object getThis();

AccessibleObject getStaticPart();
}
//ReflectiveMethodInvocation.java
public Object proceed() throws Throwable {
//如果当前的拦截器的下标等于此方法上面所有的拦截器的数量-1 ,那么当前的拦截器已经是此方法的最后拦截器。so 执行当前方法
if(this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return this.invokeJoinpoint();
} else {
Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if(interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice;
return dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)?dm.interceptor.invoke(this):this.proceed();
} else {
return ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this);
}
}
}

执行代理

如以下流程图

Created with Raphaël 2.1.0 执行被代理方法 获取代理链 末尾代理 代理匹配 执行代理 执行方法,返回结果 结束 yes no yes no

我们可以按照这个流程图做我们的Aop代理

/**
* 方法拦截助手类
*
* @author xueaohui
*/

public final class AopHelper {

private static final Logger LOGGER = LoggerFactory.getLogger(AopHelper.class);

static {
try {
//获取所有继承AspectProxy的类与代理的目标类映射
Map<Class<?>, Set<Class<?>>> proxyMap = createProxyMap();
//获取所有目标类 与 代理此目标 的代理类集合 映射
Map<Class<?>, List<Proxy>> targetMap = createTargetMap(proxyMap);
//遍历
for (Map.Entry<Class<?>, List<Proxy>> targetEntry : targetMap.entrySet()) {
Class<?> targetClass = targetEntry.getKey();
List<Proxy> proxyList = targetEntry.getValue();
//创建代理
Object proxy = ProxyManager.createProxy(targetClass, proxyList);
//遍历添加代理为bean,如果已经被添加至bean类中 将会覆盖已存在的bean 现在的是一个有CGLib生成的代理类
BeanHelper.setBean(targetClass, proxy);
}
} catch (Exception e) {
LOGGER.error("aop failure", e);
}
}

private static Map<Class<?>, Set<Class<?>>> createProxyMap() throws Exception {
Map<Class<?>, Set<Class<?>>> proxyMap = new HashMap<Class<?>, Set<Class<?>>>();
addAspectProxy(proxyMap);
/**
* 1. 为所有Service方法添加事务代理
* 2. 判断是否有事务注解
* 3. 有事务注解的开启事务->执行方法->提交事务
* 4. 无事务注解的执行方法(应用于单条查询)
*/

addTransactionProxy(proxyMap);
return proxyMap;
}

private static void addTransactionProxy(Map<Class<?>,Set<Class<?>>> proxyMap){
Set<Class<?>> serviceClassSet = ClassHelper.getServiceClassSet();
proxyMap.put(TransactionProxy.class,serviceClassSet);
}

private static void addAspectProxy(Map<Class<?>, Set<Class<?>>> proxyMap) throws Exception {
//获取实现切面代理的类
Set<Class<?>> proxyClassSet = ClassHelper.getClassSetBySuper(AspectProxy.class);
for (Class<?> proxyClass : proxyClassSet) {
//如果有@Aspect注解 加入代理类的
if (proxyClass.isAnnotationPresent(Aspect.class)) {
Aspect aspect = proxyClass.getAnnotation(Aspect.class);
Set<Class<?>> targetClassSet = createTargetClassSet(aspect);
proxyMap.put(proxyClass, targetClassSet);
}
}
}



private static Set<Class<?>> createTargetClassSet(Aspect aspect) throws Exception {
Set<Class<?>> targetClassSet = new HashSet<Class<?>>();
Class<? extends Annotation> annotation = aspect.value();
if (annotation != null && !annotation.equals(Aspect.class)) {
//获取有 切面注解value中的注解 的类 ,加入此注解的目标类中
targetClassSet.addAll(ClassHelper.getClassSetByAnnotation(annotation));
}
return targetClassSet;
}

/**
* 获取 目标类的代理类列表 映射
*/

private static Map<Class<?>, List<Proxy>> createTargetMap(Map<Class<?>, Set<Class<?>>> proxyMap) throws Exception {
Map<Class<?>, List<Proxy>> targetMap = new HashMap<Class<?>, List<Proxy>>();
for (Map.Entry<Class<?>, Set<Class<?>>> proxyEntry : proxyMap.entrySet()) {
Class<?> proxyClass = proxyEntry.getKey();
Set<Class<?>> targetClassSet = proxyEntry.getValue();
for (Class<?> targetClass : targetClassSet) {
Proxy proxy = (Proxy) proxyClass.newInstance();

if (targetMap.containsKey(targetClass)) {
targetMap.get(targetClass).add(proxy);
} else {
//如果目标类还没有添加代理 初始化并添加代理
List<Proxy> proxyList = new ArrayList<Proxy>();
proxyList.add(proxy);
targetMap.put(targetClass, proxyList);
}
}
}
return targetMap;
}
}