引入依赖后,类路径存在 Aspect.class、Advice.class、AnnotatedElement.class 因此自动化配置类AopAutoConfiguration生效。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> 复制代码
@Configuration @ConditionalOnClass({ EnableAspectJAutoProxy.class, Aspect.class, Advice.class, AnnotatedElement.class }) @ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true) public class AopAutoConfiguration { @Configuration @EnableAspectJAutoProxy(proxyTargetClass = false) @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = false) public static class JdkDynamicAutoProxyConfiguration { } @Configuration @EnableAspectJAutoProxy(proxyTargetClass = true) @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true) public static class CglibAutoProxyConfiguration { } } 复制代码
@Aspect @Component public class LogAspect { @Pointcut("execution(public * com.mrglint.springbootdemo.service..*.*(..))") private void pointCut(){ } /** * 切面作用于 com.mrglint.springbootdemo 下的子包以及子包下的子包,任意类的任意方法 * @param joinPoint */ @Before("pointCut()") public void doBefore(JoinPoint joinPoint) { System.out.println("doBefore run..."); } @After("pointCut()") public void doAfter(JoinPoint joinpoint) { System.out.println("doAfter run..."); } @AfterReturning(value = "pointCut()", returning = "res") public void doAfterReturning(JoinPoint joinPoint, Object res) { System.out.println("doAfterReturning run, result: " + res); } @AfterThrowing(value = "pointCut()", throwing = "e") public void doAfterThrowing(JoinPoint joinPoint, Throwable e) { System.out.println("doAfterThrowing run, exception: " + e); } @Around("pointCut()") public Object doArround(ProceedingJoinPoint proceedingJoinPoint) { System.out.println("doArround run on before..."); Object res = null; try { res = proceedingJoinPoint.proceed(); System.out.println("doArround run on after"); } catch (Throwable throwable) { System.out.println("doArround run on throw exception: " + throwable); throwable.printStackTrace(); } return res; } } 复制代码
可以通过配置 exposeProxy = true来暴露代理对象到ThreadLocal中,之后在被代理类对象内部可以使用 AopContext.currentProxy() 来获取代理类对象
// 默认为false @EnableAspectJAutoProxy(exposeProxy = true) 复制代码
由@EnableAspectJAutoProxy导入的AspectJAutoProxyRegistrar注册到beanfactory中,作为一个BeanPostProcessor存在
在了解调用代理的逻辑之前,我们来回顾创建代理对象的方法实现
// JdkDynamicAopProxy.getProxy @Override public Object getProxy() { return getProxy(ClassUtils.getDefaultClassLoader()); } @Override public Object getProxy(@Nullable ClassLoader classLoader) { if (logger.isTraceEnabled()) { logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource()); } Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true); findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); // JDK动态代理,JdkDynamicAopProxy自身作为 InvocationHandler对象 return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); } 复制代码
@Override @Nullable public Object proceed() throws Throwable { // We start with an index of -1 and increment early. if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { // 执行被代理方法 return invokeJoinpoint(); } // 获取第一个切面逻辑拦截器。一开始为 (-1 + 1) = 0,interceptorsAndDynamicMethodMatchers 中的第一个 Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { // Evaluate dynamic method matcher here: static part will already have // been evaluated and found to match. InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice; Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass()); if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) { return dm.interceptor.invoke(this); } else { // Dynamic matching failed. // Skip this interceptor and invoke the next in the chain. return proceed(); } } else { // It's an interceptor, so we just invoke it: The pointcut will have // been evaluated statically before this object was constructed. return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } } 复制代码