拦截器总结:
总结执行顺序:
preHandle按拦截器定义顺序调用
postHandler按拦截器定义逆序调用
afterCompletion按拦截器定义逆序调用
postHandler在拦截器链内全部拦截器返成功调用
afterCompletion只有preHandle返回true才调用复制代码
在applicationContext中存在一个beanFactoryjava
进去beanFactory能够看到beanPostProcessorsweb
进去beanPostProcessors能够看到AnnotationAwareAspectJAutoProxyCreator
spring
进去AnnotationAwareAspectJAutoProxyCreator能够看到beanFactory和proxyType和adviseBeans
api
进去beanFactory的singletonObjects能够看到mathTest代理类,代开一个拦截器,能够看到里面全部咱们后面源码分析的一些参数。好比active=true,targetSource,advisors等
springboot
package org.springframework.context.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
boolean proxyTargetClass() default false;
boolean exposeProxy() default false;
}复制代码
进入注解EnableAspectJAutoProxy能够发现@Import(AspectJAutoProxyRegistrar.class),注入了一个AspectJAutoProxyRegistrar的组件,咱们在看看AspectJAutoProxyRegistrar里面代码bash
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
"org.springframework.aop.config.internalAutoProxyCreator";@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
复制代码
从上面的代码能够看出在ioc初始化的时候BeanDefinition中保存了name为org.springframework.aop.config.internalAutoProxyCreator,类为AnnotationAwareAspectJAutoProxyCreator的Bean定义信息。app
接下来看看AnnotationAwareAspectJAutoProxyCreatoride
先看看继承关系
public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator;
public class AspectJAwareAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator;
public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator ;
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport;
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware;
从这里能够看出他的父类实现了SmartInstantiationAwareBeanPostProcessor
, BeanFactoryAware这两个接口,
看看后置处理器作了什么?
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
Object cacheKey = getCacheKey(beanClass, beanName);
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// Create proxy here if we have a custom TargetSource.
// Suppresses unnecessary default instantiation of the target bean:
// The TargetSource will handle target instances in a custom fashion.
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return null;
}从上面的代码能够看出他将全部的代理类的加强拦截器(before,after等,加上事务管理的TransationInterceptor),目标类等,都会
整理出来保存到代理类中。到这里其实前置条件已经基本完成了。le复制代码
package com.felix.springbootdemo.aspects;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.List;
@Aspect
@Slf4j
public class MathAspect {
@Pointcut("execution(public * com.felix.springbootdemo.test.*.*(..))")
public void test() {
}
@Before("test()")
public void doBefore(JoinPoint joinPoint) {
//获取方法名称
String name = joinPoint.getSignature().getName();
//获取参数
List<Object> list = Arrays.asList(joinPoint.getArgs());
log.info("方法{}前置加强,参数为:{}", name, list);
}
@After("test()")
public void doAfter(JoinPoint joinPoint) {
//获取方法名称
String name = joinPoint.getSignature().getName();
//获取参数
List<Object> list = Arrays.asList(joinPoint.getArgs());
log.info("方法{}后置加强,参数为:{}", name, list);
}
@AfterReturning(value = "test()", returning = "returning")
public void doAfterReturning(JoinPoint joinPoint, Object returning) {
//获取方法名称
String name = joinPoint.getSignature().getName();
//获取参数
List<Object> list = Arrays.asList(joinPoint.getArgs());
log.info("方法{}返回加强,参数为:{},返回值为:{}", name, list, returning);
}
@AfterThrowing(value = "test()", throwing = "e")
public void doAfterThrowing(JoinPoint joinPoint, Exception e) {
//获取方法名称
String name = joinPoint.getSignature().getName();
//获取参数
List<Object> list = Arrays.asList(joinPoint.getArgs());
log.info("方法{}异常加强,参数为:{},异常为:{}", name, list, e.getMessage());
}
}复制代码
package com.felix.springbootdemo.config;
import com.felix.springbootdemo.aspects.MathAspect;
import com.felix.springbootdemo.test.MathTest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@EnableAspectJAutoProxy
public class AopConfig {
@Bean
public MathTest mathTest() {
return new MathTest();
}
@Bean
public MathAspect mathAspect() {
return new MathAspect();
}
}复制代码
package com.felix.springbootdemo.test;
public class MathTest {
public int div(int x, int y) {
return x / y;
}
}
复制代码
package com.felix.springbootdemo.config;
import com.felix.springbootdemo.test.MathTest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
@Slf4j
public class Test {
@org.junit.jupiter.api.Test
public void test() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AopConfig.class);
MathTest bean = applicationContext.getBean(MathTest.class);
log.info("{}", bean);
bean.div(1, 1);
}
}复制代码
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Object target = null;
TargetSource targetSource = this.advised.getTargetSource();
try {
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
// Check whether we only have one InvokerInterceptor: that is,
// no real advice, but just reflective invocation of the target.
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
// We can skip creating a MethodInvocation: just invoke the target directly.
// Note that the final invoker must be an InvokerInterceptor, so we know
// it does nothing but a reflective operation on the target, and no hot
// swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = methodProxy.invoke(target, argsToUse);
}
else {
// We need to create a method invocation...
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}复制代码
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);这个方法是获取拦截器链,其中在获取拦截器的时候,在使用适配器模式将全部的拦截器封装成Advisor源码分析
再看看执行的方法post
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
@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();
}
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); } }复制代码
里面有三个地方值得关注
一、this.currentInterceptorIndex=-1
二、Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
复制代码
三、return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
下面的图片为执行的过程图。