手写AOP实现过程

三.手写aop主要实现过程
1.定义配置标记

@Aspect:配置标记横切对象(方法)的地址

@Order:配置标记横切的顺序

@Aspect/@Order

Copy
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Aspect {
String pointcut();
}
Copy
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Order {
/**
* 控制类的执行顺序,值越小优先级越高
*/
int value();
}
2.定义默认切面类

Copy
package org.simplespring.aop.aspect;

import java.lang.reflect.Method;

/**

  • 定义默认切面类
    /
    public abstract class DefaultAspect {
    /
    *

    • 事前拦截
    • @param targetClass 被代理的目标类
    • @param method 被代理的目标方法
    • @param args 被代理的目标方法对应的参数列表
    • @throws Throwable
      */
      public void before(Class<?> targetClass, Method method, Object[] args) throws Throwable{

    }
    /**

    • 事后拦截
    • @param targetClass 被代理的目标类
    • @param method 被代理的目标方法
    • @param args 被代理的目标方法对应的参数列表
    • @param returnValue 被代理的目标方法执行后的返回值
    • @throws Throwable
      /
      public Object afterReturning(Class<?> targetClass, Method method, Object[] args, Object returnValue) throws Throwable{
      return returnValue;
      }
      /
      *
    • @param targetClass 被代理的目标类
    • @param method 被代理的目标方法
    • @param args 被代理的目标方法对应的参数列表
    • @param e 被代理的目标方法抛出的异常
    • @throws Throwable
      */
      public void afterThrowing(Class<?> targetClass, Method method, Object[] args, Throwable e) throws Throwable{

    }
    }
    3.定义切面织入器

核心流程:

1.获取所有的切面类

2.遍历容器管理的类
3.筛选出匹配容器管理类的切面aspectlist
4.尝试进行Aspect的织入 生成动态代理对象 并替换beancontainer中原先class对应所对应的实例对象

Copy
package org.simplespring.aop;

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

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

/**

  • @Classname AspectWeaver

  • @Description 切面织入器

  • @Date 2020/8/8 19:43

  • @Created by zhangtianci
    */
    public class AspectWeaver {

    /**

    • 拥有一个bean容器
      */
      private BeanContainer beanContainer;

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

    /**

    • 1.获取所有的切面类
    • 2.遍历容器里的类
    • 3.筛选出匹配类的切面aspect
    • 4.尝试进行Aspect的织入 生成动态代理对象
      */
      public void doAop() {
      //1.获取所有的切面类
      Set<Class<?>> aspectSet = beanContainer.getClassesByAnnotation(Aspect.class);
      if(ValidationUtil.isEmpty(aspectSet)){return;}
      //2.拼装AspectInfoList
      List aspectInfoList = packAspectInfoList(aspectSet);
      //3.遍历容器里的类
      Set<Class<?>> classSet = beanContainer.getClasses();
      for (Class<?> targetClass: classSet) {
      //排除AspectClass自身
      if(targetClass.isAnnotationPresent(Aspect.class)){
      continue;
      }
      //4.粗筛符合条件的Aspect
      List roughMatchedAspectList = collectRoughMatchedAspectListForSpecificClass(aspectInfoList, targetClass);
      //5.尝试进行Aspect的织入
      wrapIfNecessary(roughMatchedAspectList,targetClass);
      }

    }

    private void wrapIfNecessary(List 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 collectRoughMatchedAspectListForSpecificClass(List aspectInfoList, Class<?> targetClass) {
    List roughMatchedAspectList = new ArrayList<>();
    for(AspectInfo aspectInfo : aspectInfoList){
    //粗筛
    if(aspectInfo.getPointcutLocator().roughMatches(targetClass)){
    roughMatchedAspectList.add(aspectInfo);
    }
    }
    return roughMatchedAspectList;
    }

    private List packAspectInfoList(Set<Class<?>> aspectSet) {
    List 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
    //此外,@Aspect的属性值不能是它本身
    private boolean verifyAspect(Class<?> aspectClass) {
    return aspectClass.isAnnotationPresent(Aspect.class) &&
    aspectClass.isAnnotationPresent(Order.class) &&
    DefaultAspect.class.isAssignableFrom(aspectClass);
    }
    }
    切面信息包装类(增强的动作/增强对象地址/横切顺序)

Copy
package org.simplespring.aop.aspect;

import lombok.AllArgsConstructor;
import lombok.Getter;
import org.simplespring.aop.PointcutLocator;

@AllArgsConstructor
@Getter
public class AspectInfo {
private int orderIndex;
private DefaultAspect aspectObject;
private PointcutLocator pointcutLocator;
}
采用cglib动态的实现方式:

实现net.sf.cglib.proxy.MethodInterceptor接口,定义代理后方法的动作(相当于实现jdk动态代理中的InvocationHandler接口)

Copy
package org.simplespring.aop;

import lombok.Getter;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import org.simplespring.aop.aspect.AspectInfo;
import org.simplespring.util.ValidationUtil;

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

public class AspectListExecutor implements MethodInterceptor {
//被代理的类
private Class<?> targetClass;
//排好序的Aspect列表
@Getter
private ListsortedAspectInfoList;

public AspectListExecutor(Class<?> targetClass, List<AspectInfo> aspectInfoList){
    this.targetClass = targetClass;
    this.sortedAspectInfoList = sortAspectInfoList(aspectInfoList);
}
/**
 * 按照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)){
        returnValue = methodProxy.invokeSuper(proxy, args);
        return returnValue;
    }
    //1.按照order的顺序升序执行完所有Aspect的before方法
    invokeBeforeAdvices(method, args);
    try{
        //2.执行被代理类的方法
        returnValue = methodProxy.invokeSuper(proxy, args);
        //3.如果被代理方法正常返回,则按照order的顺序降序执行完所有Aspect的afterReturning方法
        returnValue = invokeAfterReturningAdvices(method, args, returnValue);
    } catch (Exception e){
        //4.如果被代理方法抛出异常,则按照order的顺序降序执行完所有Aspect的afterThrowing方法
        invokeAfterThrowingAdvides(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();
        }
    }
}


//4.如果被代理方法抛出异常,则按照order的顺序降序执行完所有Aspect的afterThrowing方法
private void invokeAfterThrowingAdvides(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);
    }
}

//3.如果被代理方法正常返回,则按照order的顺序降序执行完所有Aspect的afterReturning方法
private Object invokeAfterReturningAdvices(Method method, Object[] args, Object returnValue) throws Throwable {
    Object result = null;
    for (int i =  sortedAspectInfoList.size() - 1; i >=0 ; i--){
        result = sortedAspectInfoList.get(i).getAspectObject().afterReturning(targetClass, method, args, returnValue);
    }
    return result;
}

//1.按照order的顺序升序执行完所有Aspect的before方法
private void invokeBeforeAdvices(Method method, Object[] args) throws Throwable {
    for(AspectInfo aspectInfo : sortedAspectInfoList){
        aspectInfo.getAspectObject().before(targetClass, method, args);
    }
}

}
创建代理类:

Copy
package org.simplespring.aop;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;

public class ProxyCreator {
/**
* 创建动态代理对象并返回
* @param targetClass 被代理的Class对象
* @param methodInterceptor 方法拦截器
* @return
*/
public static Object createProxy(Class<?> targetClass, MethodInterceptor methodInterceptor){
return Enhancer.create(targetClass, methodInterceptor);
}
}
解析Aspect表达式并且定位被织入的目标工具类:

Copy
package org.simplespring.aop;

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

import java.lang.reflect.Method;

/**

  • 解析Aspect表达式并且定位被织入的目标
    /
    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){
      //couldMatchJoinPointsInType比较坑,只能校验within
      //不能校验 (execution(精确到某个类除外), call, get, set),面对无法校验的表达式,直接返回true
      return pointcutExpression.couldMatchJoinPointsInType(targetClass);
      }
      /
      *
    • 判断传入的Method对象是否是Aspect的目标代理方法,即匹配Pointcut表达式(精筛)
    • @param method
    • @return
      */
      public boolean accurateMatches(Method method){
      ShadowMatch shadowMatch = pointcutExpression.matchesMethodExecution(method);
      if(shadowMatch.alwaysMatches()){
      return true;
      } else{
      return false;
      }
      }
      }
      亚马逊测评 www.yisuping.com
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值