一、時序圖
spring AOP時序圖,描述代理對象生成及攔截器執行流程。由于圖檔過大,此處不做截圖展示。
git位址有詳細時序圖,有相應的html檔案可以直接浏覽
位址: https://github.com/13162576590/spring-source-study
二、Spring AOP
AOP 是 OOP 的延續,是 Aspect Oriented Programming 的縮寫,意思是面向切面程式設計。可以通過預 編譯方式和運作期動态代理實作在不修改源代碼的情況下給程式動态統一添加功能的一種技術。AOP 設計模式孜孜不倦追求的是調用者和被調用者之間的解耦,AOP 可以說也是這種目标的一種實作。 我們現在做的一些非業務,如:日志、事務、安全等都會寫在業務代碼中(也即是說,這些非業務類橫切 于業務類),但這些代碼往往是重複,複制——粘貼式的代碼會給程式的維護帶來不便,AOP 就實作了 把這些業務需求與系統需求分開來做。這種解決的方式也稱代理機制。
Spring 的 AOP 是通過接入 BeanPostProcessor 後置處理器開始的,它是 Spring IOC 容器經常使用到 的一個特性,這個 Bean 後置處理器是一個監聽器,可以監聽容器觸發的 Bean 聲明周期事件。後置處 理器向容器注冊以後,容器中管理的 Bean 就具備了接收 IOC 容器事件回調的能力。
initializeBean()方法為容器産生的 Bean 執行個體對象添加 BeanPostProcessor 後置處理器,AbstractAutowireCapableBeanFactory 類中,initializeBean()方法實作為容器建立的 Bean 執行個體對象添加 BeanPostProcessor 後置處理器。該方法就是spring AOP的入口。
進入AbstractAutowireCapableBeanFactory類protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd)方法
exposedObject = initializeBean(beanName, exposedObject, mbd);
繼續調用AbstractAutowireCapableBeanFactory類方法
1、public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException 方法
//調用 BeanPostProcessor 後置處理器執行個體對象初始化之前的處理方法
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
//周遊容器為所建立的Bean添加的所有BeanPostProcessor後置處理器
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
//周遊容器為所建立的Bean添加的所有BeanPostProcessor後置處理器
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
//調用Bean執行個體所有的後置進行中的初始化前處理方法,為Bean執行個體對象在初始化之前做一些自定義的處理操作
Object current = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
2、public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException方法
//周遊容器為所建立的Bean添加的所有BeanPostProcessor後置處理器
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
//調用BeanPostProcessor後置處理器執行個體對象初始化之後的處理方法
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
//周遊容器為所建立的Bean添加的所有BeanPostProcessor後置處理器
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
//調用Bean執行個體所有的後置進行中的初始化後處理方法,為Bean執行個體對象在初始化之後做一些自定義的處理操作
Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
BeanPostProcessor是一個接口,其初始化前的操作方法和初始化後的操作方法均委托其實作子類來實作,在Spring中,BeanPostProcessor的實作子類非常的多,分别完成不同的操作,如:AOP面向切面程式設計的注冊通知擴充卡、Bean對象的資料校驗、Bean繼承屬性、方法的合并等,我們以最簡單的AOP切面織入來簡單了解其主要的功能。下面我們來分析其中一個建立AOP代理對象的子類AbstractAutoProxyCreator類。該類重寫了 postProcessAfterInitialization()方法。
進入AbstractAutoProxyCreator類public Object postProcessAfterInitialization(@Nullable Object bean, String beanName)方法
Object current = processor.postProcessAfterInitialization(result, beanName);
繼續調用AbstractAutoProxyCreator類方法
1、protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey)方法
return wrapIfNecessary(bean, beanName, cacheKey);
進入AspectJAwareAdvisorAutoProxyCreator類protected boolean shouldSkip(Class<?> beanClass, String beanName)方法
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName))
進入AnnotationAwareAspectJAutoProxyCreator類protected List<Advisor> findCandidateAdvisors()方法
List<Advisor> candidateAdvisors = findCandidateAdvisors();
進入AbstractAdvisorAutoProxyCreator類protected List<Advisor> findCandidateAdvisors()方法
List<Advisor> advisors = super.findCandidateAdvisors();
進入BeanFactoryAspectJAdvisorsBuilder類public List<Advisor> buildAspectJAdvisors()方法
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
回到AbstractAutoProxyCreator類public Object postProcessAfterInitialization(@Nullable Object bean, String beanName)方法,繼續調用
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
再次進入AbstractAdvisorAutoProxyCreator類,調用protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource)方法
繼續調用AbstractAdvisorAutoProxyCreator類方法
1、protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName)方法
進入AopUtils類public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) 方法
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
再次回到AbstractAutoProxyCreator類protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey)方法,繼續調用protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource)方法方法
Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
繼續調用AbstractAutoProxyCreator類方法
1、protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors)方法
//封裝成 Advisor
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
進入DefaultAdvisorAdapterRegistry類public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException 方法
advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
再次回到AbstractAutoProxyCreator類protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource)方法,繼續調用public Object getProxy(@Nullable ClassLoader classLoader)方法
return proxyFactory.getProxy(getProxyClassLoader());
進入ProxyFactory類public Object getProxy(@Nullable ClassLoader classLoader)方法
return proxyFactory.getProxy(getProxyClassLoader());
進入ProxyCreatorSupport類protected final synchronized AopProxy createAopProxy()方法
return createAopProxy().getProxy(classLoader);
進入DefaultAopProxyFactory類public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException方法
return getAopProxyFactory().createAopProxy(this);
代理2種實作方式:
1.jdk動态代理
2.cglib代理
spring5及spring boot2.x AOP預設是cglib。此處使用cglib代理。
回到ProxyFactory類public Object getProxy(@Nullable ClassLoader classLoader)方法,進入CglibAopProxy類public Object getProxy(@Nullable ClassLoader classLoader)方法
return createAopProxy().getProxy(classLoader);
繼續調用CglibAopProxy類方法
1、private Callback[] getCallbacks(Class<?> rootClass) throws Exception方法
Callback[] callbacks = getCallbacks(rootClass);
進入ObjenesisCglibAopProxy類protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks)方法
return createProxyClassAndInstance(enhancer, callbacks);
進入Enhancer類public Class createClass()方法
Class<?> proxyClass = enhancer.createClass();
繼續調用Enhancer類方法
1、private Object createHelper()方法
return (Class) createHelper();
進入AbstractClassGenerator類protected Object create(Object key)方法
Object result = super.create(key);
繼續調用AbstractClassGenerator類方法
1、public Object get(AbstractClassGenerator gen, boolean useCache)方法
Object obj = data.get(this, getUseCache());
進入LoadingCache類public V get(K key)方法
Object cachedValue = generatedClasses.get(gen);
繼續調用LoadingCache類方法
1、protected V createEntry(final K key, KK cacheKey, Object v)方法
return v != null && !(v instanceof FutureTask) ? v : this.createEntry(key, cacheKey, v);
源碼:
protected V createEntry(final K key, KK cacheKey, Object v) {
boolean creator = false;
FutureTask task;
Object result;
if (v != null) {
task = (FutureTask)v;
} else {
task = new FutureTask(new Callable<V>() {
public V call() throws Exception {
//執行線程方法
return LoadingCache.this.loader.apply(key);
}
});
result = this.map.putIfAbsent(cacheKey, task);
if (result == null) {
creator = true;
//啟動一個線程,調用run方法,在run方法内部在回調call()方法,即上述源碼return LoadingCache.this.loader.apply(key)處
task.run();
} else {
if (!(result instanceof FutureTask)) {
return result;
}
task = (FutureTask)result;
}
}
try {
result = task.get();
} catch (InterruptedException var9) {
throw new IllegalStateException("Interrupted while loading cache item", var9);
} catch (ExecutionException var10) {
Throwable cause = var10.getCause();
if (cause instanceof RuntimeException) {
throw (RuntimeException)cause;
}
throw new IllegalStateException("Unable to load cache item", cause);
}
if (creator) {
this.map.put(cacheKey, result);
}
return result;
}
上述源碼啟動一個線程,調用run方法,在run方法内部在回調call()方法,即上述源碼return LoadingCache.this.loader.apply(key)處,然後進入AbstractClassGenerator類内部類ClassLoaderData的構造函數public ClassLoaderData(ClassLoader classLoader)。
進入AbstractClassGenerator類内部類ClassLoaderData的public ClassLoaderData(ClassLoader classLoader)構造函數
return LoadingCache.this.loader.apply(key);
此處調用是初始化時的一個function接口,源碼如下:
public ClassLoaderData(ClassLoader classLoader) {
if (classLoader == null) {
throw new IllegalArgumentException("classLoader == null is not yet supported");
} else {
this.classLoader = new WeakReference(classLoader);
//function接口
Function<AbstractClassGenerator, Object> load = new Function<AbstractClassGenerator, Object>() {
public Object apply(AbstractClassGenerator gen) {
Class klass = gen.generate(ClassLoaderData.this);
return gen.wrapCachedClass(klass);
}
};
this.generatedClasses = new LoadingCache(GET_KEY, load);
}
}
當在類LoadingCache的protected V createEntry(final K key, KK cacheKey, Object v)方法調用task.run()方法時,會啟動一個線程,最終回調到線程的public V call() throws Exception方法,執行LoadingCache.this.loader.apply(key),是以執行到初始化的function接口。
再次進入Enhancer類,調用protected Class generate(ClassLoaderData data)方法
Class klass = gen.generate(ClassLoaderData.this);
再次進入AbstractClassGenerator類,調用protected Class generate(ClassLoaderData data)方法
return super.generate(data);
進入ClassLoaderAwareGeneratorStrategy類public byte[] generate(ClassGenerator cg) throws Exception方法
public byte[] generate(ClassGenerator cg) throws Exception
進入DefaultGeneratorStrategy類public byte[] generate(ClassGenerator cg) throws Exception方法
return super.generate(cg);
再次進入Enhancer類,調用public void generateClass(ClassVisitor v) throws Exception方法
this.transform(cg).generateClass(cw);
繼續調用Enhancer類方法
1、private void emitMethods(final ClassEmitter ce, List methods, List actualMethods)方法
emitMethods(e, methods, actualMethods);
再次CglibAopProxy類,調用public int accept(Method method)方法
int index = filter.accept(actualMethod);
進入AdvisedSupport類public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass)方法
List<?> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
進入DefaultAdvisorChainFactory類public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass)方法
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this, method, targetClass);
進入DefaultAdvisorAdapterRegistry類public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException方法
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
cglib執行過程,執行入口在CglibAopProxy内部類DynamicAdvisedInterceptor類public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable方法
再次進入AdvisedSupport類 public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass)方法
// 擷取目前方法的攔截器鍊
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
進入CglibAopProxy類public Object proceed() throws Throwable方法
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
進入ReflectiveMethodInvocation類public Object proceed() throws Throwable方法
return super.proceed();
源碼如下:
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);
}
}
進入ExposeInvocationInterceptor類public Object invoke(MethodInvocation mi) throws Throwable方法
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
ExposeInvocationInterceptor暴露調用器的攔截器,其就是起了暴露一個調用器作用的攔截器。
進入CglibAopProxy内部類CglibMethodInvocation的public Object proceed() throws Throwable方法
return mi.proceed();
再次回到ReflectiveMethodInvocation類public Object proceed() throws Throwable方法
//CglibMethodInvocation#proceed
return super.proceed();
進入AspectJAroundAdvice類public Object invoke(MethodInvocation mi) throws Throwable方法
//根據不同的攔截器,進入不同的類
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
進入AbstractAspectJAdvice類方法protected Object invokeAdviceMethod(JoinPoint jp, @Nullable JoinPointMatch jpMatch,@Nullable Object returnValue, @Nullable Throwable t) throws Throwable方法
return invokeAdviceMethod(pjp, jpm, null, null);
繼續調用AbstractAspectJAdvice類方法
1、return invokeAdviceMethodWithGivenArgs(argBinding(jp, jpMatch, returnValue, t))方法
return invokeAdviceMethodWithGivenArgs(argBinding(jp, jpMatch, returnValue, t));
進入Method類public Object invoke(Object obj, Object... args)方法
return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
進入DelegatingMethodAccessorImpl類public Object invoke(Object var1, Object[] var2) throws IllegalArgumentException, InvocationTargetException方法
return ma.invoke(obj, args);
進入NativeMethodAccessorImpl類public Object invoke(Object var1, Object[] var2) throws IllegalArgumentException, InvocationTargetException方法
return this.delegate.invoke(var1, var2);
進入切面方法,Demo是以LogAspect為列,故進入LogAspect類public Object doAround(ProceedingJoinPoint point) throws Throwable方法
return invoke0(this.method, var1, var2);
LogAspect類源碼如下:
/**
* 項目名稱:spring-cloud-service
* 類 名 稱:LogAspect
* 類 描 述:TODO
* 建立時間:2020/9/12 11:06 下午
* 創 建 人:chenyouhong
*/
@Aspect
@Component
public class LogAspect {
@Pointcut("execution(* com.cloud.user.controller.*.*(..))")
public void aspect() {
}
@Before("aspect()")
public void before(JoinPoint jp) throws Throwable {
//...
System.out.println("Before");
}
@Around("aspect()")
public Object doAround(ProceedingJoinPoint point) throws Throwable {
//...
System.out.println("==========");
Object returnValue = point.proceed(point.getArgs());
System.out.println("**********");
//...
return returnValue;
}
@After("aspect()")
public void after(JoinPoint jp) throws Throwable {
//...
System.out.println("after");
}
}
此處會進入切面LogAspect類public Object doAround(ProceedingJoinPoint point) throws Throwable方法
進入MethodInvocationProceedingJoinPoint類public Object proceed(Object[] arguments) throws Throwable方法
Object returnValue = point.proceed(point.getArgs());
再次回到ReflectiveMethodInvocation類public Object proceed() throws Throwable方法
//CglibMethodInvocation#proceed
return super.proceed();
進入MethodBeforeAdviceInterceptor類public Object invoke(MethodInvocation mi) throws Throwable方法
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
因為此時的攔截器interceptorOrInterceptionAdvice對應的類型是MethodBeforeAdviceInterceptor。
進入AspectJMethodBeforeAdvice類public void before(Method method, Object[] args, @Nullable Object target) throws Throwable方法
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
再次進入AbstractAspectJAdvice類方法protected Object invokeAdviceMethod(JoinPoint jp, @Nullable JoinPointMatch jpMatch,@Nullable Object returnValue, @Nullable Throwable t) throws Throwable方法
return invokeAdviceMethod(pjp, jpm, null, null);
繼續調用AbstractAspectJAdvice類方法
1、return invokeAdviceMethodWithGivenArgs(argBinding(jp, jpMatch, returnValue, t))方法
return invokeAdviceMethodWithGivenArgs(argBinding(jp, jpMatch, returnValue, t));
此處邏輯同上述invokeAdviceMethod方法執行一直,隻是執行切面時,進入方法是LogAspect類public void before(JoinPoint jp) throws Throwable方法
再次回到CglibAopProxy内部類CglibMethodInvocation的public Object proceed() throws Throwable方法
return mi.proceed();
繼續執行,當執行到攔截器,因為此時的攔截器interceptorOrInterceptionAdvice對應的類型是AspectJAfterAdvice。
進入AspectJAfterAdvice類public Object invoke(MethodInvocation mi) throws Throwable方法
//interceptorOrInterceptionAdvice類型是AspectJAfterAdvice
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
當執行到最後一個攔截器時,進入CglibAopProxy内部類CglibMethodInvocation的protected Object invokeJoinpoint() throws Throwable方法
return invokeJoinpoint();
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
進入MethodProxy類public Object invoke(Object obj, Object[] args) throws Throwable方法
return this.methodProxy.invoke(this.target, this.arguments);
繼續調用MethodProxy類方法
1、init()方法
進入被代理類需要執行的方法,demo是UserController類public Mono<String> login()方法
return fci.f1.invoke(fci.i1, obj, args);
被代理類源碼如下:
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private TestService testService;
private List<String> list;
/**
* 密碼模式 認證.
*
* @return
*/
@RequestMapping("/test")
public Mono<String> login() {
//登入 之後生成令牌的資料傳回
testService.test();
return Mono.just("test");
}
/**
* 密碼模式 認證.
*
* @return
*/
@RequestMapping("/test2")
@PreAuthorize(value = "hasAnyAuthority('test')")
// @PreAuthorize("hasPermission('test8988989')")
public Mono<String> login2() {
//登入 之後生成令牌的資料傳回
System.out.println("rest2");
return Mono.just("test2");
}
}
再次回到AspectJAfterAdvice類public Object invoke(MethodInvocation mi) throws Throwable方法
繼續之前并未執行完邏輯,繼續往後執行,源碼如下:
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
try {
//執行被代理類想要執行的方法
return mi.proceed();
}
finally {
//此處邏輯同上述invokeAdviceMethod方法執行一直,隻是執行切面時,進入方法是LogAspect類public void after(JoinPoint jp) throws Throwable方法
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}