1. 程式人生 > 程式設計 >Spring AOP原始碼實現分步解析

Spring AOP原始碼實現分步解析

1 概述

1.1 示例

最基本的使用,在建立了業務介面和實現類後,通過配置<aop:config>....</aop:config>標籤來指定<aop:pointcut<aop:advisor。示例如下:

1.1.1 建立介面及實現類

介面

public interface MockService {
    public String hello(String s);
}
複製程式碼

實現類

public class MockServiceImpl implements MockService {
    @Override
    public String hello
(String s)
{ System.out.println("execute hello"); return s; } } 複製程式碼

1.1.2 實現方法攔截

實現介面org.aopalliance.intercept.MethodInterceptor

public class CustomInterceptor implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("CustomInterceptor before"
); Object result = invocation.proceed(); System.out.println("CustomInterceptor after"); return result; } } 複製程式碼

1.1.3 配置xml

建立aop.xml,放在resources目錄下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd" default-lazy-init="false" default-autowire="byName">
<!-- 實現來org.aopalliance.intercept.MethodInterceptor的攔截器 --> <bean id="customInterceptor" class="com.xxx.yyy.CustomInterceptor"/> <bean id="mockService" class="com.xxx.yyy.MockServiceImpl"/> <aop:config proxy-target-class="true"> <aop:pointcut id="interceptorPointCuts" expression="execution(* com.xxx.yyy..*.*(..))"/> <aop:advisor advice-ref="customInterceptor" pointcut-ref="interceptorPointCuts"/> </aop:config> </beans> 複製程式碼

1.1.4 執行

public class Main {

    public static void main(String[] args){
        ApplicationContext context = new ClassPathXmlApplicationContext("aop.xml");
        MockService mockService = (MockService) context.getBean("mockService");
        mockService.hello("mock");
    }
}
複製程式碼

返回:

CustomInterceptor before
execute hello
CustomInterceptor after
複製程式碼

1.2 AOP實現過程

Spring環境啟動過程中,會呼叫AbstractApplicationContext.refresh(),AOP的實現流程,也就是從這裡開始。

  • 1 在obtainFreshBeanFactory()執行過程中,載入aop.xml,並根據namespace找到aop對應的NamespaceHandlerAopNamespaceHandler
  • 2 AopNamespaceHandler中,找到config標籤對應的BeanDefinitionParser的實現物件,也就是ConfigBeanDefinitionParser
  • 3 執行ConfigBeanDefinitionParser.parse,有兩個作用:
    1. AspectJAwareAdvisorAutoProxyCreator註冊BeanDefinition;
    2. 解析pointcutadvisor等標籤,並將相關物件註冊為BeanDefinition。
  • 4 註冊BeanPostProcessor:AspectJAwareAdvisorAutoProxyCreator是BeanPostProcessor的實現類AbstractAutoProxyCreator的子類。註冊BeanPostProcessor後,AspectJAwareAdvisorAutoProxyCreator會在Spring建立bean的代理過程中呼叫。
  • 5 建立proxy,並用advisor增強,主要有幾步:
    1. 建立代理;
    2. 查詢匹配的advisor;
    3. 增強代理。

2 AopNamespaceHandler

Spring環境的載入,需要呼叫AbstractApplicationContext.refresh()。

在refresh()方法中,執行ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();建立BeanFacotry的時候,載入並解析xml資源。

在這個過程中,會呼叫BeanDefinitionParserDelegate.parseCustomElement進行擴充套件標籤的解析:

public BeanDefinition parseCustomElement(Element ele,BeanDefinition containingBd) {
                // 獲取namespace
		String namespaceUri = getNamespaceURI(ele);
		// 根據檔案META-INF/spring.handlers,獲取對應的NamespaceHandler
		NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
		if (handler == null) {
			error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]",ele);
			return null;
		}
		// 呼叫NamespaceHandler.parse方法,返回BeanDefinition
		return handler.parse(ele,new ParserContext(this.readerContext,this,containingBd));
	}

複製程式碼

詳細過程可參考Spring自定義標籤配置的原始碼解析與實現


對於<aop:config/>,Spring會根據xmlnsMETA-INF/spring.handlers檔案中查詢相應的namespace解析類: http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler

AopNamespaceHandler中: registerBeanDefinitionParser("config",new ConfigBeanDefinitionParser());

所以:

  • aopnamespace的解析類是AopNamespaceHandler
  • <aop:config/>標籤的解析類是ConfigBeanDefinitionParser,在 ConfigBeanDefinitionParser 中,<aop:config/>定義的各個元素被解析為 BeanDefinition

3 ConfigBeanDefinitionParser

ConfigBeanDefinitionParser實現了BeanDefinitionParser介面,在parse(Element element,ParserContext parserContext)方法中,實現了兩部分功能:

  • 1 向Spring環境註冊一個BeanDefinition:AspectJAwareAdvisorAutoProxyCreator
  • 2 將xml配置的pointcut,advisor等解析為一系列BeanDefinition。
@Override
	@Nullable
	public BeanDefinition parse(Element element,ParserContext parserContext) {
		CompositeComponentDefinition compositeDef =
				new CompositeComponentDefinition(element.getTagName(),parserContext.extractSource(element));
		parserContext.pushContainingComponent(compositeDef);

        // 註冊AspectJAwareAdvisorAutoProxyCreator為BeanDefinition
		configureAutoProxyCreator(parserContext,element);

		List<Element> childElts = DomUtils.getChildElements(element);
		for (Element elt: childElts) {
			String localName = parserContext.getDelegate().getLocalName(elt);
			if (POINTCUT.equals(localName)) {
			    // 解析pointcut
				parsePointcut(elt,parserContext);
			}
			else if (ADVISOR.equals(localName)) {
			    // 解析advisor
				parseAdvisor(elt,parserContext);
			}
			else if (ASPECT.equals(localName)) {
				parseAspect(elt,parserContext);
			}
		}

		parserContext.popAndRegisterContainingComponent();
		return null;
	}
複製程式碼

其中:

private static final String POINTCUT = "pointcut";
private static final String ADVISOR = "advisor";
private static final String ASPECT = "aspect";
複製程式碼

3.1 AspectJAwareAdvisorAutoProxyCreator

3.1.1 作用

  • AspectJAwareAdvisorAutoProxyCreatorAbstractAutoProxyCreator的子類;
  • AbstractAutoProxyCreator實現了介面BeanPostProcessor;
  • AbstractAutoProxyCreator在postProcessAfterInitialization的實現中,呼叫wrapIfNecessary進行bean代理。
@Override
	public Object postProcessAfterInitialization(@Nullable Object bean,String beanName) throws BeansException {
		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(),beanName);
			if (!this.earlyProxyReferences.contains(cacheKey)) {
				return wrapIfNecessary(bean,beanName,cacheKey);
			}
		}
		return bean;
	}
複製程式碼

Spring在例項化bean的過程中,會呼叫BeanPostProcessor對bean生成前後進行處理,aop利用這一點:

呼叫AbstractAutoProxyCreator.postProcessAfterInitialization方法,根據pointcut查詢到相應的advisor,對bean進行代理

3.1.2 註冊BeanDefinition

程式碼執行流程:

  • 1 ConfigBeanDefinitionParser.configureAutoProxyCreator;

  • 2 AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(parserContext,element);

    	public static void registerAspectJAutoProxyCreatorIfNecessary(
      		ParserContext parserContext,Element sourceElement) {
    
          // 註冊BeanDefinition
      	BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAutoProxyCreatorIfNecessary(
      			parserContext.getRegistry(),parserContext.extractSource(sourceElement));
      	// 設定class-proxy
      	useClassProxyingIfNecessary(parserContext.getRegistry(),sourceElement);
      	registerComponentIfNecessary(beanDefinition,parserContext);
      }
    複製程式碼
  • 3 AopConfigUtils.registerAspectJAutoProxyCreatorIfNecessary;

  • 4 AopConfigUtils.registerOrEscalateApcAsRequired:

public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
			"org.springframework.aop.config.internalAutoProxyCreator";
			
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
		////  省略程式碼
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME,beanDefinition);
複製程式碼

最終生成了AspectJAwareAdvisorAutoProxyCreator的BeanDefinition,beanName為 org.springframework.aop.config.internalAutoProxyCreator

同時,useClassProxyingIfNecessary方法中,根據**aop:config/**中的proxy-target-class,設定了AspectJAwareAdvisorAutoProxyCreator的一個父類ProxyConfigproxyTargetClass屬性。

3.2 解析pointcut

解析<aop:pointcut id="interceptorPointCuts" expression="execution(* com.xxx.yyy..*.*(..))"/>,註冊AbstractExpressionPointcut的BeanDefinition。

3.2.1 parsePointcut

	private AbstractBeanDefinition parsePointcut(Element pointcutElement,ParserContext parserContext) {
		String id = pointcutElement.getAttribute(ID);
		
		// 獲取表示式 配置中的 expression="execution(* com.xxx.yyy..*.*(..))"
		String expression = pointcutElement.getAttribute(EXPRESSION);

		AbstractBeanDefinition pointcutDefinition = null;
		try {
			this.parseState.push(new PointcutEntry(id));
			
			// 使用AspectJExpressionPointcut,為pointcut建立BeanDefinition,
			pointcutDefinition = createPointcutDefinition(expression);
			pointcutDefinition.setSource(parserContext.extractSource(pointcutElement));

			String pointcutBeanName = id;
			if (StringUtils.hasText(pointcutBeanName)) {
			     // 以id為beanName註冊AspectJExpressionPointcut為bean.
				parserContext.getRegistry().registerBeanDefinition(pointcutBeanName,pointcutDefinition);
			}
			else {
			    // 自動生成beanName註冊AspectJExpressionPointcut為bean.
				pointcutBeanName = parserContext.getReaderContext().registerWithGeneratedName(pointcutDefinition);
			}
			parserContext.registerComponent(
					new PointcutComponentDefinition(pointcutBeanName,pointcutDefinition,expression));
		}
		finally {
			this.parseState.pop();
		}

		return pointcutDefinition;
	}
複製程式碼

3.2.2 createPointcutDefinition

  • 1 aop:pointcut 解析為 AspectJExpressionPointcut物件。
  • 2 AspectJExpressionPointcut extends AbstractExpressionPointcut
  • 3 expressionAbstractExpressionPointcut的屬性
	protected AbstractBeanDefinition createPointcutDefinition(String expression) {
		RootBeanDefinition beanDefinition = new RootBeanDefinition(AspectJExpressionPointcut.class);
		beanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE);
		beanDefinition.setSynthetic(true);
		beanDefinition.getPropertyValues().add(EXPRESSION,expression);
		return beanDefinition;
	}
複製程式碼

3.3 解析advisor

解析<aop:advisor advice-ref="customInterceptor" pointcut-ref="interceptorPointCuts"/>,註冊DefaultBeanFactoryPointcutAdvisor的BeanDefinition。

3.3.1 parseAdvisor

  • 1 呼叫createAdvisorBeanDefinition建立advisor;
  • 2 呼叫parsePointcutProperty獲取pointcut。
	private void parseAdvisor(Element advisorElement,ParserContext parserContext) {
	
	    // 1 建立bean : DefaultBeanFactoryPointcutAdvisor
		AbstractBeanDefinition advisorDef = createAdvisorBeanDefinition(advisorElement,parserContext);
		String id = advisorElement.getAttribute(ID);

		try {
			this.parseState.push(new AdvisorEntry(id));
			String advisorBeanName = id;
			
			// 2 註冊bean : DefaultBeanFactoryPointcutAdvisor
			if (StringUtils.hasText(advisorBeanName)) {
				parserContext.getRegistry().registerBeanDefinition(advisorBeanName,advisorDef);
			}
			else {
				advisorBeanName = parserContext.getReaderContext().registerWithGeneratedName(advisorDef);
			}

            // 3 解析 pointcut-ref="interceptorPointCuts"
			Object pointcut = parsePointcutProperty(advisorElement,parserContext);
			if (pointcut instanceof BeanDefinition) {
			    // 返回的是有`pointcut`構造的BeanDefinition(AspectJExpressionPointcut物件),則設定`DefaultBeanFactoryPointcutAdvisor.pointcut = pointcut`
				advisorDef.getPropertyValues().add(POINTCUT,pointcut);
				parserContext.registerComponent(
						new AdvisorComponentDefinition(advisorBeanName,advisorDef,(BeanDefinition) pointcut));
			}
			else if (pointcut instanceof String) {
			   // 返回的是beanName,則設定`DefaultBeanFactoryPointcutAdvisor.pointcut`為一個執行時Bean引用。
				advisorDef.getPropertyValues().add(POINTCUT,new RuntimeBeanReference((String) pointcut));
				parserContext.registerComponent(
						new AdvisorComponentDefinition(advisorBeanName,advisorDef));
			}
		}
		finally {
			this.parseState.pop();
		}
	}
複製程式碼

3.3.2 createAdvisorBeanDefinition

  • 1 建立DefaultBeanFactoryPointcutAdvisor的BeanDefinition,DefaultBeanFactoryPointcutAdvisor是PointcutAdvisor的一個實現;
  • 2 解析advice-ref獲取advisor的Bean的beanName,即aop.xml中的customInterceptor。
  • 3 DefaultBeanFactoryPointcutAdvisor extends AbstractBeanFactoryPointcutAdvisor,使用advice-ref設定adviceBeanName屬性,即前面的customInterceptor
    private static final String ADVICE_BEAN_NAME = "adviceBeanName";
    
	private AbstractBeanDefinition createAdvisorBeanDefinition(Element advisorElement,ParserContext parserContext) {
	
	    // 建立`DefaultBeanFactoryPointcutAdvisor`的BeanDefinition;
		RootBeanDefinition advisorDefinition = new RootBeanDefinition(DefaultBeanFactoryPointcutAdvisor.class);
		advisorDefinition.setSource(parserContext.extractSource(advisorElement));

        // 解析`advice-ref`獲取advice的Bean的beanName;
		String adviceRef = advisorElement.getAttribute(ADVICE_REF);
		if (!StringUtils.hasText(adviceRef)) {
			parserContext.getReaderContext().error(
					"'advice-ref' attribute contains empty value.",advisorElement,this.parseState.snapshot());
		}
		else {
		    // 設定AbstractBeanFactoryPointcutAdvisor的adviceBeanName屬性
			advisorDefinition.getPropertyValues().add(
					ADVICE_BEAN_NAME,new RuntimeBeanNameReference(adviceRef));
		}

		if (advisorElement.hasAttribute(ORDER_PROPERTY)) {
			advisorDefinition.getPropertyValues().add(
					ORDER_PROPERTY,advisorElement.getAttribute(ORDER_PROPERTY));
		}

		return advisorDefinition;
	}
複製程式碼

3.3.3 parsePointcutProperty

  • 1 屬性有pointcut,則使用expression呼叫createPointcutDefinition,構造AspectJExpressionPointcut的bean後直接返回。
  • 2 否則返回pointcut-ref指定的bean作為Pointcut。

所以:pointcut優先於 pointcut-ref,有pointcut就不再解析pointcut-ref

	private Object parsePointcutProperty(Element element,ParserContext parserContext) {
		if (element.hasAttribute(POINTCUT) && element.hasAttribute(POINTCUT_REF)) {
			parserContext.getReaderContext().error(
					"Cannot define both 'pointcut' and 'pointcut-ref' on <advisor> tag.",element,this.parseState.snapshot());
			return null;
		}
		else if (element.hasAttribute(POINTCUT)) {
			
			// 屬性有`pointcut`,則使用expression呼叫createPointcutDefinition,構造AspectJExpressionPointcut的bean後直接返回。
			String expression = element.getAttribute(POINTCUT);
			AbstractBeanDefinition pointcutDefinition = createPointcutDefinition(expression);
			pointcutDefinition.setSource(parserContext.extractSource(element));
			
			// 返回BeanDefinition
			return pointcutDefinition;
		}
		else if (element.hasAttribute(POINTCUT_REF)) {
			String pointcutRef = element.getAttribute(POINTCUT_REF);
			if (!StringUtils.hasText(pointcutRef)) {
				parserContext.getReaderContext().error(
						"'pointcut-ref' attribute contains empty value.",this.parseState.snapshot());
				return null;
			}
			// 返回pointcut-ref的beanName
			return pointcutRef;
		}
		else {
			parserContext.getReaderContext().error(
					"Must define one of 'pointcut' or 'pointcut-ref' on <advisor> tag.",this.parseState.snapshot());
			return null;
		}
	}
複製程式碼

3.4 解析過程中註冊的BeanDefinition

  • BeanPostProcessor : AspectJAwareAdvisorAutoProxyCreator,beanName是org.springframework.aop.config.internalAutoProxyCreator
  • pointcut:AbstractExpressionPointcut,設定了expression屬性;
  • advisor:DefaultBeanFactoryPointcutAdvisor,pointcut屬性設定為AbstractExpressionPointcut

4 註冊BeanPostProcessor

在AbstractApplicationContext.refresh()方法中,建立ConfigurableListableBeanFactory後,會執行registerBeanPostProcessors向Spring環境註冊BeanPostProcessor

// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
複製程式碼

AspectJAwareAdvisorAutoProxyCreator 在這個時候被加入到用於處理bean建立的BeanPostProcessor列表中。

簡要過程如下:

  • 1 呼叫PostProcessorRegistrationDelegate.registerBeanPostProcessors
  • 2 通過beanFactory.getBean(ppName,BeanPostProcessor.class);獲取BeanPostProcessor列表;
  • 3 執行beanFactory.addBeanPostProcessor(postProcessor)

5 建立Bean並增強

5.1 createProxy

Spring建立Bean,是在AbstractAutowireCapableBeanFactory.doCreateBean方法中:

  1. AbstractAutowireCapableBeanFactory.doCreateBean中呼叫了initializeBean
// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			populateBean(beanName,mbd,instanceWrapper);
			exposedObject = initializeBean(beanName,exposedObject,mbd);
		}
		catch (Throwable ex) {
			if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
				throw (BeanCreationException) ex;
			}
			else {
				throw new BeanCreationException(
						mbd.getResourceDescription(),"Initialization of bean failed",ex);
			}
		}
複製程式碼
  1. initializeBean中:
if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean,beanName);
		}
複製程式碼
  1. applyBeanPostProcessorsAfterInitialization執行了BeanPostProcessor.postProcessAfterInitialization方法:
@Override
	public Object applyBeanPostProcessorsAfterInitialization(Object existingBean,String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
			Object current = beanProcessor.postProcessAfterInitialization(result,beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}
複製程式碼
  1. AbstractAutoProxyCreator.postProcessAfterInitialization就在這裡執行:
@Override
	public Object postProcessAfterInitialization(@Nullable Object bean,cacheKey);
			}
		}
		return bean;
	}
複製程式碼
  1. wrapIfNecessary中使用advisor執行createProxy:
// Create proxy if we have advice.

        // 1 查詢advisor
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(),null);
		if (specificInterceptors != DO_NOT_PROXY) {
			this.advisedBeans.put(cacheKey,Boolean.TRUE);
			// 2 建立proxy,並使用advisor進行增強
			Object proxy = createProxy(
					bean.getClass(),specificInterceptors,new SingletonTargetSource(bean));
			this.proxyTypes.put(cacheKey,proxy.getClass());
			return proxy;
		}
複製程式碼

5.2 查詢匹配的advisor

AbstractAutoProxyCreator.getAdvicesAndAdvisorsForBean是一個抽象方法,由子類AbstractAdvisorAutoProxyCreator實現。

AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean呼叫了findEligibleAdvisors,主要實現兩個流程:

  • 1 獲取候選的advisors;
  • 2 過濾出匹配的advisors。
    /*
    beanClass:要代理的類
    beanName:當前要代理的bean的beanName
    */
	protected List<Advisor> findEligibleAdvisors(Class<?> beanClass,String beanName) {
	    // 1 獲取候選的advisors
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
		// 2 過濾出匹配的advisors
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors,beanClass,beanName);
		extendAdvisors(eligibleAdvisors);
		if (!eligibleAdvisors.isEmpty()) {
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}
		return eligibleAdvisors;
	}
