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

}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM