Just began to see the source code, a lot of places do not understand deep, this article is suitable as a beginner’s tutorial. Welcome your advice:)

Zero, terms and concepts

1.1 Advisor

  • ==Advisor== a combination of ==PointCut==, ==Advice==, is the top-level abstraction of Spring Aop.

  • There are two main inheritance systems: PointCutAdvisor and cloud advisor

  • IntroductionAdvisor: Only applicable to class-level interceptions.


One, the introduction of AOP functionality – AnnotationAwareAspectJAutoProxyCreator

Aop functionality is introduced by @enableAspectJAutoProxy

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
	boolean proxyTargetClass(a) default false;
	boolean exposeProxy(a) default false;
}
Copy the code
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
	@Override
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
	
	    / / register AnnotationAwareAspectJAutoProxyCreator, see the following code
		AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
		
		AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
		
		if(enableAspectJAutoProxy ! =null) {
			if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
				AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
			}
			if (enableAspectJAutoProxy.getBoolean("exposeProxy")) { AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry); }}}}@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, @Nullable Object source) {
    / / register AnnotationAwareAspectJAutoProxyCreator
	return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
Copy the code


The function of aop is mainly provided by the = = AnnotationAwareAspectJAutoProxyCreator = =, its inheritance diagram is as follows:


Can see AnnotationAwareAspectJAutoProxyCreator BeanPoseProcessor parent. Have postProcessorAfterInitialization BeanPostProcessor interface method, will be called after the bean is initialized.

public interface BeanPostProcessor {
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Nullable
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        returnbean; }}Copy the code

Second, build advisors that apply to beans

As a wholeThe flow chartAs follows:

Known by the first quarter, the entry for AnnotationAwareAspectJAutoProxyCreator# postProcessorAfterInitailization

AbstractAutoProxyCreator:

= = = postProcessAfterInitialization:public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
	if(bean ! =null) {
		Object cacheKey = getCacheKey(bean.getClass(), beanName);
		if (this.earlyProxyReferences.remove(cacheKey) ! = bean) {// This method determines whether the bean needs to be proxied
			returnwrapIfNecessary(bean, beanName, cacheKey); }}returnbean; } = = = wrapIfNecessary:protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
	// Whether the current bean exists in the targetSourcedBeans cache (already processed) or returns if it does
	/ / targetSourcedBeans. Add in beforePostProcessInitialization ()
	if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
		return bean;
	}
	if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
		return bean;
	}
	// Beans are aop base classes or should be skipped
	if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}
	
	// Attention, see code1
	// Action: Get the advisor or advice for the bean
	/ / in AbstractAdvisorAutoProxyCreator specific logic
	Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
	
	// The bean needs to be proxied
	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;
}
Copy the code


Code1 – Advisor to obtain the process – AbstractAdvisorAutoProxyCreator# getAdvicesAndAdvisorsForBean

// Find a valid Advisor on the bean
protected List<Advisor> findEligibleAdvisors(Class
        beanClass, String beanName) {
    / / this method in AnnotationAwareAspectJAutoProxyCreator subclass implementation
	List<Advisor> candidateAdvisors = findCandidateAdvisors();
	
	// Find the advisor in the advisor that applies to the current bean
	// See section code2
	List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
	
	/ / in front of the interceptor chain add ExposeInvocationInterceptor DefaultPointcutAdvisor ADVISOR
	extendAdvisors(eligibleAdvisors);
	
	if(! eligibleAdvisors.isEmpty()) { eligibleAdvisors = sortAdvisors(eligibleAdvisors); }return eligibleAdvisors;
}

/ / AnnotationAwareAspectJAutoProxyCreator subclass implementation
protected List<Advisor> findCandidateAdvisors(a) {
    // Get advisors' attention
    List<Advisor> advisors = super.findCandidateAdvisors();
    if (this.aspectJAdvisorsBuilder ! =null) {
        advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
    }
    return advisors;
}
Copy the code


1. findCandidateAdvisors

Then see findCandidateAdvisors () = = the concrete implementation in BeanFactoryAdvisorRetrievalHelper# findAdvisorBeans = =

protected List<Advisor> findCandidateAdvisors(a) {
    / / for advisors
    List<Advisor> advisors = super.findCandidateAdvisors();
    
    // Build the advisor for the bean factory
    if (this.aspectJAdvisorsBuilder ! =null) {
        advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
    }
    return advisors;
}
Copy the code


2. buildAspectJAdvisors

BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors:

public List<Advisor> buildAspectJAdvisors(a) {
	List<String> aspectNames = this.aspectBeanNames;
	
	/ * * this. AspectBeanNames cache is empty, that is not treated, to perform the following logic * in postProcessBeforeInstantiation into this method, Cache is null * after postProcessAfterInstantiation process, the cache is not null * /
	if (aspectNames == null) {
		synchronized (this) {
			aspectNames = this.aspectBeanNames;
			if (aspectNames == null) {
				List<Advisor> advisors = new ArrayList<>();
				aspectNames = new ArrayList<>();
				
				/* * The object. class argument is used to fetch all beans. * This method is time-consuming, so Spring sets up a caching mechanism here * this.aspectBeannames */
				String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true.false);
				
				// Then iterate over the beanName
				for (String beanName : beanNames) {
					// Skip illegal beanName
					if(! isEligibleBean(beanName)) {continue; }
					
					// Get the class information from beanNameClass<? > beanType =this.beanFactory.getType(beanName);
					
					if (beanType == null) { continue; }
					
					// Process classes marked with AspectJ annotations
					if (this.advisorFactory.isAspect(beanType)) {
						// add cache
						aspectNames.add(beanName);
						
						AspectMetadata amd = new AspectMetadata(beanType, beanName);
						if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
							/ actual type is BeanFactoryAspectInstanceFactory * * * according to beanName beanName, find the corresponding class attribute * class encapsulated into AspectMetadata * /
							MetadataAwareAspectInstanceFactory factory = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
							
							/** * parses the interceptor method to generate the enhancer ** using the beanName in factory, gets its class information, and then * 1. parsing@pointCutOn the expression of encapsulated into AspectJExpressionPointcut * 2. To obtain@Before,@AfterMethods, such as encapsulated into a Method * 3. The above parameters are encapsulated into InstantiationModelAwarePointcutAdvisorImpl, A subclass of the Advisor * * specific implementation in ReflectiveAspectJAdvisorFactory# getAdvisors * in order not to affect the analysis of the overall process, the concrete implementation of this method in the * / at the end of the article
							List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
							
							// The singleton directly puts the resolved enhancement method into the cache
							if (this.beanFactory.isSingleton(beanName)) {
								this.advisorsCache.put(beanName, classAdvisors);
							}
							
							// If not singleton, cache factory
							else {
								this.aspectFactoryCache.put(beanName, factory);
							}
							
							advisors.addAll(classAdvisors);
						}
						else {
							if (this.beanFactory.isSingleton(beanName)) {
								throw new IllegalArgumentException("");
							}
							MetadataAwareAspectInstanceFactory factory = new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
							this.aspectFactoryCache.put(beanName, factory);
							advisors.addAll(this.advisorFactory.getAdvisors(factory)); }}}this.aspectBeanNames = aspectNames;
				returnadvisors; }}}if (aspectNames.isEmpty()) {
		return Collections.emptyList();
	}
	List<Advisor> advisors = new ArrayList<>();
	for (String aspectName : aspectNames) {
		List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
		if(cachedAdvisors ! =null) {
			advisors.addAll(cachedAdvisors);
		}
		else {
			MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
			advisors.addAll(this.advisorFactory.getAdvisors(factory)); }}return advisors;
}
Copy the code


2. findAdvisorsThatCanApply

AopUtils# findAdvisorsThatCanApply:

/ * * *@paramCandidateAdvisors is returned in the previous step findCandidateAdvisor, that is, all advisors *@param clazz beanClass
 */
public static List<Advisor> findAdvisorsThatCanApply(List
       
         candidateAdvisors, Class
         clazz)
        {
	if (candidateAdvisors.isEmpty()) {
		return candidateAdvisors;
	}
	
	List<Advisor> eligibleAdvisors = new ArrayList<>();
	for (Advisor candidate : candidateAdvisors) {
	    // Introduction enhancement
		if (candidate instanceofIntroductionAdvisor && canApply(candidate, clazz)) { eligibleAdvisors.add(candidate); }}booleanhasIntroductions = ! eligibleAdvisors.isEmpty();for (Advisor candidate : candidateAdvisors) {
		if (candidate instanceof IntroductionAdvisor) {
			// already processed
			continue;
		}
		
		// Plain enhanced PointcutAdvisor
		if(canApply(candidate, clazz, hasIntroductions)) { eligibleAdvisors.add(candidate); }}return eligibleAdvisors;
}
Copy the code

   AopUtils#canApply:

public static boolean canApply(Pointcut pc, Class<? > targetClass,boolean hasIntroductions) {
	if(! pc.getClassFilter().matches(targetClass)) {return false;
	}
	
	MethodMatcher methodMatcher = pc.getMethodMatcher();
	if (methodMatcher == MethodMatcher.TRUE) {
		return true;
	}
	
	/ / AspectJExpressionPointcut, tangent point expression matcher
	IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
	if (methodMatcher instanceofIntroductionAwareMethodMatcher) { introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher; } Set<Class<? >> classes =new LinkedHashSet<>();
	if(! Proxy.isProxyClass(targetClass)) { classes.add(ClassUtils.getUserClass(targetClass)); } classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));for(Class<? > clazz : classes) { Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);for (Method method : methods) {
		    // If the pointcut expression matcher is not null, the pointcut expression match is used
			if(introductionAwareMethodMatcher ! =null ? introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) : methodMatcher.matches(method, targetClass)) {
				return true; }}}return false;
}
Copy the code


Generate proxy objects

Go back to ==AbstractAutoProxyCreator#wrapIfNecessary==. In this method, there are two important processes:

  1. Get the Advisor on the bean
  2. Generate a proxy object with the obtained Advisor as a parameter

  AbstractAutoProxyCreator#wrapIfNecessary:

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
	// Whether the current bean exists in the targetSourcedBeans cache (already processed) or returns if it does
	/ / targetSourcedBeans. Add in beforePostProcessInitialization ()
	if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
		return bean;
	}
	if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
		return bean;
	}
	// Beans are aop base classes or should be skipped
	if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}
	
	Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
	
	if(specificInterceptors ! = DO_NOT_PROXY) {this.advisedBeans.put(cacheKey, Boolean.TRUE);
		
		// Generate a proxy object
		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;
}
Copy the code