複製程式碼

5.2.1 findCandidateAdvisors

呼叫BeanFactoryAdvisorRetrievalHelper.findAdvisorBeans,獲取到所有實現了Advisor介面的Bean,主要程式碼片段如下:

  • 1 找到是有實現了Advisor介面的beanName:

    advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory,Advisor.class,true,false);

  • 2 根據beanName獲取Bean:

    List<Advisor> advisors = new LinkedList<>();
    ....
    advisors.add(this.beanFactory.getBean(name,Advisor.class));
    ....
    return advisors;
    複製程式碼

5.2.2 findAdvisorsThatCanApply

過濾出匹配的Advisor,主要通過AopUtils.findAdvisorsThatCanApply,呼叫canApply實現:

public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors,Class<?> clazz) {
		if (candidateAdvisors.isEmpty()) {
			return candidateAdvisors;
		}
		List<Advisor> eligibleAdvisors = new LinkedList<>();
		for (Advisor candidate : candidateAdvisors) {
		    // 呼叫 canApply
			if (candidate instanceof IntroductionAdvisor && canApply(candidate,clazz)) {
				eligibleAdvisors.add(candidate);
			}
		}
		boolean hasIntroductions = !eligibleAdvisors.isEmpty();
		for (Advisor candidate : candidateAdvisors) {
			if (candidate instanceof IntroductionAdvisor) {
				// already processed
				continue;
			}
			// 呼叫canApply
			if (canApply(candidate,clazz,hasIntroductions)) {
				eligibleAdvisors.add(candidate);
			}
		}
		return eligibleAdvisors;
	}
