栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

使用TDD手写AOP代码

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

使用TDD手写AOP代码

github地址:GitHub - CodePpoi/spring-code

学习了TDD测试驱动,觉得得拿个东西来练手,想起之前写的AOP一直写不出来,就用测试驱动的方法来完成,没想到还真写出来了。

首先记录自己写测试的时候,列出的代办事项,后面的d表示done,完成的意思

//调用时获得的是代理对象
//先执行实际方法d
//後执行代理对象的方法 before + 1 d
//把代理对象改为JDK代理 d
//调用测试通过 d
//把before和after移动到beforeAdvice和After d
//调用BeforeAdvice和AfterAdvice d
//调用BeforeAdvice和AfterAdvice interceptor d
//用Chain调用 interceptor d
//用JDK代理调用chain d
//使用注解的方式添加advisior buildAdvisor
//添加Before和After注解 

//before advice和 before联系起来
//advisior和before advice联系起来 add
//advice和intecep 联系起来 d

测试通过打印输出来完成,代码

public static void main(String[] args) throws Throwable {

        AnnotationAOPProxyCreator  a = new AnnotationAOPProxyCreator();
        final BizAImpl bizAImpl = new BizAImpl();
        List advisors = a.buildAdvisors();
                //buildAdvisors(BizAImpl.class.getDeclaredMethod("doSomething"));
        JdkDynamicProxyImpl jdkDynamicProxy = new JdkDynamicProxyImpl(advisors, bizAImpl);
        jdkDynamicProxy.invoke(bizAImpl, BizAImpl.class.getDeclaredMethod("doSomething"), null);

        //final IBizA newBizA = (IBizA) createProxy(bizAImpl);
        //newBizA.doSomething();
    }

对应的输出为:

 

其实代理,就是给原对象加了一层List advisors,

        List advisors = a.buildAdvisors();
                //buildAdvisors(BizAImpl.class.getDeclaredMethod("doSomething"));
        JdkDynamicProxyImpl jdkDynamicProxy = new JdkDynamicProxyImpl(advisors, bizAImpl);

那么到底是怎么加的呢,

private List getAdvisorsByAspect(Class class1) {
        List advisors = new ArrayList<>();
        for (Method method : getAdvisorMethods(class1)) {
            Advisor advisor = null;
            try {
                advisor = getAdvisor(method, class1.getAnnotation(Aspect.class));
            } catch (Exception e) {
                //e.printStackTrace();
            }
            if (advisor != null) {
                advisors.add(advisor);
            }
        }
        return advisors;
    }

首先通过getAdvisorMethods获取对应class的所有方法,然后调用getAdivsor

private Advisor getAdvisor(Method method, Object aspect) {
        Advisor advisor = null;
        Advice advice = getAdvice(method, aspect);
        if(advice == null) return advisor;
        advisor = new Advisor();
        advisor.setAspect((Aspect)aspect);
        advisor.setPointcut(getPointcut(method));
        advisor.setAdvice(advice);
        return advisor;
    }

这个方法里有设置advice,advice又是从getAdvice获取的:

private Advice getAdvice(Method method, Object aspect) {
        if(isBefore(method)) {
            return new BeforeAdvice(method, (Aspect) aspect);
        }

        if(isAfter(method)) {
            return new AfterAdvice(method, (Aspect) aspect);
        }

        return null;
    }

也就顺其自然的引入了BeforeAdvice,上面的代码就是把@MyBefore和Advice关联起来,那么标注了@MyBefore的方法也就会执行,intecept方法

public class BeforeAdvice extends Advice implements MyMethodInterceptor {
    public BeforeAdvice(Method adviceMethod, Aspect aspect) {
        super(adviceMethod, aspect);
        // TODO Auto-generated constructor stub
    }



    public void before(final Object target, final Method method, final Object[] args) {
        this.invokeAspectMethod(target, method, args);
    }

    @Override
    public Object intercept(Method method, Object[] arguments, Object target, MethodInterceptorChain chain) {
        //before(target);
        //this.before(target, method, arguments);
        try {
            adviceMethod.invoke(new Logging(), arguments);//第一个参数必为对象实例
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return chain.intercept(method, arguments, target);
    }
}

那么intecept在哪执行:

@Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        MyMethodInterceptor[] iterceptors =
            AdvisorHelper.getMethodInterceptors(this.getAdvisors(), method);
        
        Object obj = new MethodInterceptorChain(iterceptors)
                        .intercept(method,args,proxy);
        return obj;
    }

就是在jdk代理执行invoke方法是,会先根据Adivsor获取一个拦截器组,然后顺着这个责任链,一步一步的调用下去,也就会执行到BeforeAdvice里面了。

TDD最常用的就是伪实现,也正是这个技巧让我成功实现了AOP,不然头都是晕的=.=

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/781687.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号