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<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;
}
}
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。