概述
spring aop实现的核心原理为动态代理+反射,本篇文章采用Java动态代理实现aop功能
相关文章
代码地址
目录结构
代码
- 注解类
/**
* 定义切面
* @author jipf
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface JAspect {
}
/**
* 定义切点
* @author jipf
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface JPointcut {
/**
* 仅支持注解方式
* @return
*/
Class<?> clazz();
}
- 切面处理类
package com.jipf.aop.aspect;
public interface IAspectHandler {
/**
* 获取切面实例
* @param pointCanonicalName
* @return
*/
public Object getAspectInstance(String pointCanonicalName);
}
package com.jipf.aop.aspect;
import com.jipf.aop.annotation.JAspect;
import com.jipf.aop.annotation.JPointcut;
import com.jipf.aop.core.IAspect;
import com.jipf.aop.exception.AspectHandlerException;
import java.lang.reflect.Method;
import java.util.*;
public abstract class AbsAspectHandler implements IAspectHandler{
/* key=切点getCanonicalName value=切面类实例**/
private Map<String, Object> aspectPointMap = new HashMap<>();
@Override
public Object getAspectInstance(String pointCanonicalName) {
return this.aspectPointMap.get(pointCanonicalName);
}
protected List<Object> filterAspect(Map<String, Object> iocBeans) {
List<Object> list = new ArrayList<Object>();
Iterator<Map.Entry<String, Object>> iterator = iocBeans.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, Object> entry = iterator.next();
if (entry.getValue().getClass().isAnnotationPresent(JAspect.class)) {
list.add(entry.getValue());
/* 移除切面类**/
iterator.remove();
}
}
return list;
}
protected void parseAspect(List<Object> aspectBeans) {
aspectBeans.stream().forEach(aspect -> {
Class<?> clazz = aspect.getClass();
this.checkIAspect(clazz);
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(JPointcut.class)) {
JPointcut jPointcut = method.getAnnotation(JPointcut.class);
Class<?> annotation = jPointcut.clazz();
if (!annotation.isAnnotation()) {
throw new AspectHandlerException("@JPointcut value must be annotation!");
}
this.aspectPointMap.put(annotation.getCanonicalName(), aspect);
}
}
});
}
/**
* 定义@JAspect的类必须实现IAspect接口
*
* @param clazz
* @return
*/
private void checkIAspect(Class<?> clazz) {
Class<?>[] cl = clazz.getInterfaces();
boolean status = false;
for (Class<?> c : cl) {
if (c == IAspect.class) {
status = true;
}
}
if (!status) {
throw new AspectHandlerException(clazz.getCanonicalName() + " not implements IAspect !");
}
}
}
package com.jipf.aop.aspect.impl;
import com.jipf.aop.aspect.AbsAspectHandler;
import java.util.List;
import java.util.Map;
public class AspectHandler extends AbsAspectHandler {
public AspectHandler(Map<String, Object> iocBeans) {
/* 获取带有@JAspect的类**/
List<Object> aspectBeans = this.filterAspect(iocBeans);
/* 解析切面类**/
this.parseAspect(aspectBeans);
}
}
package com.jipf.aop.core;
/**
* 切面顶级接口,自定义切面类必须实现该接口
* @author jipf
*/
public interface IAspect {
/**
* 前置执行
*/
public void before(String s);
/**
* 后置执行
*/
public void after(String s);
}
- 代理相关
package com.jipf.aop.proxy;
import com.jipf.aop.aspect.IAspectHandler;
import com.jipf.aop.core.IAspect;
import com.jipf.aop.exception.AspectHandlerException;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
public abstract class AbsBeanInvocationHandler implements InvocationHandler {
/* 代理目标对象**/
private Object target;
private IAspectHandler iAspectHandler;
protected AbsBeanInvocationHandler(Object target, IAspectHandler iAspectHandler) {
this.target = target;
this.iAspectHandler = iAspectHandler;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) {
try {
/* 获取该方法切点对应的切面实例**/
Method m = this.target.getClass().getDeclaredMethod(method.getName(), method.getParameterTypes());
List<Object> instances = this.getAspectInstances(m.getAnnotations());
String info = "Class:" + this.target.getClass().getCanonicalName() + " Method:" + method.getName();
/* 前置处理**/
this.execAspectInstance("before", instances,info);
Object result = result = method.invoke(this.target, args);
/* 后置处理**/
this.execAspectInstance("after", instances,info);
return result;
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
throw new AspectHandlerException("proxy invoke method exception!");
}
}
private List<Object> getAspectInstances(Annotation[] annotations) {
List<Object> instances = new ArrayList<>();
for (Annotation annotation : annotations) {
Class<?> clazz = annotation.annotationType();
Object instance = this.iAspectHandler.getAspectInstance(clazz.getCanonicalName());
if (instance != null) {
instances.add(instance);
}
}
return instances;
}
/**
* 执行切面实例方法
*
* @param cmd
* @param instances
*/
private void execAspectInstance(String cmd, List<Object> instances,String info) {
instances.stream().forEach(instance -> {
IAspect iAspect = (IAspect) instance;
switch (cmd) {
case "before":
iAspect.before(info);
break;
case "after":
iAspect.after(info);
break;
default:
break;
}
});
}
}
package com.jipf.aop.proxy.impl;
import com.jipf.aop.aspect.IAspectHandler;
import com.jipf.aop.proxy.AbsBeanInvocationHandler;
public class BeanInvocationHandler extends AbsBeanInvocationHandler {
public BeanInvocationHandler(Object target,IAspectHandler iAspectHandler) {
super(target,iAspectHandler);
}
}
package com.jipf.aop.proxy;
import com.jipf.aop.aspect.IAspectHandler;
import com.jipf.aop.proxy.impl.BeanInvocationHandler;
import java.lang.reflect.Proxy;
public class ProxyBeanFactory {
public static Object newProxyBean(Object target, IAspectHandler iAspectHandler, Class<?>[] interfaces) {
return Proxy.newProxyInstance(target.getClass().getClassLoader()
, interfaces
, new BeanInvocationHandler(target, iAspectHandler));
}
}
- aop入口
package com.jipf.aop;
import com.jipf.aop.aspect.IAspectHandler;
import com.jipf.aop.aspect.impl.AspectHandler;
import com.jipf.aop.exception.AspectHandlerException;
import com.jipf.aop.proxy.ProxyBeanFactory;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.Map;
public class AopBeanContext {
/**
* 根据切点创建含有代理类的ioc bean容器
*
* @return
*/
public static void createProxyBeanContext(Map<String, Object> iocBeans) {
IAspectHandler iAspectHandler = new AspectHandler(iocBeans);
/* 处理需要代理的类 生成代理实例替换原始对象**/
doProxy(iocBeans, iAspectHandler);
}
private static void doProxy(Map<String, Object> iocBeans, IAspectHandler iAspectHandler) {
Iterator<Map.Entry<String, Object>> iterator = iocBeans.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, Object> entry = iterator.next();
Class<?> clazz = entry.getValue().getClass();
boolean status = false;
for (Method method : clazz.getDeclaredMethods()) {
for (Annotation annotation : method.getDeclaredAnnotations()) {
Class<?> cl = annotation.annotationType();
if (iAspectHandler.getAspectInstance(cl.getCanonicalName()) != null) {//需要生成代理类
status = true;
break;
}
}
}
if (status) {//需要生成代理类
Class<?>[] classes = clazz.getInterfaces();
if (classes.length == 0) {
throw new AspectHandlerException("proxy instance must be implements interface");
}
Object proxy = ProxyBeanFactory.newProxyBean(entry.getValue(), iAspectHandler, classes);
iocBeans.put(entry.getKey(), proxy);
}
}
}
}