This method creates a proxy for the bean, delegating the proxy creation to the proxyFactory, which initializes the proxyFactory. The main points are as follows:

  • Copy attributes
  • SetProxyTargetClass () to determine how the proxy works
  • Adding a Proxy Interface
  • Packaging advisor
  • Execute the custom function customizeProxyFactory()
  • To create the agent
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);
	}
	
	ProxyFactory proxyFactory = new ProxyFactory();
	proxyFactory.copyFrom(this);
	
	// proxyTargetClass defaults to false, true to use CGLib proxy, false to use JDK dynamic proxy
	if(! proxyFactory.isProxyTargetClass()) {// Determine whether the CGLib proxy is based on the class proxy
		if (shouldProxyTargetClass(beanClass, beanName)) {
			proxyFactory.setProxyTargetClass(true);
		}else {
		    // For further evaluation of the proxy interface, see codeevaluateProxyInterfaces(beanClass, proxyFactory); }}// Wrap the interceptor as advisor, see code
	Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
	
	proxyFactory.addAdvisors(advisors);
	proxyFactory.setTargetSource(targetSource);
	
	//
	customizeProxyFactory(proxyFactory);
	
	proxyFactory.setFrozen(this.freezeProxy);
	
	if (advisorsPreFiltered()) {
		proxyFactory.setPreFiltered(true);
	}
	
	/ / call getProxy ()
	return proxyFactory.getProxy(getProxyClassLoader());
}
Copy the code


Code2 — construct advisor abstractautoxyxy# buildAdvisors

In this approach, all interceptors are wrapped as advisors

protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
	// Parse the public interceptor
	Advisor[] commonInterceptors = resolveInterceptorNames();
	
	List<Object> allInterceptors = new ArrayList<>();
	if(specificInterceptors ! =null) {
		allInterceptors.addAll(Arrays.asList(specificInterceptors));
		// Determine the priority
		if (commonInterceptors.length > 0) {
			if (this.applyCommonInterceptorsFirst) {
				allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
			}
			else {
				allInterceptors.addAll(Arrays.asList(commonInterceptors));
			}
		}
	}

	Advisor[] advisors = new Advisor[allInterceptors.size()];
	for (int i = 0; i < allInterceptors.size(); i++) {
	    // Wrap the interceptor as an advisor
	    // DefaultAdvisorAdapterRegistry.wrap()
		advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
	}
	return advisors;
}
Copy the code


