- aop是动态代理的一种应用。对于有接口的类,使用原生的代理类,利用反射获取到类加载器,然后构造出构造函数,通过构造函数返一个代理对象,另一种没有实现接口的类使用的就是cglib代理,代理类继承自原类。
- 使用:(aspect + component)
pointcut 切点 (进行切点匹配)
advice 通知 (对匹配到的进行织入) joinpoint 连接点|proceedingjoinpoint 进行连接点 ≈ target weaving 织入
@Aspect
@Slf4j
@Component
public class WebLogAspect {
@Pointcut("execution( * com.az.controller..*(..))")
public void webLog() {}
@Around("webLog()")
public Object aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable {
log.info("方法执行: " + joinPoint.getSignature().getDeclaringType().getName() + "#" + joinPoint.getSignature().getName());
Object[] args = joinPoint.getArgs();
Object arg = args[0];
Object proceed = joinPoint.proceed();
log.info("方法: " + joinPoint.getSignature().getName() + "() 执行完毕");
return proceed;
}
@AfterThrowing(pointcut = "webLog()", throwing = "e")
public void afterThrowingMethod(JoinPoint joinPoint, Throwable e) {
log.error("方法异常:" + joinPoint.getSignature().getDeclaringType().getName() + "#" + joinPoint.getSignature().getName() + " 异常");
log.error("异常信息:" + e.getMessage());
}
@Before("execution(* com.az.controller.add(..))")
public void beforeAddOperation(JoinPoint joinPoint) {
Object[] args = joinPoint.getArgs();
log.info("Before executing the add() method");
log.info("Arguments: " + Arrays.toString(args));
}
}
位置图 Big picture
- 不同注解之间重要是位置。
try{
try{
//@Around start
//@Before
method.invoke(..);
//@Around end
}finally{
//@After
}
//@AfterReturning
}catch(){
//@AfterThrowing
}
获得运行时 JoinPoint’s Signature
- 获得常用目标
// ProceedingJoinPoint point;
// 获取当前执行类
String typeName = point.getTarget().getName();
// String typeName = point.getSignature().getDeclaringTypeName();
// 获取当前执行类的执行方法名
String name = point.getSignature().getName();
// 获取当前执行方法的执行参数
Object[] object = point.getArgs();
// 获取当前执行 method
Signature signature = point.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
// 获取方法注解
if (method.isAnnotationPresent(DataSource.class)) {
DataSource dataSource = method.getAnnotation(DataSource.class);
String value = dataSource.value();
- 获取入参对象的 class
Method targetMethod = ((MethodSignature) (point.getSignature())).getMethod();
Class<?>[] parameterTypes = targetMethod.getParameterTypes();
// 转变为集合
List<Class<?>> collect = Arrays.stream(parameterTypes).collect(Collectors.toList());
// 入参对象
Class<?> aClass1 = collect.get(0);
Summary
package aop;
import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.*;
/**
* Advice -> Interceptor -> MethodInterceptor (core is Advice, specific aspect code, this is static)
* <p>Joinpoint-> Invocation -> MethodInvocation (core is Joinpoint, specific cut into the context, this is the runtime)
* <p>advice is the action to take at a joinpoint</p>
*/
public class AopAlliance {
/**
* Action taken by an aspect at a particular join point.
*/
private Advice advice;
private Interceptor interceptor;
private MethodInterceptor methodInterceptor;
/**
* A point during the execution of a program,
* such as the execution of a method or the handling of an exception.
* In Spring AOP, a join point always represents a method execution.
*/
private Joinpoint joinpoint;
/**
* This interface represents an invocation in the program.
* <p>An invocation is a joinpoint and can be intercepted by an interceptor.
*/
private Invocation invocation;
/**
* Description of an invocation to a method, given to an interceptor upon method-call.
* <p>A method invocation is a joinpoint and can be intercepted by a method interceptor.
*/
private MethodInvocation methodInvocation; // ReflectiveMethodInvocation
/**
* A modularization of a concern that cuts across multiple classes.
* Transaction management is a good example of a crosscutting concern in enterprise Java application.
*/
private enum Aspect {
/**
* <p>Spring Addition</p>
* A predicate that matches join points.
* Advice is associated with pointcut expression and runs at any join point matched by the pointcut.
* (for example, the execution of a method with a certain name)
* <p>
* Pointcut vs Joinpoint: static vs runtime(instance)
*/
Pointcut,
/**
* Advisor -> PointcutAdvisor
* <p>Holders of Advice, the main reference sub-interface PointcutAdvisor
* <p>An Advisor advises someone (Pointcut) to do something at a certain time (Advice)
*/
Advisor,
/**
* Declare additional methods or fields on behalf of a type.
* Spring AOP lets you introduce new interfaces (and a corresponding implementation)
* to any advised object. For example, you could use an introduction to make a bean implement an IsModified interface, to simplify caching.
*/
Introduction,
/**
* An object being advised by one or more aspects. Also referred to as the "advised object".
* Since Spring AOP is implemented by using runtime proxies, this object is always a proxies object.
*/
Target_object,
/**
* An object created by the AOP framework in order to implement the aspect contracts.
* In the Spring Framework, an AOP proxy is a JDK dynamic proxy or a CGLIB proxy.
*/
AOP_proxy,
/**
* linking aspects with other application types or objects to create an advised object.
* This can be done at compile time (using the AspectJ compiler, for example), load time, or at runtime.
* Spring AOP, like other pure Java AOP frameworks, performs weaving at runtime.
*/
Weaving;
}
/**
* Spring AOP's approach to AOP differs from that of most other AOP frameworks. The aim is not
* to provide the most complete AOP implementation (although Spring AOP is quite capable).
* Rather, the aim is to provide a close integration between AOP implementation and Spring IoC,
* to help solve common problems in enterprise applications.
* <p>
* If you get a bean and want to know if it has been enhanced,
* you can determine if the bean is subclass of {@code Advised}
*/
public AopAlliance() {
Aspect[] aspects =
{Aspect.Pointcut, Aspect.Advisor, Aspect.Introduction, Aspect.Target_object,
Aspect.AOP_proxy, Aspect.Weaving};
}
}