複製程式碼

5.2.3 canApply

  • 1 如果介面是IntroductionAdvisor,則呼叫IntroductionAdvisor.ClassFilter.matchs進行判斷;
  • 2 如果介面是PointcutAdvisor(比如前面建立的DefaultBeanFactoryPointcutAdvisor),則先呼叫PointcutAdvisor.ClassFilter.matches進行判斷,再MethodMatcher.getMethodMatcher()進行判斷。
public static boolean canApply(Advisor advisor,Class<?> targetClass,boolean hasIntroductions) {
		if (advisor instanceof IntroductionAdvisor) {
			return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
		}
		else if (advisor instanceof PointcutAdvisor) {
			PointcutAdvisor pca = (PointcutAdvisor) advisor;
			return canApply(pca.getPointcut(),targetClass,hasIntroductions);
		}
		else {
			// It doesn't have a pointcut so we assume it applies.
			return true;
		}
	}

public static boolean canApply(Pointcut pc,boolean hasIntroductions) {
		Assert.notNull(pc,"Pointcut must not be null");
		if (!pc.getClassFilter().matches(targetClass)) {
			return false;
		}

		MethodMatcher methodMatcher = pc.getMethodMatcher();
		if (methodMatcher == MethodMatcher.TRUE) {
			// No need to iterate the methods if we're matching any method anyway...
			return true;
		}

		IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
		if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
			introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
		}

		Set<Class<?>> classes = new LinkedHashSet<>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
		classes.add(targetClass);
		for (Class<?> clazz : classes) {
			Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
			for (Method method : methods) {
				if ((introductionAwareMethodMatcher != null &&
						introductionAwareMethodMatcher.matches(method,hasIntroductions)) ||
						methodMatcher.matches(method,targetClass)) {
					return true;
				}
			}
		}

		return false;
	}
