千家信息网

JavaEE手写AOP实现,自动代理, AOP 面向切面的编程思想

发表于:2024-11-17 作者:千家信息网编辑
千家信息网最后更新 2024年11月17日,AOP 面向切面的编程思想。 Spring的主要特性之一,今天我整理了一下,小牛试刀,写了一个Demo分享给大家。切面最主要的功能是在不影响主业务方法逻辑的情况下,在执行业务方法之前或之后加入执行代码
千家信息网最后更新 2024年11月17日JavaEE手写AOP实现,自动代理, AOP 面向切面的编程思想

AOP 面向切面的编程思想。 Spring的主要特性之一,今天我整理了一下,小牛试刀,写了一个Demo分享给大家。

切面最主要的功能是在不影响主业务方法逻辑的情况下,在执行业务方法之前或之后加入执行代码。
在JavaEE中最常见的莫过于事务控制, 使得程序员只需关注核心业务逻辑,而无需关注事务相反非业务而又必须要的代码。

切面的主要组件有:

1、切面(@Aspect)。

2、切点(@Pointcut)、

3、通知方法(@Advise),主要有3个

1、执行前通知- @Before

2、执行后通知- @After

3、环绕通知- @Around


关系图如下:

AOP项目展开截图:



InstanceFactory 源码:

