Исходный код Spring AOP реализует пошаговый анализ

Spring

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, размещенный в каталоге ресурсов:

<?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 Процесс реализации АОП

Во время запуска среды Spring он будет называтьсяAbstractApplicationContext.refresh(), процесс реализации АОП, то есть отсюда.

  • 1 дюймobtainFreshBeanFactory()Во время выполнения загрузитьaop.xml, и согласноnamespaceоказатьсяaopсоответствующийNamespaceHandler:AopNamespaceHandler;
  • 2 AopNamespaceHandlerв, найтиconfigсоответствует этикеткеBeanDefinitionParserобъект реализации, т.ConfigBeanDefinitionParser;
  • 3 ВыполнитьConfigBeanDefinitionParser.parse, выполняет две функции:
    1. кAspectJAwareAdvisorAutoProxyCreatorЗарегистрировать BeanDefinition;
    2. Разобратьpointcut,advisorИ другие метки, и связанные с ними объекты, зарегистрированные как BeanDefinition.
  • 4 Зарегистрируйте BeanPostProcessor:AspectJAwareAdvisorAutoProxyCreatorэто класс реализации BeanPostProcessorAbstractAutoProxyCreatorподкласс . После регистрации BeanPostProcessor,AspectJAwareAdvisorAutoProxyCreatorБудет вызываться во время прокси-процесса создания bean-компонента Spring.
  • 5 Создать прокси и дополнить его советником, есть несколько основных шагов:
    1. создать прокси;
    2. Найти подходящего советника;
    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/>, весна будетxmlnsидтиMETA-INF/spring.handlersНайдите в файле соответствующий класс разрешения пространства имен:http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler.

существуетAopNamespaceHandlerсередина:registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());

так:

  • aopКласс разрешения пространства именAopNamespaceHandler
  • <aop:config/>Класс синтаксического анализа для тегаConfigBeanDefinitionParser,существуетConfigBeanDefinitionParserсередина,<aop:config/>Отдельные элементы определения анализируются какBeanDefinition.

3 ConfigBeanDefinitionParser

ConfigBeanDefinitionParserДостигнутоBeanDefinitionParserинтерфейс, вparse(Element element, ParserContext parserContext)В методе реализованы две части функций:

  • 1 Зарегистрируйте BeanDefinition в среде Spring:AspectJAwareAdvisorAutoProxyCreator;
  • 2 Разберите pointcut, советник и т. д. конфигурации xml в серию BeanDefinitions.
@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 Функция

  • AspectJAwareAdvisorAutoProxyCreatorдаAbstractAutoProxyCreatorподкласс;
  • 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 вызоветBeanPostProcessorДля обработки до и после генерации bean-компонента aop использует это:

передачаAbstractAutoProxyCreator.postProcessAfterInitializationметод, согласноpointcutнайти соответствующийadvisor, прокси боб.

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);

наконец сгенерированныйAspectJAwareAdvisorAutoProxyCreatorBeanDefinition, beanNameorg.springframework.aop.config.internalAutoProxyCreator.

в то же время,useClassProxyingIfNecessaryметод, согласно **aop:config/**серединаproxy-target-class, который устанавливает родительский класс AspectJAwareAdvisorAutoProxyCreatorProxyConfigизproxyTargetClassАтрибуты.

3.2 Парсинг pointcut

Разобрать<aop:pointcut id="interceptorPointCuts" expression="execution(* com.xxx.yyy..*.*(..))"/>,регистрAbstractExpressionPointcutBeanDefinition.

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 expressionдаAbstractExpressionPointcutсвойства
	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 Анализ советников

Разобрать<aop:advisor advice-ref="customInterceptor" pointcut-ref="interceptorPointCuts"/>,регистрDefaultBeanFactoryPointcutAdvisorBeanDefinition.

3.3.1 parseAdvisor

  • 1 звонокcreateAdvisorBeanDefinitionсоздать советник;
  • 2 звонкаparsePointcutPropertyПолучить точечный разрез.
	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 СоздатьDefaultBeanFactoryPointcutAdvisorBeanDefinition, DefaultBeanFactoryPointcutAdvisor — этоPointcutAdvisorреализация ;
  • 2 Анализadvice-refПолучите beanName bean-компонента советника, то есть customInterceptor в aop.xml.
  • 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, затем используйте выражение для вызова createPointcutDefinition и возвращайтесь сразу после создания bean-компонента AspectJExpressionPointcut.
  • 2 иначе вернутьсяpointcut-refОпределяет компонент как Pointcut.

так:pointcut имеет приоритет над pointcut-ref, и pointcut-ref больше не анализируется, если есть pointcut.

	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, beanNameorg.springframework.aop.config.internalAutoProxyCreator;
  • точечный разрез:AbstractExpressionPointcut, установлен атрибут выражения;
  • советник:DefaultBeanFactoryPointcutAdvisor, для атрибута Pointcut установлено значениеAbstractExpressionPointcut.

4 Зарегистрируйте BeanPostProcessor

В методе AbstractApplicationContext.refresh() создайтеConfigurableListableBeanFactory, выполнитregisterBeanPostProcessorsЗарегистрируйтесь в среде SpringBeanPostProcessor.

// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);

AspectJAwareAdvisorAutoProxyCreatorНа этом этапе добавляется в список BeanPostProcessors, используемых для обработки создания bean-компонентов.

Краткий процесс выглядит следующим образом:

  • 1 звонокPostProcessorRegistrationDelegate.registerBeanPostProcessors;
  • 2 проходbeanFactory.getBean(ppName, BeanPostProcessor.class);Получить список BeanPostProcessors;
  • 3 ВыполнитьbeanFactory.addBeanPostProcessor(postProcessor).

5 Создавайте bean-компоненты и улучшайте

5.1 createProxy

Весна создает бобы в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Используйте советник для выполнения 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 Найдите подходящих советников

AbstractAutoProxyCreator.getAdvicesAndAdvisorsForBeanэто абстрактный метод, используемый подклассамиAbstractAdvisorAutoProxyCreatorвыполнить.

AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBeanназываетсяfindEligibleAdvisors, Для достижения двух основных процессов:

  • 1 Получить кандидатов в советники;
  • 2 Отфильтруйте подходящие советники.
    /*
    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, чтобы получить все bean-компоненты, реализующие интерфейс Advisor.Основные фрагменты кода следующие:

  • 1 Найдите beanName, который реализует интерфейс Advisor:

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

  • 2 Получить bean-компоненты по beanName:

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

5.2.2 findAdvisorsThatCanApply

Отфильтровать соответствующий советник, в основном через 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 Использование советника для улучшения агента

существуетAbstractAutoProxyCreator.createProxyРеализовано в:

  • 1 Создать ПроксиФабрику
  • 2 Определить проксицелевой класс
  • 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, создается объект 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()Прокси реализован.