Spring AOP
AOP
execution
: 用于匹配方法执行的连接点。这是使用Spring AOP时要使用的主要切入点指示符。within
: 将匹配限制为某些类型内的连接点(使用Spring AOP时,在匹配类型内声明的方法的执行)。this
: 限制匹配到连接点(使用Spring AOP时方法的执行),其中bean引用(Spring AOP代理)是给定类型的实例。target
: 限制匹配到连接点(使用Spring AOP时方法的执行)的匹配,其中目标对象(正在代理的应用程序对象)是给定类型的实例。args
: 限制匹配到连接点(使用Spring AOP时方法的执行)的匹配,其中参数是给定类型的实例@target
: 限制匹配到连接点(使用Spring AOP时方法的执行)的匹配,其中执行对象的类具有给定类型的注释。@args
: 限制匹配的连接点(使用Spring AOP时方法的执行),其中传递的实际参数的运行时类型具有给定类型的注释。@within
: 限制匹配到具有给定注释的类型内的连接点(使用Spring AOP时,使用给定注释的类型中声明的方法的执行)。@annotation
: 将匹配点限制为连接点的主题(在Spring AOP中执行的方法)具有给定注释的连接点。
.Java
@Pointcut("execution(* transfer(..))") // the pointcut expression
private void anyOldTransfer() {} // the pointcut signature
.Java
@Pointcut("execution(public * \*(..))")
private void anyPublicOperation() {} // <1>
@Pointcut("within(com.xyz.someapp.trading..*)")
private void inTrading() {} // <2>
@Pointcut("anyPublicOperation() && inTrading()")
private void tradingOperation() {} // <3>
.Java
package com.xyz.someapp;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class SystemArchitecture {
/**
* 如果以com.xyz.someapp.web包或该包下的任何子包中的类型定义该方法,则该连接点位于Web层中。
*/
@Pointcut("within(com.xyz.someapp.web..*)")
public void inWebLayer() {}
/**
* A join point is in the service layer if the method is defined
* in a type in the com.xyz.someapp.service package or any sub-package
* under that.
*/
@Pointcut("within(com.xyz.someapp.service..*)")
public void inServiceLayer() {}
/**
* A join point is in the data access layer if the method is defined
* in a type in the com.xyz.someapp.dao package or any sub-package
* under that.
*/
@Pointcut("within(com.xyz.someapp.dao..*)")
public void inDataAccessLayer() {}
/**
* A business service is the execution of any method defined on a service
* interface. This definition assumes that interfaces are placed in the
* "service" package, and that implementation types are in sub-packages.
*
* If you group service interfaces by functional area (for example,
* in packages com.xyz.someapp.abc.service and com.xyz.someapp.def.service) then
* the pointcut expression "execution(* com.xyz.someapp..service.*.*(..))"
* could be used instead.
*
* Alternatively, you can write the expression using the 'bean'
* PCD, like so "bean(*Service)". (This assumes that you have
* named your Spring service beans in a consistent fashion.)
*/
@Pointcut("execution(* com.xyz.someapp..service.*.*(..))")
public void businessService() {}
/**
* A data access operation is the execution of any method defined on a
* dao interface. This definition assumes that interfaces are placed in the
* "dao" package, and that implementation types are in sub-packages.
*/
@Pointcut("execution(* com.xyz.someapp.dao.*.*(..))")
public void dataAccessOperation() {}
}
.Java
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class BeforeExample {
@Before("com.xyz.myapp.SystemArchitecture.dataAccessOperation()")
public void doAccessCheck() {
// ...
}
}
.Java
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.AfterReturning;
@Aspect
public class AfterReturningExample {
@AfterReturning(
pointcut="com.xyz.myapp.SystemArchitecture.dataAccessOperation()",
returning="retVal")
public void doAccessCheck(Object retVal) {
// ...
}
}
.Java
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.AfterThrowing;
@Aspect
public class AfterThrowingExample {
@AfterThrowing(
pointcut="com.xyz.myapp.SystemArchitecture.dataAccessOperation()",
throwing="ex")
public void doRecoveryActions(DataAccessException ex) {
// ...
}
}
.Java
@Before("com.xyz.myapp.SystemArchitecture.dataAccessOperation() && args(account,..)")
public void validateAccount(Account account) {
// ...
}
.Java
@Pointcut("com.xyz.myapp.SystemArchitecture.dataAccessOperation() && args(account,..)")
private void accountDataAccessOperation(Account account) {}
@Before("accountDataAccessOperation(account)")
public void validateAccount(Account account) {
// ...
}
.Java
@Before("com.xyz.lib.Pointcuts.anyPublicMethod() && @annotation(auditable)")
public void audit(Auditable auditable) {
AuditCode code = auditable.value();
// ...
}
Spring AOP可以处理类声明和方法参数中使用的泛型。假设您具有如下通用类型:
.Java
@Before("execution(* ..Sample+.sampleGenericMethod(*)) && args(param)")
public void beforeSampleMethod(MyType param) {
// Advice implementation
}
.Java
@Aspect
public class UsageTracking {
@DeclareParents(value="com.xzy.myapp.service.*+", defaultImpl=DefaultUsageTracked.class)
public static UsageTracked mixin;
@Before("com.xyz.myapp.SystemArchitecture.businessService() && this(usageTracked)")
public void recordUsage(UsageTracked usageTracked) {
usageTracked.incrementUseCount();
}
}
.Java
@Aspect("perthis(com.xyz.myapp.SystemArchitecture.businessService())")
public class MyAspect {
private int someState;
@Before(com.xyz.myapp.SystemArchitecture.businessService())
public void recordServiceUsage() {
// ...
}
}