複製程式碼

5.3 使用advisor增強代理

AbstractAutoProxyCreator.createProxy中實現:

  • 1 建立ProxyFactory
  • 2 判斷proxyTargetClass
  • 3 buildAdvisors
  • 4 執行getProxy
protected Object createProxy(Class<?> beanClass,@Nullable String beanName,@Nullable Object[] specificInterceptors,TargetSource targetSource) {

		if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
			AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory,beanClass);
		}

        // 建立ProxyFactory
		ProxyFactory proxyFactory = new ProxyFactory();
		proxyFactory.copyFrom(this);

        // 判斷proxyTargetClass
		if (!proxyFactory.isProxyTargetClass()) {
			if (shouldProxyTargetClass(beanClass,beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {
				evaluateProxyInterfaces(beanClass,proxyFactory);
			}
		}

        //  buildAdvisors
		Advisor[] advisors = buildAdvisors(beanName,specificInterceptors);
		proxyFactory.addAdvisors(advisors);
		proxyFactory.setTargetSource(targetSource);
		customizeProxyFactory(proxyFactory);

		proxyFactory.setFrozen(this.freezeProxy);
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}

        // 執行getProxy
		return proxyFactory.getProxy(getProxyClassLoader());
	}
複製程式碼

5.3.1 DefaultAopProxyFactory.createAopProxy

