Spring AOP源碼實現分步解析

1 概述

1.1 示例

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

1.1.1 建立接口及實現類

接口java

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

實現類spring

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

1.1.2 實現方法攔截

實現接口org.aopalliance.intercept.MethodInterceptorexpress

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");
    }
}
複製代碼

返回:bash

CustomInterceptor before
execute hello
CustomInterceptor after
複製代碼

1.2 AOP實現過程

Spring環境啓動過程當中,會調用AbstractApplicationContext.refresh(),AOP的實現流程,也就是從這裏開始。app

  • 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()。ide

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

在這個過程當中,會調用BeanDefinitionParserDelegate.parseCustomElement進行擴展標籤的解析:ui

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.", element, 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.",
					element, 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(), beanName, "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, 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;
	}
複製代碼
  1. wrapIfNecessary中使用advisor執行createProxy:
// Create proxy if we have advice.

        // 1 查找advisor
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		if (specificInterceptors != DO_NOT_PROXY) {
			this.advisedBeans.put(cacheKey, Boolean.TRUE);
			// 2 建立proxy,並使用advisor進行加強
			Object proxy = createProxy(
					bean.getClass(), beanName, 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, Class<?> targetClass, 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, targetClass, 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, beanName, 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, method, args, targetClass, 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, target, method, args, targetClass, chain, methodProxy).proceed();
複製代碼

CglibMethodInvocation是ReflectiveMethodInvocation的子類,因此也是調用ReflectiveMethodInvocation.proceed()實現了代理。

相關文章
相關標籤/搜索