package com.hianzuo.aop;import java.lang.annotation.Annotation;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.util.ArrayList;import java.util.HashMap;import java.util.List;/** * Created by Ryan * On 2017/10/5. */public class InstanceFactory {    private static final HashMap, Object> classBeanMap = new HashMap<>();    private static final HashMap beanNameMap = new HashMap<>();    private static final HashMap, List> mAspectPointcutMethodListMap = new HashMap<>();    public static  T getInstance(Class clazz) {        return (T) classBeanMap.get(clazz);    }    public static  T getInstance(String beanName) {        return (T) classBeanMap.get(beanName);    }    public static void init(String pnScan) {        List> classes = ClassUtil.getClasses(pnScan);        for (Class clazz : classes) {            if (isAspectClazz(clazz)) {                initAspect(clazz);            }        }        for (Class clazz : classes) {            if (isBeanClazz(clazz)) {                initBean(clazz);            }        }    }    private static void initAspect(Class aspectClazz) {        Method[] methods = aspectClazz.getMethods();        Object obj;        try {            obj = aspectClazz.newInstance();        } catch (Exception e) {            throw new RuntimeException(e);        }        for (Method method : methods) {            if (method.isAnnotationPresent(Before.class)) {                Before adviceBefore = method.getAnnotation(Before.class);                List adviceList = getAspectAdviceList(Before.class);                adviceList.add(new AspectAdviceMethod(adviceBefore.value(), adviceBefore.order(), obj, method));            }            if (method.isAnnotationPresent(After.class)) {                After adviceAfter = method.getAnnotation(After.class);                List adviceList = getAspectAdviceList(After.class);                adviceList.add(new AspectAdviceMethod(adviceAfter.value(), adviceAfter.order(), obj, method));            }            if (method.isAnnotationPresent(Around.class)) {                Around adviceAround = method.getAnnotation(Around.class);                List adviceList = getAspectAdviceList(Around.class);                adviceList.add(new AspectAdviceAroundMethod(adviceAround.value(), adviceAround.order(), obj, method));            }        }    }    private static List getAspectAdviceList(Class adviceClazz) {        List methodList = mAspectPointcutMethodListMap.get(adviceClazz);        if (null == methodList) {            methodList = new ArrayList<>();            mAspectPointcutMethodListMap.put(adviceClazz, methodList);        }        return methodList;    }    private static boolean isAspectClazz(Class aClass) {        if (aClass.isAnnotationPresent(Aspect.class)) {            return true;        }        return false;    }    private static void initBean(Class beanClazz) {        Class[] interfaces = beanClazz.getInterfaces();        if (null == interfaces) return;        for (Class anInterface : interfaces) {            String beanName = getBeanName(anInterface);            Object obj = newInstanceProxyClass(anInterface, beanClazz);            beanNameMap.put(beanName, obj);            classBeanMap.put(anInterface, obj);        }    }    private static Object newInstanceProxyClass(Class anInterface, Class beanClazz) {        try {            Object targetObj = beanClazz.newInstance();            return Proxy.newProxyInstance(targetObj.getClass().getClassLoader(), new Class[]{anInterface}, new AspectHandler(targetObj, mAspectPointcutMethodListMap));        } catch (Exception e) {            throw new RuntimeException(e);        }    }    private static String getBeanName(Class anInterface) {        return anInterface.getSimpleName();    }    private static boolean isBeanClazz(Class aClass) {        if (aClass.isAnnotationPresent(Component.class)) {            return true;        }        return false;    }}
AspectHandler 源码:
package com.hianzuo.aop;import java.lang.annotation.Annotation;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.util.*;/** * Created by Ryan * On 2017/10/5. */class AspectHandler implements InvocationHandler {    private Object targetObj;    private HashMap, List> mAspectPointcutMethodListMap;    private HashMap> mBeforeMethodMap = new HashMap<>();    private HashMap> mAfterMethodMap = new HashMap<>();    private HashMap mAroundMethodMap = new HashMap<>();    public AspectHandler(Object targetObj, HashMap, List> map) {        this.targetObj = targetObj;        this.mAspectPointcutMethodListMap = map;    }    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        List beforeMethods = getBeforeMethodList(method);        JointPoint beforePoint = new JointPoint().setTargetObj(targetObj).setProxy(proxy).setMethod(method).setArgs(args);        for (AspectAdviceMethod adviceMethod : beforeMethods) {            adviceMethod.invoke(beforePoint);        }        AspectAdviceAroundMethod aroundMethod = getAroundMethodList(method);        Object obj;        if (null != aroundMethod) {            obj = aroundMethod.invoke(beforePoint);        } else {            obj = method.invoke(targetObj, args);        }        List afterMethods = getAfterMethodList(method);        JointPoint afterPoint = new JointPoint().setTargetObj(targetObj).setProxy(proxy).setMethod(method).setArgs(args).setResult(obj);        for (AspectAdviceMethod adviceMethod : afterMethods) {            adviceMethod.invoke(afterPoint);        }        return obj;    }    private AspectAdviceAroundMethod getAroundMethodList(Method method) {        if (mAroundMethodMap.containsKey(method)) return mAroundMethodMap.get(method);        List adviceMethods = mAspectPointcutMethodListMap.get(Around.class);        if (null == adviceMethods) return null;        List list = new ArrayList<>();        for (AspectAdviceMethod adviceMethod : adviceMethods) {            AspectAdviceAroundMethod adviceAroundMethod = (AspectAdviceAroundMethod) adviceMethod;            if (adviceAroundMethod.match(method)) {                list.add(adviceAroundMethod);            }        }        AspectAdviceAroundMethod aroundMethod = null;        if (!list.isEmpty()) {            sortAdviceList(list);            AspectAdviceAroundMethod upMethod = null;            for (AspectAdviceAroundMethod adviceAroundMethod : list) {                if (null == aroundMethod) aroundMethod = adviceAroundMethod;                if (null != upMethod) {                    upMethod.setNextMethod(adviceAroundMethod);                }                upMethod = adviceAroundMethod;            }        }        mAroundMethodMap.put(method, aroundMethod);        return aroundMethod;    }    private static void sortAdviceList(List list) {        Collections.sort(list, (Comparator) (o1, o2) -> {            Integer order1 = o1.getPointMethodOrder();            Integer order2 = o2.getPointMethodOrder();            return order1.compareTo(order2);        });    }    private List getAfterMethodList(Method method) {        return getAspectAdviceMethods(After.class, mAspectPointcutMethodListMap, mAfterMethodMap, method);    }    private List getBeforeMethodList(Method method) {        return getAspectAdviceMethods(Before.class, mAspectPointcutMethodListMap, mBeforeMethodMap, method);    }    private static List getAspectAdviceMethods(Class adviceClass, HashMap, List> dataMap, HashMap> methodMap, Method method) {        List aspectAdviceMethods = methodMap.get(method);        if (null != aspectAdviceMethods) return aspectAdviceMethods;        aspectAdviceMethods = new ArrayList<>();        methodMap.put(method, aspectAdviceMethods);        List methods = dataMap.get(adviceClass);        if (null == method) return aspectAdviceMethods;        for (AspectAdviceMethod adviceMethod : methods) {            if (adviceMethod.match(method)) {                aspectAdviceMethods.add(adviceMethod);            }        }        sortAdviceList(aspectAdviceMethods);        return aspectAdviceMethods;    }}
0