zoukankan      html  css  js  c++  java
  • Spring AOP 之二:Pointcut注解表达式

    简介
    在Spring AOP概述中我们重点注意的是AOP的整体流程和Advice,简化了一些其他的东西,其中就有一些对灵活应用Spring AOP很重要的知识点,例如Pointcut表达式,下面就介绍一下Spring AOP的Pointcut表达式。

    如果你对Pointcut表达式的作用还不是很了解,可以先看一下Spring AOP概述,也可以先了解一下匹配规则,后面会有一些具体的例子来帮助理解。
    我们使用最多的就是execution表示了,下面就从execution表达式开始介绍吧。

    注意:把designators翻译为表达式也许不太合适,所以不必纠结这个问题,只需要知道在看到Spring AOP中的designators知道对应的是个什么东西就可以了。管它是表达式还是指示器只是一个代称而已。

    execution表达式

    execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern)
    throws-pattern?)
    

    上面的就是execution表达式的格式,execution匹配的就是连接点(Joinpoint,一般是方法),看上面的表达式execution是固定的,方法的修饰符是可选的,返回类型是必须的,定义的全限类型也是可选的,名称是必须的,参数是必须的,这些都可以使用通配符。

    任何的public方法

    execution(public * *(..))
    

    以set开始的方法

    execution(* set*(..))
    

    定义在cn.freemethod.business.pack.Say接口中的方法

    execution(* cn.freemethod.business.pack.Say.*(..))
    

    任何cn.freemethod.business包中的方法

    execution(* cn.freemethod.business.*.*(..))
    

    任何定义在com.xyz.service包或者其子包中的方法

    execution(* cn.freemethod.business..*.*(..))
    

    其他表达式

    任何在com.xyz.service包中的方法

    within(com.xyz.service.*)
    

    任何定义在com.xyz.service包或者其子包中的方法

    within(com.xyz.service..*)
    

    任何实现了com.xyz.service.AccountService接口中的方法

    this(com.xyz.service.AccountService)
    

    任何目标对象实现了com.xyz.service.AccountService的方法

    target(com.xyz.service.AccountService)
    

    一般情况下代理类(Proxy)和目标类(Target)都实现了相同的接口,所以上面的2个基本是等效的。


    有且只有一个Serializable参数的方法

    args(java.io.Serializable)
    

    只要这个参数实现了java.io.Serializable接口就可以,不管是java.io.Serializable还是Integer,还是String都可以。

    目标(target)使用了@Transactional注解的方法

    @target(org.springframework.transaction.annotation.Transactional)
    

    目标类(target)如果有Transactional注解中的所有方法

    @within(org.springframework.transaction.annotation.Transactional)
    

    任何方法有Transactional注解的方法

    @annotation(org.springframework.transaction.annotation.Transactional)
    

    有且仅有一个参数并且参数上类型上有Transactional注解

    @args(org.springframework.transaction.annotation.Transactional)
    

    注意是参数类型上有Transactional注解,而不是方法的参数上有注解。

    -- bean的名字为tradeService中的方法

     bean(simpleSay)
     bean名字为simpleSay中的所有方法。
    

    -- bean名字能匹配

    bean(*Impl)
    bean名字匹配*Impl的bean中的所有方法。
    

    实例
    这个实例是对Spring AOP概述中介绍的实例进行了扩展。当然下面给的实例也可以独立测试,最好是一个一个测试观察输出了验证,多个输出结果不够直观。
    下面的图片是项目工程目录结构:

    下面的代码列表因为比较多,只能展示部分代码。

    --OtherPointcutAspect:

    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.Aspect;
    import org.springframework.stereotype.Component;

    @Component
    @Aspect
    public class OtherPointcutAspect {

    // @After("cn.freemethod.pointcut.OtherPointcut.argsSerializable()")
    public void argsSerialize(){
    System.out.println("OtherPointcutAspect argsSerialize after...");
    }

    // @After("cn.freemethod.pointcut.OtherPointcut.inBusinessPackage()")
    public void inBusinessPackage(){
    System.out.println("OtherPointcutAspect inBusinessPackage after...");
    }

    // @After("cn.freemethod.pointcut.OtherPointcut.inBusinessOrSubPackage()")
    public void inBusinessOrSubPackage(){
    System.out.println("OtherPointcutAspect inBusinessOrSubPackage after...");
    }

    // @After("cn.freemethod.pointcut.OtherPointcut.proxyImplementHaveResultBusinessInteferce()")
    public void proxyImplementHaveResultBusinessInteferce(){
    System.out.println("OtherPointcutAspect proxyImplementHaveResultBusinessInteferce after...");
    }

    // @After("cn.freemethod.pointcut.OtherPointcut.targetImplementBusinessInteferce()")
    public void targetImplementBusinessInteferce(){
    System.out.println("OtherPointcutAspect targetImplementBusinessInteferce after...");
    }

    // @After("cn.freemethod.pointcut.OtherPointcut.targetHaveTransactional()")
    public void targetHaveTransactional(){
    System.out.println("OtherPointcutAspect targetHaveTransactional after...");
    }

    // @After("cn.freemethod.pointcut.OtherPointcut.targetDeclareHaveTransactional()")
    public void targetDeclareHaveTransactional(){
    System.out.println("OtherPointcutAspect targetDeclareHaveTransactional after...");
    }

    // @After("cn.freemethod.pointcut.OtherPointcut.methodHaveTransactional()")
    public void methodHaveTransactional(){
    System.out.println("OtherPointcutAspect methodHaveTransactional after...");
    }

    @After("cn.freemethod.pointcut.OtherPointcut.argsHaveValueAnnotation()")
    public void argsHaveTransactional(){
        System.out.println("OtherPointcutAspect argsHaveValueAnnotation after...");
    }
    

    // @After("cn.freemethod.pointcut.OtherPointcut.beanName()")
    public void beanName(){
    System.out.println("OtherPointcutAspect beanName after...");
    }

    // @After("cn.freemethod.pointcut.OtherPointcut.matchBeanName()")
    public void matchBeanName(){
    System.out.println("OtherPointcutAspect matchBeanName after...");
    }

    }

    上面是一个测试Pointcut表达式的切面,很多Advice都注释了,请为了从输出中直观的了解Pointcut表达式匹配到了什么方法(Joinpoint),请根据自己的需要测试的Pointcut表达式取消添加注释。

    --ExecutionPointcutAspect:

    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.springframework.stereotype.Component;

    @Component
    @Aspect
    public class ExecutionPointcutAspect {

    @Before("cn.freemethod.pointcut.ExecutionPointcut.allPublicMethod()")
    public void allPublicBefore(){
        System.out.println("PointcutExpressionAspect allPublicBefore...");
    }
    
    @After("cn.freemethod.pointcut.ExecutionPointcut.allStartSayMethod()")
    public void sayAfter(){
        System.out.println("PointcutExpressionAspect sayAfter...");
    }
    
    @AfterReturning("cn.freemethod.pointcut.ExecutionPointcut.allInSayInterfaceMethod()")
    public void allInSayInterfaceMethod(){
        System.out.println("PointcutExpressionAspect allInSayInterfaceMethod...");
    }
    
    @Before("cn.freemethod.pointcut.ExecutionPointcut.allInBusinessPackage()")
    public void allInBusinessPackageBefore(){
        System.out.println("PointcutExpressionAspect all business before...");
    }
    
    @After("cn.freemethod.pointcut.ExecutionPointcut.allInBusinessOrSubPackage()")
    public void allallInBusinessOrSubPackageAfter(){
        System.out.println("PointcutExpressionAspect allallInBusinessOrSubPackageAfter...");
    }
    

    }

    ---ParamBean:

    import org.springframework.transaction.annotation.Transactional;

    @Transactional
    public class ParamBean {

    }

    --HaveResultBusinessImpl:

    import org.springframework.stereotype.Service;

    import cn.freemethod.business.HaveResultBusiness;

    @Service
    public class HaveResultBusinessImpl implements HaveResultBusiness {

    @Override
    public Integer getResult(Integer div) {
        System.out.println("HaveResultBusinessImpl getResult");
        Integer result = 100 / div;
        return result;
    }
    

    }

    --IOtherPointcutImpl:

    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;

    import cn.freemethod.bean.ParamBean;
    import cn.freemethod.business.pack.IOtherPointcut;

    @Transactional
    @Service
    public class IOtherPointcutImpl implements IOtherPointcut {

    @Override
    public Integer printInteger(Integer arg) {
        System.out.println("IOtherPointcutImpl printInteger");
        return arg;
    }
    
    
    @Override
    public void withAnotationParam(ParamBean arg) {
        System.out.println("IOtherPointcutImpl withAnotationParam");
    }
    

    }

    --SimpleSay:

    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;

    import cn.freemethod.business.pack.Say;

    @Transactional
    @Service
    public class SimpleSay implements Say {

    @Override
    public String sayChiness(String name) {
        String result = "你好:" + name;
        System.out.println(result);
        return result;
    }
    
    @Override
    public String sayEnglish(String name) {
        String result = "Hello " + name;
        System.out.println(result);
        return result;
    }
    
    @Transactional
    @Override
    public String whatSay() {
        System.out.println("what say");
        return "what say";
    }
    

    }

    --IOtherPointcut:

    import cn.freemethod.bean.ParamBean;

    public interface IOtherPointcut {

    Integer printInteger(Integer arg);
    
    void withAnotationParam(ParamBean arg);
    

    }

    --Say:

    public interface Say {

    String sayChiness(String name);
    
    String sayEnglish(String name);
    
    String whatSay();
    

    }

    --HaveResultBusiness:

    public interface HaveResultBusiness {

    Integer getResult(Integer div);
    

    }

    --AspectConfig:

    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.EnableAspectJAutoProxy;

    @Configuration
    @EnableAspectJAutoProxy
    @ComponentScan(basePackages = {"cn.freemethod"})
    public class AspectConfig {

    }

    --ExecutionPointcut:

    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;

    @Aspect
    public class ExecutionPointcut {

    @Pointcut("execution(public * *(..))")
    public void allPublicMethod(){}
    
    @Pointcut("execution(* say*(..))")
    public void allStartSayMethod(){}
    
    @Pointcut("execution(* cn.freemethod.business.pack.Say.*(..))")
    public void allInSayInterfaceMethod(){}
    
    @Pointcut("execution(* cn.freemethod.business.*.*(..))")
    public void allInBusinessPackage(){}
    
    @Pointcut("execution(* cn.freemethod.business..*.*(..))")
    public void allInBusinessOrSubPackage(){}
    

    }

    --OtherPointcut :

    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;

    @Aspect
    public class OtherPointcut {

    @Pointcut("within(cn.freemethod.business.impl.*)")
    public void inBusinessPackage(){}
    
    @Pointcut("within(cn.freemethod.business..*)")
    public void inBusinessOrSubPackage(){}
    
    @Pointcut("this(cn.freemethod.business.HaveResultBusiness)")
    public void proxyImplementHaveResultBusinessInteferce(){}
    
    @Pointcut("target(cn.freemethod.business.HaveResultBusiness)")
    public void targetImplementBusinessInteferce(){}
    
    @Pointcut("args(java.io.Serializable)")
    

    // @Pointcut("args(java.lang.Integer)")
    public void argsSerializable(){}

    @Pointcut("@target(org.springframework.transaction.annotation.Transactional)")
    public void targetHaveTransactional(){}
    
    @Pointcut("@within(org.springframework.transaction.annotation.Transactional)")
    public void targetDeclareHaveTransactional(){}
    
    @Pointcut("@annotation(org.springframework.transaction.annotation.Transactional)")
    public void methodHaveTransactional(){}
    
    @Pointcut("@args(org.springframework.transaction.annotation.Transactional)")
    public void argsHaveValueAnnotation(){}
    
    @Pointcut("bean(simpleSay)")
    public void beanName(){}
    
    @Pointcut("bean(*Impl)")
    public void matchBeanName(){}
    

    }

    --AnnotationConfigStart:

    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.context.support.AbstractApplicationContext;

    import cn.freemethod.business.HaveResultBusiness;
    import cn.freemethod.business.pack.Say;
    import cn.freemethod.config.AspectConfig;

    public class AnnotationConfigStart {

    public static void main(String[] args) {
        AbstractApplicationContext  context = new AnnotationConfigApplicationContext(AspectConfig.class);
        HaveResultBusiness haveResultBusiness = context.getBean(HaveResultBusiness.class);
        haveResultBusiness.getResult(100);
        Say say = context.getBean(Say.class);
        say.sayChiness("tim");
        say.sayEnglish("tim");
        say.whatSay();
        context.close();
    }
    

    }

    --PointcutExpressionStart:

    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.context.support.AbstractApplicationContext;

    import cn.freemethod.bean.ParamBean;
    import cn.freemethod.business.HaveResultBusiness;
    import cn.freemethod.business.pack.IOtherPointcut;
    import cn.freemethod.business.pack.Say;
    import cn.freemethod.config.AspectConfig;

    public class PointcutExpressionStart {

    public static void main(String[] args) {
        AbstractApplicationContext  context = new AnnotationConfigApplicationContext(AspectConfig.class);
        IOtherPointcut iOtherPointcut = context.getBean(IOtherPointcut.class);
        iOtherPointcut.printInteger(new Integer(10));
        iOtherPointcut.withAnotationParam(new ParamBean());
        
        HaveResultBusiness haveResultBusiness = context.getBean(HaveResultBusiness.class);
        haveResultBusiness.getResult(100);
        
        Say say = context.getBean(Say.class);
        say.sayChiness("tim");
        say.sayEnglish("tim");
        say.whatSay();
        context.close();
    }
    

    }

  • 相关阅读:
    Java开发中的23种设计模式详解(转)
    主表和从表
    MyBatis开发中解决返回字段不全的问题
    个人常用配置文件解析
    SpringMVC+MyBatis开发中指定callSettersOnNulls,可解决返回字段不全的问题
    mybatis之sql执行有数据但返回结果为null
    Hadoop window win10 基础环境搭建(2.8.1)
    什么水平算精通C++ Builder?
    Delphi中取得汉字的首字母(十分巧妙)
    全部的Windows消息对应值
  • 原文地址:https://www.cnblogs.com/miniSimple/p/12375962.html
Copyright © 2011-2022 走看看