proxyFactory.getProxy中,需要一個AopProxy去實現,AopProxy的建立,在DefaultAopProxyFactory中,返回一個JdkDynamicAopProxy或一個CglibAopProxy

@Override
	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
		if (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);
		}
	}
複製程式碼

5.3.2 JdkDynamicAopProxy

JdkDynamicAopProxy實現了java.lang.reflect.InvocationHandler介面,在invoke(Object proxy,Method method,Object[] args)中實現代理。程式碼片段如下:

// Get the interception chain for this method.
			List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method,targetClass);

			// Check whether we have any advice. If we don't,we can fallback on direct
			// reflective invocation of the target,and avoid creating a MethodInvocation.
			if (chain.isEmpty()) {
				// 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 = AopUtils.invokeJoinpointUsingReflection(target,method,argsToUse);
			}
			else {
				// We need to create a method invocation...
				invocation = new ReflectiveMethodInvocation(proxy,target,args,chain);
				// Proceed to the joinpoint through the interceptor chain.
				retVal = invocation.proceed();
			}
複製程式碼

呼叫ReflectiveMethodInvocation.proceed()實現了代理。

5.3.3 ObjenesisCglibAopProxy

ObjenesisCglibAopProxy是CglibAopProxy的子類,代理邏輯都實現在CglibAopProxy裡。

CglibAopProxy中獲取Callback陣列時,建立了DynamicAdvisedInterceptor物件。

private Callback[] getCallbacks(Class<?> rootClass){
    //省略程式碼
    // Choose an "aop" interceptor (used for AOP calls).
    Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
    //省略程式碼
}
複製程式碼

DynamicAdvisedInterceptor實現了org.springframework.cglib.proxy.MethodInterceptor介面,在intercept方法裡執行了代理:

// We need to create a method invocation...
retVal = new CglibMethodInvocation(proxy,chain,methodProxy).proceed();
複製程式碼

CglibMethodInvocation是ReflectiveMethodInvocation的子類,所以也是呼叫ReflectiveMethodInvocation.proceed()實現了代理。