Spring AOP编程官方文档解读之另类切面Advisor


Spring AOP编程官方文档解读目录



前言

从前面几章我们不难看出 Aspect(切面) = PointCut(切入点)+ Advice(增强)。所谓的增强也就是在被增强的方法的前后执行特定的逻辑。对应的类被代理了。如下图所示:
在这里插入图片描述
仔细看一下上图,会发现增强的对象里面包含有advisorsadvisorArray这样的信息。那这些都是什么信息呢?恰巧在Spring AOP中,存在这样的一个接口org.springframework.aop.Advisor。这个接口就包含有两个方法:

public interface Advisor {

	Advice getAdvice();

	boolean isPerInstance();
}

从第一个方法不难看出,这个一个提供Advice增强的的接口。然后再看看这个接口的两个子接口
在这里插入图片描述
尤其是org.springframework.aop.PointcutAdvisor,是不是有点想法了?PointcutAdvisor = Pointcut + Advice,这是不是就和Aspect一模一样了?本文就通过使用Advisor的方式来达到之前Aspect所达到的效果。

An advisor is like a small self-contained aspect that has a single piece of advice. The advice itself is represented by a bean, and must implement one of the advice interfaces。

Base interface holding AOP advice (action to take at a joinpoint) and a filter determining the applicability of the advice (such as a pointcut). This interface is not for use by Spring users, but to allow for commonality in support for different types of advice.

Spring AOP is based around around advice delivered via method interception, compliant with the AOP Alliance interception API. The Advisor interface allows support for different types of advice, such as before and after advice, which need not be implemented using interception.


自定义Advisor

package com.example.aop.anno.aspects;

import org.aopalliance.aop.Advice;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.Pointcut;
import org.springframework.aop.PointcutAdvisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Arrays;

@Component
public class BeforePointcutAdvisor implements PointcutAdvisor {
    @Override
    public Pointcut getPointcut() {
        AspectJExpressionPointcut aspectJExpressionPointcut = new AspectJExpressionPointcut();
        aspectJExpressionPointcut.setExpression("execution(public * *(..)) && within(com.example.aop.anno.service..*)");
        return aspectJExpressionPointcut;
    }

    @Override
    public Advice getAdvice() {
        return new MethodBeforeAdvice() {
            @Override
            public void before(Method method, Object[] args, Object target) throws Throwable {
                System.out.println("------------方法 " + method.getName() + " 增强逻辑-----------");
                System.out.println("target = " + target);
                System.out.println("args = " + Arrays.toString(args));
            }
        };
    }

    @Override
    public boolean isPerInstance() {
        return false;
    }
}

运行结果如下

"C:\Program Files\Java\jdk1.8.0_92\bin\java.exe" "-javaagent:D:\Program Files\JetBrains\IntelliJ IDEA 2019.3.1\lib\idea_rt.jar=12142:D:\Program Files\JetBrains\IntelliJ IDEA 2019.3.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_92\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\rt.jar;D:\springboot\gs-managing-transactions-master\complete\target\classes;D:\maven\repo\org\springframework\spring-core\4.3.27.RELEASE\spring-core-4.3.27.RELEASE.jar;D:\maven\repo\commons-logging\commons-logging\1.2\commons-logging-1.2.jar;D:\maven\repo\org\springframework\spring-tx\4.3.27.RELEASE\spring-tx-4.3.27.RELEASE.jar;D:\maven\repo\org\springframework\spring-beans\4.3.27.RELEASE\spring-beans-4.3.27.RELEASE.jar;D:\maven\repo\org\springframework\spring-context-support\4.3.27.RELEASE\spring-context-support-4.3.27.RELEASE.jar;D:\maven\repo\org\springframework\spring-context\4.3.27.RELEASE\spring-context-4.3.27.RELEASE.jar;D:\maven\repo\org\springframework\spring-expression\4.3.27.RELEASE\spring-expression-4.3.27.RELEASE.jar;D:\maven\repo\org\springframework\spring-aop\4.3.27.RELEASE\spring-aop-4.3.27.RELEASE.jar;D:\maven\repo\org\springframework\spring-aspects\4.3.27.RELEASE\spring-aspects-4.3.27.RELEASE.jar;D:\maven\repo\org\aspectj\aspectjweaver\1.8.9\aspectjweaver-1.8.9.jar" com.example.aop.anno.SpringStartMain
九月 15, 2020 11:39:22 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@20ad9418: startup date [Tue Sep 15 23:39:22 CST 2020]; root of context hierarchy
------------方法 add 增强逻辑-----------
target = com.example.aop.anno.service.impl.DealServiceImpl@36902638
args = [Order{orderId=1600184364312, name='HuaWei', price=5998.00}, User{name='Lisa', age=18}]
九月 15, 2020 11:39:24 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
信息: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@20ad9418: startup date [Tue Sep 15 23:39:22 CST 2020]; root of context hierarchy

Process finished with exit code 0

不难看出,与前面通过Aspect定义的结果没什么差别。

还可以采用以下的方式

package com.example.aop.anno.aspects;

import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.Pointcut;
import org.springframework.aop.PointcutAdvisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.StaticMethodMatcherPointcut;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Arrays;

@Component
public class BeforePointcutAdvisor implements PointcutAdvisor {
    @Override
    public Pointcut getPointcut() {
        return new StaticMethodMatcherPointcut() {
            @Override
            public boolean matches(Method method, Class<?> targetClass) {
                Class<?>[] interfaces = targetClass.getInterfaces();
                for (Class<?> anInterface : interfaces) {
                    if (anInterface.getName().startsWith("com.example.aop.anno.service")) {
                        return true;
                    }
                }
                return false;
            }
        };
    }

    @Override
    public Advice getAdvice() {
        return new MethodInterceptor() {
            @Override
            public Object invoke(MethodInvocation invocation) throws Throwable {
                System.out.println("------------方法 " + invocation.getMethod().getName() + " 增强逻辑-----------");
                System.out.println("this = " + invocation.getThis());
                System.out.println("args = " + Arrays.toString(invocation.getArguments()));
                return invocation.proceed();
            }
        };
    }

    @Override
    public boolean isPerInstance() {
        return false;
    }
}

结果如下

"C:\Program Files\Java\jdk1.8.0_92\bin\java.exe" "-javaagent:D:\Program Files\JetBrains\IntelliJ IDEA 2019.3.1\lib\idea_rt.jar=12282:D:\Program Files\JetBrains\IntelliJ IDEA 2019.3.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_92\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\rt.jar;D:\springboot\gs-managing-transactions-master\complete\target\classes;D:\maven\repo\org\springframework\spring-core\4.3.27.RELEASE\spring-core-4.3.27.RELEASE.jar;D:\maven\repo\commons-logging\commons-logging\1.2\commons-logging-1.2.jar;D:\maven\repo\org\springframework\spring-tx\4.3.27.RELEASE\spring-tx-4.3.27.RELEASE.jar;D:\maven\repo\org\springframework\spring-beans\4.3.27.RELEASE\spring-beans-4.3.27.RELEASE.jar;D:\maven\repo\org\springframework\spring-context-support\4.3.27.RELEASE\spring-context-support-4.3.27.RELEASE.jar;D:\maven\repo\org\springframework\spring-context\4.3.27.RELEASE\spring-context-4.3.27.RELEASE.jar;D:\maven\repo\org\springframework\spring-expression\4.3.27.RELEASE\spring-expression-4.3.27.RELEASE.jar;D:\maven\repo\org\springframework\spring-aop\4.3.27.RELEASE\spring-aop-4.3.27.RELEASE.jar;D:\maven\repo\org\springframework\spring-aspects\4.3.27.RELEASE\spring-aspects-4.3.27.RELEASE.jar;D:\maven\repo\org\aspectj\aspectjweaver\1.8.9\aspectjweaver-1.8.9.jar" com.example.aop.anno.SpringStartMain
九月 15, 2020 11:51:55 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@20ad9418: startup date [Tue Sep 15 23:51:55 CST 2020]; root of context hierarchy
------------方法 add 增强逻辑-----------
this = com.example.aop.anno.service.impl.DealServiceImpl@3b2cf7ab
args = [Order{orderId=1600185117718, name='HuaWei', price=5998.00}, User{name='Lisa', age=18}]
九月 15, 2020 11:51:57 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
信息: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@20ad9418: startup date [Tue Sep 15 23:51:55 CST 2020]; root of context hierarchy

Process finished with exit code 0


总结

Advisor属于Spring AOP的范畴,是对AspectJ的补充。也同样可以充分利用AspectJ的切点表达式。有一点需要注意下,就是Aspect类中可以定义多个Advice,而Advisor真能包含一个。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lang20150928

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值