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

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

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

切面的主要组件有:  

    1、切面(@Aspect)。 

    2、切点(@Pointcut)、

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

             1、执行前通知- @Before

             2、执行后通知- @After

             3、环绕通知- @Around

 关系图如下:

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

AOP项目展开截图:

JavaEE手写AOP实现,自动代理, 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<Class<?>, Object> classBeanMap = new HashMap<>();
    private static final HashMap<String, Object> beanNameMap = new HashMap<>();
    private static final HashMap<Class<? extends Annotation>, List<AspectAdviceMethod>> mAspectPointcutMethodListMap = new HashMap<>();
    public static <T> T getInstance(Class<T> clazz) {
        return (T) classBeanMap.get(clazz);
    }
    public static <T> T getInstance(String beanName) {
        return (T) classBeanMap.get(beanName);
    }
    public static void init(String pnScan) {
        List<Class<?>> 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<AspectAdviceMethod> 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<AspectAdviceMethod> 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<AspectAdviceMethod> adviceList = getAspectAdviceList(Around.class);
                adviceList.add(new AspectAdviceAroundMethod(adviceAround.value(), adviceAround.order(), obj, method));
            }
        }
    }
    private static List<AspectAdviceMethod> getAspectAdviceList(Class<? extends Annotation> adviceClazz) {
        List<AspectAdviceMethod> 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<? extends AspectAdviceMethod> 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<? extends Annotation> 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;
    }
}

原创文章,作者:kepupublish,如若转载,请注明出处:https://blog.ytso.com/197955.html

(0)
上一篇 2021年11月17日
下一篇 2021年11月17日

相关推荐

发表回复

登录后才能评论