自己动手写一个spring之aop_2

发布时间:2026/7/31 18:39:22
自己动手写一个spring之aop_2 写在前面在这篇文章 中我们已经使得AOP有了雏形但是代理逻辑的执行还是硬编码的如下OverridepublicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{if(method.getName().equals(doAction)){System.out.println(-----通过jdk动态代理代理了类的doAction方法........);returnmethod.invoke(target,args);}returnnull;}当然这样做呢不能算错但是扩展性就要弱很多了在不同的业务场景中要做的内容不同该怎么办呢本文就一起来把这个问题解决了。1正文对于具体业务方法执行过程的干预我们可以抽象出一个增强的概念即增强业务方法本身的能力如开始没有性能统计的能力通过AOP就能增加这部分能力为此定义一个类似于标记的接口如下packagecom.hc.minispring.web.v7_aop.aop;/** * 切面概念接口更加具象化使用方法拦截器进行增强织入 */publicinterfaceAdvisor{MethodInterceptorgetMethodInterceptor();voidsetMethodInterceptor(MethodInterceptormethodInterceptor);}再来定义一个更加具体的拦截接口代表要通过拦截的方式来增强packagecom.hc.minispring.web.v7_aop.aop;/** * 基于拦截的抽象这里拦截也是一个抽象的概念并不限定于如何拦截 */publicinterfaceInterceptorextendsAdvice{}在定义一个更加具体的基于方法执行拦截的接口/** * 具体的基于方法的拦截也是我们实现AOP方法动态增强织入的关键 */publicinterfaceMethodInterceptorextendsInterceptor{/** * 增强逻辑执行invocation负责执行目标方法 * param invocation * return * throws Throwable */Objectinvoke(MethodInvocationinvocation)throwsThrowable;}当然MethodInterceptor的具体实现类要由用户来指定这里给出一个追踪方法执行过程的实现类以供测试使用当然仅仅是个例子了packagecom.hc.minispring.web.v7_aop.aop;/** * 方法调用追踪 */publicclassTracingInterceptorimplementsMethodInterceptor{publicObjectinvoke(MethodInvocationi)throwsThrowable{System.out.println(即将执行方法 i.getMethod());Objectreti.proceed();System.out.println(执行方法 i.getMethod() 成功*★,°*:.☆(▽)/$:*.°★* 。);returnret;}}为了能够更加明确的表达要做的事情再来定义一个类似于Advice不真正干活的接口Advisor切面抽象出的概念因为对方法执行的拦截就好像拦了一个面一样如下packagecom.hc.minispring.web.v7_aop.aop;/** * 切面概念接口更加具象化使用方法拦截器进行增强织入 */publicinterfaceAdvisor{MethodInterceptorgetMethodInterceptor();voidsetMethodInterceptor(MethodInterceptormethodInterceptor);}可以看出真正干活的还是MethodInterceptor给出实现类/** * 默认实现简单仅仅是维护了方法拦截器信息更多的是Advisor对于功能的表达语义 * 即更加形象化的存在并不做具体的工作 */publicclassDefaultAdvisorimplementsAdvisor{privateMethodInterceptormethodInterceptor;publicDefaultAdvisor(){}publicvoidsetMethodInterceptor(MethodInterceptormethodInterceptor){this.methodInterceptormethodInterceptor;}publicMethodInterceptorgetMethodInterceptor(){returnthis.methodInterceptor;}}接着就来改造现有的类了从生成代理类的FacotryBean入手这里是com.hc.minispring.aop.ProxyFactoryBean,修改如下packagecom.hc.minispring.aop;// .../** * 真正返回代理bean的工厂bean */publicclassProxyFactoryBeanimplementsFactoryBeanObject{// .../** 切面相关内容 **/privateStringinterceptorName;privateAdvisoradvisor;/** 切面相关内容 **/// ...protectedAopProxycreateAopProxy(){// System.out.println(----------createAopProxy for : target --------);// return getAopProxyFactory().createAopProxy(target);// 修改点创建代理类时增加advisor参数用来执行织入的增强逻辑returngetAopProxyFactory().createAopProxy(target,advisor);}// ...OverridepublicObjectgetObject()throwsException{// 修改点初始化切面initializeAdvisor();returngetSingletonInstance();}// 修改点privatesynchronizedvoidinitializeAdvisor(){Objectadvicenull;MethodInterceptorminull;try{// advice (MethodInterceptor) this.beanFactory.getBean(this.interceptorName);// 正常应该从容器中获取但是这里为了走通流程忽略这个次要矛盾了advicenewTracingInterceptor();// } catch (BeansException e) {}catch(Exceptione){e.printStackTrace();}advisornewDefaultAdvisor();// 给切面设置用户给定的方法拦截器即用户自定义的增强逻辑advisor.setMethodInterceptor((MethodInterceptor)advice);}// ...}advisor参数一路传最终传给负责真正干活的代理类JdkDynamicAopProxy,同时修改其逻辑使用methodinterceprot执行增强的织入逻辑packagecom.hc.minispring.aop;// ...publicclassJdkDynamicAopProxyimplementsAopProxy,InvocationHandler{Objecttarget;// 修改点增加切面Advisoradvisor;publicJdkDynamicAopProxy(Objecttarget,Advisoradvisor){this.targettarget;this.advisoradvisor;}OverridepublicObjectgetProxy(){ObjectobjProxy.newProxyInstance(JdkDynamicAopProxy.class.getClassLoader(),target.getClass().getInterfaces(),this);System.out.println(----------创建基于jdk的动态代理类成功 ---------obj);returnobj;}OverridepublicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{if(method.getName().equals(doAction)){Class?targetClass(target!null?target.getClass():null);// 修改点使用切面执行逻辑MethodInterceptorinterceptorthis.advisor.getMethodInterceptor();MethodInvocationinvocationnewReflectiveMethodInvocation(proxy,target,method,args,targetClass);returninterceptor.invoke(invocation);}returnnull;}}先来测试一下conrollerRequestMapping(/hello1746)// public String doTest(String name) {// public String doTest(/*HttpServletRequest request, HttpServletResponse response*/) {publicStringdoTest(/*HttpServletRequest request, HttpServletResponse response*/){System.out.println(action: action.getClass());action.doAction();returnindex;}}运行截至这里源码 。我们继续来优化。在很多时候我们可能只需要在方法执行前进行增强或者是在方法执行后进行增强。当然目前的方式也能够实现但是对于用户来说还是不够简洁并且也不够明确所以我们来进一步进行优化即分别定义执行前后的增强方法执行前后的增强方法执行前后的拦截如下4个接口2个类执行前的增强方法执行前的增强方法执行前的拦截/** * 前置增强 */publicinterfaceBeforeAdviceextendsAdvice{}/** * 方法前置增强 */publicinterfaceMethodBeforeAdviceextendsBeforeAdvice{voidbefore(Methodmethod,Object[]args,Objecttarget)throwsThrowable;}/** * 方法前置拦截器包装方法前置增强 */publicclassMethodBeforeAdviceInterceptorimplementsMethodInterceptor{privatefinalMethodBeforeAdviceadvice;publicMethodBeforeAdviceInterceptor(MethodBeforeAdviceadvice){this.adviceadvice;}OverridepublicObjectinvoke(MethodInvocationmi)throwsThrowable{// 方法执行前插入的逻辑由用户给出具体的实现this.advice.before(mi.getMethod(),mi.getArguments(),mi.getThis());// 目标方法执行returnmi.proceed();}}执行后的增强方法执行后的增强方法执行后的拦截/** * 后置增强 */publicinterfaceAfterAdviceextendsAdvice{}/** * 方法后置增强 */publicinterfaceAfterReturningAdviceextendsAfterAdvice{voidafterReturning(ObjectreturnValue,Methodmethod,Object[]args,Objecttarget)throwsThrowable;}publicclassAfterReturningAdviceInterceptorimplementsMethodInterceptor,AfterAdvice{privatefinalAfterReturningAdviceadvice;publicAfterReturningAdviceInterceptor(AfterReturningAdviceadvice){this.adviceadvice;}OverridepublicObjectinvoke(MethodInvocationmi)throwsThrowable{ObjectretValmi.proceed();this.advice.afterReturning(retVal,mi.getMethod(),mi.getArguments(),mi.getThis());returnretVal;}}修改proxyfactorybean的initAdvisor方法privatesynchronizedvoidinitializeAdvisor(){Objectadvicenull;MethodInterceptorminull;try{// advice (MethodInterceptor) this.beanFactory.getBean(this.interceptorName);// 正常应该从容器中获取但是这里为了走通流程忽略这个次要矛盾了// advice new TracingInterceptor();try{// advice new TracingInterceptor();advicenewMethodBeforeAdvice(){Overridepublicvoidbefore(Methodmethod,Object[]args,Objecttarget)throwsThrowable{System.out.println(method: method.getName() before execute***********!!!);}};}catch(Exceptione){e.printStackTrace();}if(adviceinstanceofBeforeAdvice){minewMethodBeforeAdviceInterceptor((MethodBeforeAdvice)advice);}elseif(adviceinstanceofAfterAdvice){minewAfterReturningAdviceInterceptor((AfterReturningAdvice)advice);}elseif(adviceinstanceofMethodInterceptor){mi(MethodInterceptor)advice;}advisornewDefaultAdvisor();advisor.setMethodInterceptor(mi);// } catch (BeansException e) {}catch(Exceptione){e.printStackTrace();}// advisor new DefaultAdvisor();// // 给切面设置用户给定的方法拦截器即用户自定义的增强逻辑// advisor.setMethodInterceptor((MethodInterceptor) advice);}根据不同的类型增强进行不同的处理这里作为测试写死了一个方法前置增强运行测试截至这里源码 。spring中还有环绕通知但基本上一个道理。写在后面参考文章列表