博客园 首页 私信博主 显示目录 隐藏目录 管理 动画

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

posted @ 2022-07-30 15:46  疯狂打码  阅读(135)  评论(0编辑  收藏  举报