从零写一个具有IOCAOPMVC功能的框架学习笔记07-AOP功能实现以及讲解

1次阅读

共计 7125 个字符,预计需要花费 18 分钟才能阅读完成。

1. 本章须要实现的内容

  1. 实现 AspectListExecutor 类的编写
  2. 实现 AspectWeaver 类的编写
  3. 实现 PointcutLocator 类的编写
  4. 实现 ProxyCreator 类的编写

2. 实现 PointcutLocator 类的编写

2.1 须要实现的代码如下:

package com.wuyiccc.helloframework.aop;

import org.aspectj.weaver.tools.PointcutExpression;
import org.aspectj.weaver.tools.PointcutParser;
import org.aspectj.weaver.tools.ShadowMatch;

import java.lang.reflect.Method;

/**
 * @author wuyiccc
 * @date 2020/7/14 9:03
 * 岂曰无衣,与子同袍~
 */
public class PointcutLocator {

    /**
     * Pointcut 解析器,间接给它赋值上 Aspectj 的所有表达式,以便反对对泛滥表达式的解析
     */
    private PointcutParser pointcutParser = PointcutParser.getPointcutParserSupportingSpecifiedPrimitivesAndUsingContextClassloaderForResolution(PointcutParser.getAllSupportedPointcutPrimitives());

    /**
     * 表达式解析器
     */
    private PointcutExpression pointcutExpression;

    public PointcutLocator(String expression) {this.pointcutExpression = pointcutParser.parsePointcutExpression(expression);
    }

    /**
     * 判断传入的 Class 对象是否是 Aspect 的指标代理类,即匹配 Pointcut 表达式 (初筛)
     *
     * @param targetClass 指标类
     * @return 是否匹配
     */
    public boolean roughMatches(Class<?> targetClass) {return pointcutExpression.couldMatchJoinPointsInType(targetClass); // 只能校验 within,对于 execution,call,get,set 等无奈校验的表达式,间接返回 true
    }

    /**
     * 判断传入的 Method 对象是否是 Aspect 的指标代理办法,即匹配 Pointcut 表达式 (精筛)
     * @param method
     * @return
     */
    public boolean accurateMatches(Method method) {ShadowMatch shadowMatch = pointcutExpression.matchesMethodExecution(method);
        if (shadowMatch.alwaysMatches()) {return true;}
        return false;
    }

}

2.2 PointcutLocator 类相干办法解说:

3. 实现 AspectListExecutor 类的编写

3.1 须要实现的代码如下:

package com.wuyiccc.helloframework.aop;

import com.wuyiccc.helloframework.aop.aspect.AspectInfo;
import com.wuyiccc.helloframework.util.ValidationUtil;
import lombok.Getter;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;

/**
 * @author wuyiccc
 * @date 2020/7/14 9:03
 * 岂曰无衣,与子同袍~
 */
public class AspectListExecutor implements MethodInterceptor {

    private Class<?> targetClass;

    @Getter
    private List<AspectInfo> sortedAspectInfoList;


    public AspectListExecutor(Class<?> targetClass, List<AspectInfo> sortedAspectInfoList) {
        this.targetClass = targetClass;
        this.sortedAspectInfoList = sortAspectInfoList(sortedAspectInfoList);
    }

    /**
     * 依照 order 的值进行升序排序,确保 Order 值小的 aspect 先被织入
     *
     * @param aspectInfoList
     * @return
     */
    private List<AspectInfo> sortAspectInfoList(List<AspectInfo> aspectInfoList) {
        // 升序排列
        Collections.sort(aspectInfoList, new Comparator<AspectInfo>() {
            @Override
            public int compare(AspectInfo o1, AspectInfo o2) {return o1.getOrderIndex() - o2.getOrderIndex();}
        });
        return aspectInfoList;
    }

    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {

        Object returnValue = null;

        collectAccurateMatchedAspectList(method);

        if (ValidationUtil.isEmpty(sortedAspectInfoList)) {return methodProxy.invokeSuper(proxy, args);
        }
        // 1. 依照 order 的程序升序执行完所有 Aspect 的 before 办法
        invokeBeforeAdvices(method, args);
        try {
            // 2. 执行被代理类的办法
            returnValue = methodProxy.invokeSuper(proxy, args);
            // 3. 如果被代理办法失常返回,则依照 order 的程序降序执行完所有 Aspect 的 afterReturning 办法
            invokeAfterReturningAdvices(method, args, returnValue);

        } catch (Exception e) {
            // 4. 如果被代理办法抛出异样,则依照 order 的程序降序执行完所有 Aspect 的 afterThrowing 办法
            invokeAfterThrowingAdvices(method, args, e);
        }
        return returnValue;
    }

    private void collectAccurateMatchedAspectList(Method method) {if (ValidationUtil.isEmpty(sortedAspectInfoList)) {return;}
        Iterator<AspectInfo> it = sortedAspectInfoList.iterator();
        while (it.hasNext()) {AspectInfo aspectInfo = it.next();
            if (!aspectInfo.getPointcutLocator().accurateMatches(method)) {it.remove(); // 须要用 Iterator 自带的 remove,不能用 sortedAspectInfoList 的 remove,否则就会呈现并发批改异样
            }
        }
    }