Continue to look at the packaging process, enclosing advisorAdapterRegistry real object for = = DefaultAdvisorAdapterRegistry = =.

DefaultAdvisorAdapterRegistry#wrap:

public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
	if (adviceObject instanceof Advisor) {
		return (Advisor) adviceObject;
	}
	if(! (adviceObjectinstanceof Advice)) {
		throw new UnknownAdviceTypeException(adviceObject);
	}
	
	Advice advice = (Advice) adviceObject;
	
	Rear / * * notice: AspectJAfterAdvice, pre inform: MethodBeforeAdviceInterceptor * is MethodInterceptor subclass * /
	if (advice instanceof MethodInterceptor) {
		return new DefaultPointcutAdvisor(advice);
	}
	for (AdvisorAdapter adapter : this.adapters) {
		// Check that it is supported.
		if (adapter.supportsAdvice(advice)) {
			return newDefaultPointcutAdvisor(advice); }}throw new UnknownAdviceTypeException(advice);
}
Copy the code


Code3 — Create proxy — ProxyFactory

public Object getProxy(@Nullable ClassLoader classLoader) {
	return createAopProxy().getProxy(classLoader);
}
Copy the code

DefaultAopProxyFactory#createAopProxy

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
	/* * CGLib agent * optimize: Used to control whether agents created with CGLib use aggressive optimization strategies. Unless you fully understand how AOP handles proxy optimization, * isProxyTargetClass: defaults to false and can be configured manually. When true, force the CGLib proxy * config: ProxyFactory * hasNoUserSuppliedProxyInterfaces: determine whether realized interface * /
	if(! IN_NATIVE_IMAGE && (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) { Class<? > targetClass = config.getTargetClass();if (targetClass == null) {
			throw new AopConfigException("xxx");
		}
		
		/ * * to be agent of object is the interface | | targetClass is the Proxy class * to use the JDK dynamic Proxy * /
		if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
			return new JdkDynamicAopProxy(config);
		}
		
		return new ObjenesisCglibAopProxy(config);
	}
	else {
		return newJdkDynamicAopProxy(config); }}Copy the code

This method selects the proxy mode based on the situation:

  • The JDK dynamic proxy is chosen by default if the bean implements the interface, but you can force the CGLib proxy by configuring proxyTargetClass=true
  • Beans do not implement interfaces and can only use CGLib proxies


Four, invoke

1. JdkDynamicAopProxy

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
	Object oldProxy = null;
	boolean setProxyContext = false;
	TargetSource targetSource = this.advised.targetSource;
	Object target = null;
	
	try {
		if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
			return equals(args[0]);
		}
		else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
			return hashCode();
		}
		else if (method.getDeclaringClass() == DecoratingProxy.class) {
			return AopProxyUtils.ultimateTargetClass(this.advised);
		}
		else if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) {
			return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
		}
		
		Object retVal;
		if (this.advised.exposeProxy) {
			oldProxy = AopContext.setCurrentProxy(proxy);
			setProxyContext = true; } target = targetSource.getTarget(); Class<? > targetClass = (target ! =null ? target.getClass() : null);
		
		// Get the interceptor chain, done by advisorChainFactory
		/ / code
		List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
		if (chain.isEmpty()) {
			Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
			retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
		}
		else {
		    // Chain is wrapped in MethodInvocation
			MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
			// For detailed analysis, see coderetVal = invocation.proceed(); } Class<? > returnType = method.getReturnType();if(retVal ! =null&& retVal == target && returnType ! = Object.class && returnType.isInstance(proxy) && ! RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { retVal = proxy; }else if (retVal == null&& returnType ! = Void.TYPE && returnType.isPrimitive()) {throw new AopInvocationException("Null return value from advice does not match primitive return type for: " + method);
		}
		
		return retVal;
	} finally {
		if(target ! =null && !targetSource.isStatic()) {
			targetSource.releaseTarget(target);
		}
		if(setProxyContext) { AopContext.setCurrentProxy(oldProxy); }}}Copy the code


Code4 – ReflectiveMethodInvocation

public Object proceed(a) throws Throwable {
    / / this. CurrentInterceptorIndex initialized to 1
	if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
		return invokeJoinpoint();
	}
	
	/ / in this interceptor in the chain, the index for ExposeInvocationInterceptor = 0
	Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
	
	if (interceptorOrInterceptionAdvice instanceofInterceptorAndDynamicMethodMatcher) { 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.
			returnproceed(); }}else {
		/* * When the advisor is fetched, different implementation classes are returned according to the notification type, as shown in paragraph 5. * The invoke method of the corresponding implementation class is invoked * * before: MethodBeforeAdviceInterceptor * after: AspectJAfterAdvice @ * * param this above new ReflectiveMethodInvocation (). The proceed () * /
		return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); }}Copy the code


2. CGLib


= = pre notice = = MethodBeforeAdviceInterceptor:

public Object invoke(MethodInvocation mi) throws Throwable {
	this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
	return mi.proceed();
}
Copy the code


== Afteradvice == AspectJAfterAdvice:

public Object invoke(MethodInvocation mi) throws Throwable {
	try {
	    // Execute the method ontology first
		return mi.proceed();
	}finally {
		invokeAdviceMethod(getJoinPointMatch(), null.null); }}Copy the code


Fifth, the specific process of Advisor acquisition

BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors

See 2 in Code1 for the main process:

  1. Get all beanName
  2. Walk through the beanName to find the beanName that has an @AspectJ annotation
  3. For beanName with @AspectJ annotations, parse the enhancements, such as @after, @before
  4. Add the results from step 3 to the cache

1. ReflectiveAspectJAdvisorFactory#getAdvisors

ReflectiveAspectJAdvisorFactory#getAdvisors:

public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
	// Get the name and class of the aspectClass<? > aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass(); String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName(); validate(aspectClass);// Wrap this aspectInstanceFactory so that it is instantiated only once
	MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory = new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
	
	List<Advisor> advisors = new ArrayList<>();
	// getAdvisorMethods(), which reflects all advice methods in the cut that are not annotated by the @pointcut annotation
	for (Method method : getAdvisorMethods(aspectClass)) {
		// Generate the enhancer, as shown in the code below
		Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
		if(advisor ! =null) { advisors.add(advisor); }}if(! advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) { Advisor instantiationAdvisor =new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
		advisors.add(0, instantiationAdvisor);
	}
	
	for (Field field : aspectClass.getDeclaredFields()) {
		Advisor advisor = getDeclareParentsAdvisor(field);
		if(advisor ! =null) { advisors.add(advisor); }}return advisors;
}
Copy the code

ReflectiveAspectJAdvisorFactory#getAdvisor:

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; }
	
	/ / by InstantiationModelAwarePointcutAdvisorImpl unified encapsulation
	return new InstantiationModelAwarePointcutAdvisorImpl(
			expressionPointcut, candidateAdviceMethod, this,
			aspectInstanceFactory, declarationOrderInAspect, aspectName
	);
}
Copy the code


Continue to look at InstantiationModelAwarePointcutAdvisorImpl constructor:

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;
		
		//
		this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut); }}private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {

    / / here specific implementation in ReflectiveAspectJAdvisorFactory# getAdvice
	Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut, this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
	return(advice ! =null ? advice : EMPTY_ADVICE);
}
/ * *Copy the code


Continue with the getAdvice method, where different implementation classes are returned depending on the type of the annotation

  • AspectJMethodBeforeAdvice
  • AspectJAroundAdvice
  • AspectJAfterAdvice
  • AspectJAfterReturningAdvice

ReflectiveAspectJAdvisorFactory#getAdvice:

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();
	}
	if (logger.isDebugEnabled()) {
		logger.debug();
	}
	
	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;
}
Copy the code