本篇內容以註解的形式使用Spring AOP,所以這裡容器使用的是AnnotationConfigApplicationContext
Spring Ioc容器的加載流程
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
register(componentClasses);
refresh();
}
-
首先是this(),此無參構造函數主要完成兩件事
- 調用AnnotationConfigApplicationContext的一系列父類的無參構造函數,初始化相關的屬性,包括beanFactoryPostProcessors,beanFactory等重要屬性;
-
通過AnnotatedBeanDefinitionReader註冊內置的postProcessor(實質是把<beanName,BeanDefinition>鍵值對放入DefaultListableBeanFactory的beanDefinitionMap屬性中)
-
AnnotationConfigUtils#registerPostProcessor會註冊以下後置處理器
- ConfigurationClassPostProcessor(BeanDefinitionRegistryPostProcessor的實現類,主要解析主配置類、處理@Bean等註解)
- AutowiredAnnotationBeanPostProcessor(SmartInstantiationAwareBeanPostProcessor和MergedBeanDefinitionPostProcessor的實現類,本質是BeanPostProcessor)
- CommonAnnotationBeanPostProcessor,設置@PostConstruct和@PreDestroy註解(在父類InitDestroyAnnotationBeanPostProcessor中)
- 如果支持JPA,註冊PersistenceAnnotationBeanPostProcessor
- EventListenerMethodProcessor
- DefaultEventListenerFactory
-
- 構造ClassPathBeanDefinitionScanner實例對象(構造函數setResourceLoader,把Spring ioc容器轉為ResourceLoader)
-
註冊配置類
- 把配置類放入DefaultListableBeanFactory的beanDefinitionMap屬性中
- 刷新容器refresh()
-
invokeBeanFactoryPostProcessors(beanFactory),主要完成的功能:往beanDefinitionNames中註冊@Bean註解標註的方法返回的對象,如:業務邏輯類,切面類,@Import註解引入的類,
- invokeBeanDefinitionRegistryPostProcessors
參數為上一步獲取的後置處理器的bean集合,如:
- 首先從Spring容器中獲取ConfigurationClassPostProcessor對應的bean;
- 然後解析配置類,流程是:ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
```
// 創建配置類的解析器
// Parse each @Configuration class
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
// 開始解析
parser.parse(candidates);
parser.validate();
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
// Read the model and create bean definitions based on its content
if (this.reader == null) {
// 創建配置類BeanDefinition的解析器
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
// 解析@Bean註解標註的方法返回的對象,@Import註解引入的類,注入的對象
this.reader.loadBeanDefinitions(configClasses);
```
ConfigurationClassBeanDefinitionReader#loadBeanDefinitions
```
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
// 解析@Bean註解標註的類返回的對象
loadBeanDefinitionsForBeanMethod(beanMethod);
}
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
// 解析@Import註解引入的類,注入的對象
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
```
- ConfigurationClassParser解析配置類,主要功能是填充configurationClasses屬性(key,value都是解析後的ConfigurationClass的實例)
- 解析ConfigurationClass,主要是得到beanMethods,importBeanDefinitionRegistrars屬性值
- ConfigurationClassBeanDefinitionReader#loadBeanDefinitions,主要功能是把上面解析得到的beanMethods註冊到beanDefinitionMap中,以及調用AspectJAutoproxyRegistrar的registerBeanDefinitions方法,把AnnotationAwareAspectJAutoProxyCreator註冊到beanDefinitionMap中
- registerBeanPostProcessors(beanFactory)
- 實例化AnnotationAwareAspectJAutoProxyCreator,並加入AbstractBeanFactory的beanPostProcessors屬性中,
- 往單例緩存池中加入internalAutoProxyCreator
-
在獲取internalAutoProxyCreator的實例過程中,會調用doCreateBean#setBeanFactory的aware接口,初始化與AOP獲取advisors相關的一些類
-總的邏輯;- 初始化BeanFactoryAdvisorRetrievalHelperAdapter對象
- ReflectiveAspectJAdvisorFactory對象(解析切面,並獲取advisors集合)
- BeanFactoryAspectJAdvisorsBuilderAdapter(AnnotationAwareAspectJAutoProxyCreator的內部類,其父類是BeanFactoryAspectJAdvisorsBuilder,作用是解析切面,並獲取advisors集合)對象
- 源碼:
- 首先調用AbstractAdvisorAutoProxyCreator的setBeanFactory方法
@Override public void setBeanFactory(BeanFactory beanFactory) { super.setBeanFactory(beanFactory); if (!(beanFactory instanceof ConfigurableListableBeanFactory)) { throw new IllegalArgumentException( "AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory); } initBeanFactory((ConfigurableListableBeanFactory) beanFactory); }
- 然後調用AnnotationAwareAspectJAutoProxyCreator的initBeanFactoryff
@Override protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) { super.initBeanFactory(beanFactory); if (this.aspectJAdvisorFactory == null) { this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory); } // 內部類,它的父類是BeanFactoryAspectJAdvisorsBuilder this.aspectJAdvisorsBuilder = new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory); }
- 調用AbstractAdvisorAutoProxyCreator的initBeanFactory
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) { this.advisorRetrievalHelper = new BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory); }
- finishBeanFactoryInitialization(beanFactory)
- 創建剩餘非懶加載的bean,並存到單例緩存池,如:業務邏輯類,主配置類,切面類
- 解析主配置類(如:aopConfig)時,在resolveBeforeInstantiation中AbstractAutoproxyCreator的postProcessBeforeInstantiation的shouldSkip中,
由ReflectiveAspectJAdvisorFactory#getAdvisors獲取advisors(不包含ExposeInvocationInterceptor)
- 源碼:
- 由ReflectiveAspectJAdvisorFactory(在上一步已創建對象)調用getAdvisors
```
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
List<Advisor> advisors = new ArrayList<>();
// 先獲取切面的通知方法(加了通知註解的方法)
for (Method method : getAdvisorMethods(aspectClass)) {
// 調用以下方法,獲取每個通知的增強器,返回類型是InstantiationModelAwarePointcutAdvisorImpl
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
```
```
@Override
@Nullable
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) {
validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
AspectJExpressionPointcut expressionPointcut = getPointcut(
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
if (expressionPointcut == null) {
return null;
}
// 構造函數中會創建advice
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
```
```
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
this.declaredPointcut = declaredPointcut;
this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
this.methodName = aspectJAdviceMethod.getName();
this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
this.aspectJAdviceMethod = aspectJAdviceMethod;
this.aspectJAdvisorFactory = aspectJAdvisorFactory;
this.aspectInstanceFactory = aspectInstanceFactory;
this.declarationOrder = declarationOrder;
this.aspectName = aspectName;
if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
// Static part of the pointcut is a lazy type.
Pointcut preInstantiationPointcut = Pointcuts.union(
aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
// Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
// If it's not a dynamic pointcut, it may be optimized out
// by the Spring AOP infrastructure after the first evaluation.
this.pointcut = new PerTargetInstantiationModelPointcut(
this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
this.lazy = true;
}
else {
// A singleton aspect.
this.pointcut = this.declaredPointcut;
this.lazy = false;
// 創建advice對象
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
}
```
- InstantiationModelAwarePointcutAdvisorImpl的instantiateAdvice方法
```
private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
return (advice != null ? advice : EMPTY_ADVICE);
}
```
- 根據通知方法的註解,分別返回對應的AspectJXXXAdvice對象,@Around/@Before/@After/@Afterreturning/@AfterThrowing
```
@Override
@Nullable
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
validate(candidateAspectClass);
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
// If we get here, we know we have an AspectJ method.
// Check that it's an AspectJ-annotated class
if (!isAspect(candidateAspectClass)) {
throw new AopConfigException("Advice must be declared inside an aspect type: " +
"Offending method '" + candidateAdviceMethod + "' in class [" +
candidateAspectClass.getName() + "]");
}
if (logger.isDebugEnabled()) {
logger.debug("Found AspectJ method: " + candidateAdviceMethod);
}
AbstractAspectJAdvice springAdvice;
switch (aspectJAnnotation.getAnnotationType()) {
case AtPointcut:
if (logger.isDebugEnabled()) {
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
}
return null;
case AtAround:
springAdvice = new AspectJAroundAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtBefore:
springAdvice = new AspectJMethodBeforeAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfter:
springAdvice = new AspectJAfterAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfterReturning:
springAdvice = new AspectJAfterReturningAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
springAdvice.setReturningName(afterReturningAnnotation.returning());
}
break;
case AtAfterThrowing:
springAdvice = new AspectJAfterThrowingAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
}
break;
default:
throw new UnsupportedOperationException(
"Unsupported advice type on method: " + candidateAdviceMethod);
}
// Now to configure the advice...
springAdvice.setAspectName(aspectName);
springAdvice.setDeclarationOrder(declarationOrder);
String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
if (argNames != null) {
springAdvice.setArgumentNamesFromStringArray(argNames);
}
springAdvice.calculateArgumentBindings();
return springAdvice;
}
```
- 解析被代理的業務邏輯類(如:mathCalculator)時,在doCreateBean中AbstractAutoproxyCreator的postProcessAfterInitialization中獲取代理對象(advisors中添加ExposeInvocationInterceptor,
並調用AspectJAwareAdvisorAutoProxyCreator#sortAdvisors排序)
- 源碼:
- 獲取代理對象的入口
```
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
```
```
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
```
- createProxy
創建代理對象,把之前解析主配置類得到的advisors集合作為參數傳入,
在getProxy中,把ProxyCreatorSupport對象本身作為參數,傳入到DefaultAopProxyFactory#createAopProxy方法,返回ObjenesisCglibAopProxy對象(ProxyCreatorSupport對象作為參數),初始化ObjenesisCglibAopProxy的父類CglibAopProxy,設置advised的值為(ProxyCreatorSupport類型的對象,其中包含advisors集合)
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
// 依次調用父類AdvisedSupport,ProxyCreatorSupport的構造函數,
// 分別聲明advisorChainFactory = new DefaultAdvisorChainFactory(),
// aopProxyFactory = new DefaultAopProxyFactory()
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// Use original ClassLoader if bean class not locally loaded in overriding class loader
ClassLoader classLoader = getProxyClassLoader();
if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {
classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();
}
return proxyFactory.getProxy(classLoader);
}
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
- DefaultAopProxyFactory的createAopProxy,根據是否實現接口,採用cglib動態代理或JDK動態代理
```
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (!NativeDetector.inNativeImage() &&
(config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
```
- 最後返回代理對象
Spring AOP通知集合如何獲取以及代理對象的生成
-
結合Spring Ioc容器的加載流程分析,在finishBeanFactoryInitialization這一步解析主配置類的bean,調用過程如下:
- resolveBeforeInstantiation這一步,AbstractAutoProxyCreator的postProcessBeforeInstantiation方法
- AspectJAwareAdvisorAutoProxyCreator#shouldSkip
- AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors
- BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors(這裡BeanFactoryAspectJAdvisorsBuilder對象實例通過在registerBeanPostProcessors方法中創建)
-
ReflectiveAspectJAdvisorFactory調用相關類的方法
- 如果是切面,由advisorFactory獲取當前切面的所有通知advisors,並存儲到advisorsCache(map類型,key是beanName,value是advisors)
- 創建BeanFactoryAspectInstanceFactory對象factory
-
ReflectiveAspectJAdvisorFactory#getAdvisors(factory),參數是上一步中創建的factory
- 創建LazySingletonAspectInstanceFactoryDecorator對象(創建MetadataAwareAspectInstanceFactory的裝飾器,便於它只被實例化一次!)
- getAdvisorMethods
通過反射得到切面類的通知方法,並循環遍歷該集合,集合返回之前排序(按照Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class的順序)
- 返回InstantiationModelAwarePointcutAdvisorImpl對象,類型是Advisor
- 如果是切面,最後把beanName加到aspectBeanNames(List類型,因為可以定義多個切面)中
- 核心過程見上述的源碼
-
解析業務邏輯類,獲取它的代理對象,獲取過程如下[核心過程見上述的源碼]:
- doCreateBea -> initializingBean -> applyBeanPostProcessorsAfterInitialization
- AbstractAutoProxyCreator#postProcessAfterInitialization
-
wrapIfNecessary 返回代理對象
- AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean,從屬性aspectBeanNames,advisorsCache中獲取,他們賦值的地方在(finishBeanFactoryInitialization中,當beanName是aopConfig時,resolveBeforeInstantiation中解析切面)
- extendAdvisors添加ExposeInvocationInterceptor.ADVISOR到集合的第一個
- 把當前bean存入advisedBeans
- createProxy
創建代理對象,把之前解析主配置類得到的advisors集合作為參數傳入,
在getProxy中,把ProxyCreatorSupport對象本身作為參數,傳入到DefaultAopProxyFactory#createAopProxy方法,返回ObjenesisCglibAopProxy對象(ProxyCreatorSupport對象作為參數),初始化ObjenesisCglibAopProxy的父類CglibAopProxy,設置advised的值為(ProxyCreatorSupport類型的對象,其中包含advisors集合)
- 創建ProxyFactory對象proxyFactory,依次實例化:AdvisedSupport(創建默認的DefaultAdvisorChainFactory對象),ProxyCreatorSupport(創建默認的DefaultAopProxyFactory對象)
- proxyFactory#getProxy
- createAopProxy(),如果當前bean是接口,則返回JdkDynamicAopProxy對象,否則,返回ObjenesisCglibAopProxy對象
- getProxy調用對應類的代理方法,生成bean的代理對象
Spring AOP攔截器鏈的生成
- 以Cglib動態代理為例,CglibAopProxy執行攔截器鏈的生成
-
當調用業務的邏輯方法時,代碼會進入CglibAopProxy的內部類DynamicAdvisedInterceptor,intercept方法
- 源碼;
@Override @Nullable 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); } } }
- 調用AdvisedSupport的方法
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) { MethodCacheKey cacheKey = new MethodCacheKey(method); List<Object> cached = this.methodCache.get(cacheKey); if (cached == null) { cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice( this, method, targetClass); this.methodCache.put(cacheKey, cached); } return cached; }
- 進入DefaultAdvisorChainFactory,主要是把前面解析得到的AspectJXXXAdvice集合,轉換為MethodInterceptor集合
@Override public List<Object> getInterceptorsAndDynamicInterceptionAdvice( Advised config, Method method, @Nullable Class<?> targetClass) { // This is somewhat tricky... We have to process introductions first, // but we need to preserve order in the ultimate list. AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance(); Advisor[] advisors = config.getAdvisors(); List<Object> interceptorList = new ArrayList<>(advisors.length); Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass()); Boolean hasIntroductions = null; for (Advisor advisor : advisors) { if (advisor instanceof PointcutAdvisor) { // Add it conditionally. PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor; if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) { MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher(); boolean match; if (mm instanceof IntroductionAwareMethodMatcher) { if (hasIntroductions == null) { hasIntroductions = hasMatchingIntroductions(advisors, actualClass); } match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions); } else { match = mm.matches(method, actualClass); } if (match) { MethodInterceptor[] interceptors = registry.getInterceptors(advisor); if (mm.isRuntime()) { // Creating a new object instance in the getInterceptors() method // isn't a problem as we normally cache created chains. for (MethodInterceptor interceptor : interceptors) { interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm)); } } else { interceptorList.addAll(Arrays.asList(interceptors)); } } } } else if (advisor instanceof IntroductionAdvisor) { IntroductionAdvisor ia = (IntroductionAdvisor) advisor; if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) { Interceptor[] interceptors = registry.getInterceptors(advisor); interceptorList.addAll(Arrays.asList(interceptors)); } } else { Interceptor[] interceptors = registry.getInterceptors(advisor); interceptorList.addAll(Arrays.asList(interceptors)); } } return interceptorList; }
- 轉換用到了DefaultAdvisorAdapterRegistry,支持3種適配轉換器:MethodBeforeAdviceAdapter,AfterReturningAdviceAdapter,ThrowsAdviceAdapter
@Override public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException { List<MethodInterceptor> interceptors = new ArrayList<>(3); Advice advice = advisor.getAdvice(); if (advice instanceof MethodInterceptor) { interceptors.add((MethodInterceptor) advice); } for (AdvisorAdapter adapter : this.adapters) { if (adapter.supportsAdvice(advice)) { interceptors.add(adapter.getInterceptor(advisor)); } } if (interceptors.isEmpty()) { throw new UnknownAdviceTypeException(advisor.getAdvice()); } return interceptors.toArray(new MethodInterceptor[0]); }
- MethodBeforeAdviceAdapter
@Override public boolean supportsAdvice(Advice advice) { return (advice instanceof MethodBeforeAdvice); } @Override public MethodInterceptor getInterceptor(Advisor advisor) { MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice(); return new MethodBeforeAdviceInterceptor(advice); }
- AfterReturningAdviceAdapter
@Override public boolean supportsAdvice(Advice advice) { return (advice instanceof AfterReturningAdvice); } @Override public MethodInterceptor getInterceptor(Advisor advisor) { AfterReturningAdvice advice = (AfterReturningAdvice) advisor.getAdvice(); return new AfterReturningAdviceInterceptor(advice); }
- ThrowsAdviceAdapter
@Override public boolean supportsAdvice(Advice advice) { return (advice instanceof ThrowsAdvice); } @Override public MethodInterceptor getInterceptor(Advisor advisor) { return new ThrowsAdviceInterceptor(advisor.getAdvice()); }
Spring AOP的調用過程
- MethodInvocation的鏈式生成過程,通過上一步獲取攔截器鏈之後,調用CglibMethodInvocation的proceed,觸發鏈式調用
-
調用過程運用的軟件設計模式是職責鏈模式
- 調用過程源碼:
- new CglibMethodInvocation()
public CglibMethodInvocation(Object proxy, @Nullable Object target, Method method, Object[] arguments, @Nullable Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers, MethodProxy methodProxy) { super(proxy, target, method, arguments, targetClass, interceptorsAndDynamicMethodMatchers); // Only use method proxy for public methods not derived from java.lang.Object this.methodProxy = (Modifier.isPublic(method.getModifiers()) && method.getDeclaringClass() != Object.class && !AopUtils.isEqualsMethod(method) && !AopUtils.isHashCodeMethod(method) && !AopUtils.isToStringMethod(method) ? methodProxy : null); }
- 調用父類ReflectiveMethodInvocation的構造函數
protected ReflectiveMethodInvocation( Object proxy, @Nullable Object target, Method method, @Nullable Object[] arguments, @Nullable Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers) { this.proxy = proxy; this.target = target; this.targetClass = targetClass; this.method = BridgeMethodResolver.findBridgedMethod(method); this.arguments = AopProxyUtils.adaptArgumentsIfNecessary(method, arguments); this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers; }
- 開始調用CglibMethodInvocation的proceed方法
@Override @Nullable public Object proceed() throws Throwable { try { return super.proceed(); } catch (RuntimeException ex) { throw ex; } catch (Exception ex) { if (ReflectionUtils.declaresException(getMethod(), ex.getClass()) || KotlinDetector.isKotlinType(getMethod().getDeclaringClass())) { // Propagate original exception if declared on the target method // (with callers expecting it). Always propagate it for Kotlin code // since checked exceptions do not have to be explicitly declared there. throw ex; } else { // Checked exception thrown in the interceptor but not declared on the // target method signature -> apply an UndeclaredThrowableException, // aligned with standard JDK dynamic proxy behavior. throw new UndeclaredThrowableException(ex); } } }
- 調用父類ReflectiveMethodInvocation的proceed方法,不斷地從增強器中獲取增強器,在ReflectiveMethodInvocation與子類CglibMethodInvocation來回調用,而且通過在各個MethodInterceptor實現類中實現鏈式調用
@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); } }
- 按照調用棧從底向上,依次為ExposeInvocationInterceptor:
@Override @Nullable public Object invoke(MethodInvocation mi) throws Throwable { MethodInvocation oldInvocation = invocation.get(); invocation.set(mi); try { return mi.proceed(); } finally { invocation.set(oldInvocation); } }
- AspectJAroundAdvice(如果有環繞通知)
@Override @Nullable public Object invoke(MethodInvocation mi) throws Throwable { if (!(mi instanceof ProxyMethodInvocation)) { throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi); } ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi; ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi); JoinPointMatch jpm = getJoinPointMatch(pmi); return invokeAdviceMethod(pjp, jpm, null, null); }
- MethodBeforeAdviceInterceptor
@Override @Nullable public Object invoke(MethodInvocation mi) throws Throwable { this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis()); return mi.proceed(); }
- AspectJAfterAdvice
@Override @Nullable public Object invoke(MethodInvocation mi) throws Throwable { try { return mi.proceed(); } finally { invokeAdviceMethod(getJoinPointMatch(), null, null); } }
- AfterReturningAdviceInterceptor
@Override @Nullable public Object invoke(MethodInvocation mi) throws Throwable { Object retVal = mi.proceed(); this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis()); return retVal; }
- AspectJAfterThrowingAdvice
@Override @Nullable public Object invoke(MethodInvocation mi) throws Throwable { try { return mi.proceed(); } catch (Throwable ex) { if (shouldInvokeOnThrowing(ex)) { invokeAdviceMethod(getJoinPointMatch(), null, ex); } throw ex; } }
- 當增強器都遍歷完,則調用業務方法
// We start with an index of -1 and increment early. if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return invokeJoinpoint(); }
- 最後依次出棧,完成整個鏈式調用
AOP運用的設計模式
- 職責鏈模式的出現背景是:把請求的發起者與處理者解耦,也就是說,客戶端只管發送請求,至於請求該誰處理由請求鏈決定
- 狀態模式與職責鏈的不同在於:狀態的改變條件,在類中是已經寫好的,無法在客戶端靈活設置
- AOP攔截器鏈的執行過程,請求處理者的攔截器鏈是在切面中定義,可以靈活設置,請求沿著鏈傳遞(只是aop約定好了前置、後置、正常返回,異常返回這些切面邏輯)
總結
-
AOP攔截器鏈的執行,運用的軟件設計模式
- 責任鏈模式
-
攔截器鏈advisor轉換為MethodInterceptor的邏輯
-
實現了MethodInterceptor接口
- AspectJAfterThrowingAdvice
- AspectJAfterAdvice
-
未實現MethodInterceptor接口
- AspectJAfterReturningAdvice
- AspectJMethodBeforeAdvice
-
-
BeanFactoryAspectJAdvisorsBuilder中的advisorsCache在何時賦值?
- BeanFactoryAspectJAdvisorsBuilder的buildAspectJAdvisors方法,同步塊雙重檢查鎖定中,先獲取advisors,然後put到cache中
待細化
- ReflectiveAspectJAdvisorFactory中的getAdvisorMethods()對切面中定義的@Befre/@Around/@After/@AfterReturning/@AfterThrowing註解標註的方法排序
-
使用
- AspectJ指示器:execution/@args/@annotations......
- @AfterReturning可設置returing()屬性
- @AfterThrowing可以設置throwing()屬性
- @Around註解以及標註的方法的調用邏輯
- 多切面,多個被攔截方法