    private void invokeAfterThrowingAdvices(Method method, Object[] args, Exception e) throws Throwable {for (int i = sortedAspectInfoList.size() - 1; i >= 0; i--) {sortedAspectInfoList.get(i).getAspectObject().afterThrowing(targetClass, method, args, e);
        }
    }

    private void invokeAfterReturningAdvices(Method method, Object[] args, Object returnValue) throws Throwable {for (int i = sortedAspectInfoList.size() - 1; i >= 0; i--) {sortedAspectInfoList.get(i).getAspectObject().afterReturning(targetClass, method, args, returnValue);
        }
    }

    private void invokeBeforeAdvices(Method method, Object[] args) throws Throwable {for (AspectInfo aspectInfo : sortedAspectInfoList) {aspectInfo.getAspectObject().before(targetClass, method, args);
        }
    }
}

3.2 AspectListExecutor 类相干办法解说:

4. 实现 ProxyCreator 类的编写

4.1 须要实现的代码及解说如下:

5. 实现 AspectWeaver 类的编写

5.1 须要实现的代码如下:

package org.myframework.aop;

import org.myframework.aop.annotation.Aspect;
import org.myframework.aop.annotation.Order;
import org.myframework.aop.aspect.AspectInfo;
import org.myframework.aop.aspect.DefaultAspect;
import org.myframework.core.BeanContainer;
import org.myframework.util.ValidationUtil;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * @author wuyiccc
 * @date 2020/6/16 8:49
 * 岂曰无衣,与子同袍~
 */
public class AspectWeaver {

    private BeanContainer beanContainer;

    public AspectWeaver() {beanContainer = BeanContainer.getInstance();
    }

    public void doAop() {

        // 1. 获取所有的切面类
        Set<Class<?>> aspectSet = beanContainer.getClassesByAnnotation(Aspect.class);
        if (ValidationUtil.isEmpty(aspectSet)) {return;}
        // 2. 拼装 AspectInfoList
        List<AspectInfo> aspectInfoList = packAspectInfoList(aspectSet);
        // 3. 遍历容器里的类
        Set<Class<?>> classSet = beanContainer.getClasses();
        for (Class<?> targetClass : classSet) {
            // 排除 AspectClass 本身
            if (targetClass.isAnnotationPresent(Aspect.class)) {continue;}
            // 4. 粗筛符和条件的 Aspect
            List<AspectInfo> roughMatchedAspectList = collectRoughMatchAspectListForSpecificClass(aspectInfoList, targetClass);
            // 5. 尝试进行 Aspect 织入
            wrapIfNecessary(roughMatchedAspectList, targetClass);
        }
    }

    private void wrapIfNecessary(List<AspectInfo> roughMatchedAspectList, Class<?> targetClass) {if (ValidationUtil.isEmpty(roughMatchedAspectList)) {return;}
        // 创立动静代理对象
        AspectListExecutor aspectListExecutor = new AspectListExecutor(targetClass, roughMatchedAspectList);
        Object proxyBean = ProxyCreator.createProxy(targetClass, aspectListExecutor);
        beanContainer.addBean(targetClass, proxyBean);
    }

    private List<AspectInfo> collectRoughMatchAspectListForSpecificClass(List<AspectInfo> aspectInfoList, Class<?> targetClass) {List<AspectInfo> roughMatchedAspectList = new ArrayList<>();
        for (AspectInfo aspectInfo : aspectInfoList) {
            // 粗筛
            if (aspectInfo.getPointcutLocator().roughMatches(targetClass)) {roughMatchedAspectList.add(aspectInfo);
            }
        }
        return roughMatchedAspectList;
    }

    private List<AspectInfo> packAspectInfoList(Set<Class<?>> aspectSet) {List<AspectInfo> aspectInfoList = new ArrayList<>();
        for (Class<?> aspectClass : aspectSet) {if (verifyAspect(aspectClass)) {Order orderTag = aspectClass.getAnnotation(Order.class);
                Aspect aspectTag = aspectClass.getAnnotation(Aspect.class);
                DefaultAspect defaultAspect = (DefaultAspect) beanContainer.getBean(aspectClass);
                // 初始化表达式定位器
                PointcutLocator pointcutLocator = new PointcutLocator(aspectTag.pointcut());
                AspectInfo aspectInfo = new AspectInfo(orderTag.value(), defaultAspect, pointcutLocator);
                aspectInfoList.add(aspectInfo);
            } else {throw new RuntimeException("@Aspect and @Order must be added to the Aspect class, and Aspect class must extend from DefaultAspect");
            }
        }
        return aspectInfoList;
    }


    // 框架中肯定要恪守给 Aspect 增加的 @Aspect 和 @Order 标签的标准,同时,必须继承自 DefaultAspect.class
    private boolean verifyAspect(Class<?> aspectClass) {return aspectClass.isAnnotationPresent(Aspect.class)
                && aspectClass.isAnnotationPresent(Order.class)
                && DefaultAspect.class.isAssignableFrom(aspectClass);

    }
}

5.2 AspectWeaver 类相干办法解析:

github 地址:https://github.com/wuyiccc/he…

正文完
 0