springboot手写AOP
身为一名java码农,Spring是再熟悉不过的框架了,无论是最初的Spring,还是后来的SpringMVC,SpringBoot以及全家桶SpringCloud,都曾经使用或者正在使用,对于spring的两大核心AOP和IOC,相信很多小伙伴在面试的时候都被问过,虽然很熟悉,但是如果真正的动手写一个,还是有一点陌生和难度的,正好今天周六,在家闲来无事,整了一个简易版的AOP,顺便记录一下,毕竟好记性不如烂笔头,话不多说,下面直接上硬货。
首先整了一个小小的流程图,避免写代码的时候思路出现卡壳。
其实思路整好了,接下来动手写就简单多了。
一、定义切点
public interface Joinpoint { // 切点的执行点 Object proceed(); // 获取切点所在的方法 Method getMethod(); // 目标类 Object getThis(); // 目标类执行的参数 Object[] getArguments(); }
二、接下来是对方法的拦截(因为只是一个简易版的,所以并没有太复杂)
public interface MethodInterceptor { Object invoke(MethodInvocation invocation); }
三、实现类
public class MethodAdviceInterceptor implements MethodInterceptor { private MethodAdvice advice; public MethodAdviceInterceptor(MethodAdvice advice){ this.advice = advice; } @Override public Object invoke(MethodInvocation invocation) { advice.sendMsg(invocation.getMethod(), invocation.getArguments(), invocation.getThis()); return invocation.proceed(); } }
四、定义一个通知的接口
public interface MethodAdvice extends Advice { void sendMsg(Method method, Object[] args, Object target); }
五、封装一个代理对象的载体
// 目标对象 private Object target; // 代理对象实现的接口 private List<Class<?>> interfaces = new ArrayList<>(); private List<Advisor> advisors = new ArrayList<>(); //适配器,advice适配成MethodInterceptor private AdvisorAdapter advisorAdapter = new MethodAdviceAdapter();
其中最重要的方法一个是添加目标对象对象所实现的接口
public void addInterface(List<Class<?>> interfaces){ this.interfaces.clear(); for (Class<?> ifc : interfaces){ this.interfaces.add(ifc); } }
另外一个就是根据所有获取到的advisor,获取advice,并将其适配成所有的MethodInterceptor
public List<Object> getBeforeInterceptorsAndDynamicInterceptionAdvice(){ List<Object> interceptorList = new ArrayList<>(); for (Advisor advisor : this.advisors){ if (advisor instanceof DefaultPointcutAdvisor && Objects.equals(advisor.getAdvisorType(), Commutil.ADVISOR_BEFORE_TYPE)){ interceptorList.add(advisorAdapter.getInterceptor(advisor)); } } return interceptorList; }
六、advisor是自定义的一个通知器
public interface Advisor { Pointcut getPointcut(); Advice getAdvice(); String getAdvisorType(); }
七、定义一个advisor的实现类
public class DefaultPointcutAdvisor implements Advisor { private Pointcut pointcut; private Advice advice; private String advisorType; public DefaultPointcutAdvisor(Pointcut pointcut, Advice advice, String advisorType){ this.pointcut = pointcut; this.advice = advice; this.advisorType = advisorType; } @Override public Pointcut getPointcut() { return this.pointcut; } @Override public Advice getAdvice() { return this.advice; } @Override public String getAdvisorType() { return this.advisorType; } }
八、advice是通知的切面逻辑,这里为了简单就没写逻辑
public interface Advice { }
到这里,准备工作就完成了,接下来正式进入核心代码逻辑
一、定义ReflectiveMethodInvocation类用来处理切面逻辑
public class ReflectiveMethodInvocation implements MethodInvocation { // 代理对象 private Object proxy; // 目标对象 private Object target; // 目标方法 private Method method; // 一连串的前置通知器,都封装成MethodInterceptor protected final List<?> beforeInterceptorsAndDynamicMethodMatchers; // 一连串的后置通知器,都封装成MethodInterceptor protected final List<?> afterInterceptorsAndDynamicMethodMatchers; private Object[] aguments; // 代表执行到第几个通知器链 private int currentBeforeInterceptorIndex = -1; private int currentAfterInterceptorIndex = -1; public ReflectiveMethodInvocation(Object proxy, Object target, Method method, Object[] aguments, List<?> beforeInterceptorsAndDynamicMethodMatchers, List<?> afterInterceptorsAndDynamicMethodMatchers) { this.proxy = proxy; this.target = target; this.method = method; this.aguments = aguments; this.beforeInterceptorsAndDynamicMethodMatchers = beforeInterceptorsAndDynamicMethodMatchers; this.afterInterceptorsAndDynamicMethodMatchers = afterInterceptorsAndDynamicMethodMatchers; } @Override public Object proceed() { Object obj = null; int methodBeforeIndex = beforeInterceptorsAndDynamicMethodMatchers.size() - 1; if (methodBeforeIndex > this.currentBeforeInterceptorIndex){ // 这里就是将advice封装成MethodInterceptor,从链表中一个一个执行 Object interceptorOrInterceptionAdvice = this.beforeInterceptorsAndDynamicMethodMatchers.get(++this.currentBeforeInterceptorIndex); // 这里将ReflectiveMethodInvocation自己用传入了,是一个递归调用 return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } if (Objects.equals(this.currentBeforeInterceptorIndex, methodBeforeIndex)) { try { // 目标方法的最终调用 obj = method.invoke(target, aguments); ++this.currentBeforeInterceptorIndex; } catch (Exception e) { e.printStackTrace(); } } int methodAfterIndex = afterInterceptorsAndDynamicMethodMatchers.size() - 1; if (methodAfterIndex > this.currentAfterInterceptorIndex){ // 这里就是将advice封装成MethodInterceptor,从链表中一个一个执行 Object interceptorOrInterceptionAdvice = this.afterInterceptorsAndDynamicMethodMatchers.get(++this.currentAfterInterceptorIndex); // 这里将ReflectiveMethodInvocation自己用传入了,是一个递归调用 return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } return obj; } @Override public Method getMethod() { return method; } @Override public Object getThis() { return target; } @Override public Object[] getArguments() { return aguments; } }
二、定义创建代理对象的委托
public interface AopProxy { // 获取代理对象 Object getProxy(); }
三、实现JDK的动态代理
public class JdkDynamicAopProxy implements AopProxy, InvocationHandler { private AdvisedSupport advisedSupport; public JdkDynamicAopProxy(AdvisedSupport advisedSupport){ this.advisedSupport = advisedSupport; } @Override public Object getProxy() { return Proxy.newProxyInstance(this.getClass().getClassLoader(), advisedSupport.getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { MethodInvocation invocation; List<Object> beforeChain = this.advisedSupport.getBeforeInterceptorsAndDynamicInterceptionAdvice(); List<Object> afterChain = this.advisedSupport.getAfterInterceptorsAndDynamicInterceptionAdvice(); invocation = new ReflectiveMethodInvocation(proxy, advisedSupport.getTarget(), method, args, beforeChain, afterChain); return invocation.proceed(); } }
四、定义一个工厂(因为时间有限,所以只实现了一个关于JDK的动态代理,感兴趣的小伙伴可以自行补上CGLIB的,后面有时间再加上)
public class DefaultAopproxyFactory implements AopProxyFactory { @Override public AopProxy createAopProxy(AdvisedSupport advisedSupport) { Object target = advisedSupport.getTarget(); if (target.getClass().getInterfaces().length > 0) { return new JdkDynamicAopProxy(advisedSupport); } else { // cglib return null; } } }
到这里,整个AOP基本算是实现了,下面就写个测试类进行测试一下,看看是否生效
public interface ADemo { void send(); }
public class ADemoImpl implements ADemo { @Override public void send() { System.out.println("........................."); } }
public class TestAOP { public static void main(String[] args) { DefaultAopproxyFactory factory = new DefaultAopproxyFactory(); ADemo ia = new ADemoImpl(); AdvisedSupport advisedSupport = new AdvisedSupport(); advisedSupport.setTarget(ia); Advice advice1 = new MethodAdvice() { @Override public void sendMsg(Method method, Object[] args, Object target) { System.out.println("1----------------"); } }; Advice advice2 = new MethodAdvice() { @Override public void sendMsg(Method method, Object[] args, Object target) { System.out.println("2----------------"); } }; List<Advisor> advisors = new ArrayList<>(); Advisor advisor1 = new DefaultPointcutAdvisor(null, advice1, "0"); Advisor advisor2 = new DefaultPointcutAdvisor(null, advice2, "1"); advisors.add(advisor1); advisors.add(advisor2); advisedSupport.setAdvisors(advisors); // advisedSupport.addAdvice(advice); List<Class<?>> interfaces = new ArrayList<>(); interfaces.add(ADemo.class); advisedSupport.addInterface(interfaces); AopProxy aopProxy = factory.createAopProxy(advisedSupport); ADemo proxyObj = (ADemo) aopProxy.getProxy(); proxyObj.send(); } }
测试结果:
最后附上项目的完整地址,欢迎感兴趣的小伙伴留言讨论
https://github.com/hyqlb/bin.git