Spring AOP 之二:Pointcut註解表達式

簡介

Spring AOP概述中咱們重點注意的是AOP的總體流程和Advice,簡化了一些其餘的東西,其中就有一些對靈活應用Spring AOP很重要的知識點,例如Pointcut表達式,下面就介紹一下Spring AOP的Pointcut表達式。java

若是你對Pointcut表達式的做用還不是很瞭解,能夠先看一下Spring AOP概述,也能夠先了解一下匹配規則,後面會有一些具體的例子來幫助理解。git

咱們使用最多的就是execution表示了,下面就從execution表達式開始介紹吧。github

注意:把designators翻譯爲表達式也許不太合適,因此沒必要糾結這個問題,只須要知道在看到Spring AOP中的designators知道對應的是個什麼東西就能夠了。管它是表達式仍是指示器只是一個代稱而已。spring

execution表達式

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

上面的就是execution表達式的格式,execution匹配的就是鏈接點(Joinpoint,通常是方法),看上面的表達式execution是固定的,方法的修飾符是可選的,返回類型是必須的,定義的全限類型也是可選的,名稱是必須的,參數是必須的,這些均可以使用通配符。express

任何的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個基本是等效的。maven

有且只有一個Serializable參數的方法

args(java.io.Serializable)

只要這個參數實現了java.io.Serializable接口就能夠,無論是java.io.Serializable仍是Integer,仍是String均可以。ide

目標(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中的全部方法。this

bean名字能匹配

bean(*Impl)

bean名字匹配*Impl的bean中的全部方法。.net

實例

這個實例是對Spring AOP概述中介紹的實例進行了擴展。固然下面給的實例也能夠獨立測試,最好是一個一個測試觀察輸出了驗證,多個輸出結果不夠直觀。

下面的圖片是項目工程目錄結構:

工程目錄結構

下面的代碼列表由於比較多,能夠在後面找到完整的代碼工程代碼的附件連接,由於其餘一些緣由沒有放到github或者碼雲上,能夠直接下載附件解壓使用maven方式導入。

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(){}
    
    
}
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();
    }

}

參考

完整工程代碼

Spring AOP 之一:基本概念與流程

Spring AOP 之二:Pointcut註解表達式

Spring AOP 之三:通知(Advice)方法參數

相關文章
相關標籤/搜索