概述

spring aop实现的核心原理为动态代理+反射,本篇文章采用Java动态代理实现aop功能

相关文章

手动实现spring ioc
手动实现spring aop

代码地址

spring 底层相关实现

目录结构

手动实现spring 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);
	            }
	        }
	    }
	}

相关文章: