热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

SpringAOP注解方式源码解析

SpringAOP注解方式源码解析TSMYKJava技术编程前言在上篇文章SpringAOP功能使用详解中,知道了SprigAOP的一个详细用法,现在的看看Spring中是如何实现

Spring AOP 注解方式源码解析

TSMYK Java技术编程


前言

在上篇文章 Spring AOP 功能使用详解 中,知道了 Sprig AOP 的一个详细用法,现在的看看Spring 中是如何实现的。


aspectj-autoproxy

我们知道,要想使用 Spring AOP ,必须首先在配置文件中添加该配置项 ,其中的两个属性是可选的。对于 Spring 的每一个标签都有对应的解析器来进行解析,而对于 aspectj-autoproxy 标签则会使用 AspectJAutoProxyBeanDefinitionParser 解析器来进行解析,如下所示:


public class AopNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
// 注册 aspectj-autoproxy 标签的解析器
registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}
}

在 AspectJAutoProxyBeanDefinitionParser 中主要完成两部分功能,一个是注册 AnnotationAwareAspectJAutoProxyCreator 这个 bean,一个就是解析 的两个属性 其中 对于 AOP 的功能,基本上都是靠 AnnotationAwareAspectJAutoProxyCreator 来完成的;


注册 AnnotationAwareAspectJAutoProxyCreator

所有的解析器都实现了接口 BeanDefinitionParser,入口都是从 parse 方法开始进行解析的,而 AspectJAutoProxyBeanDefinitionParser 的parse 方法如下:


class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser {
public BeanDefinition parse(Element element, ParserContext parserContext) {
// 注册AnnotationAwareAspectJAutoProxyCreator bean 和处理标签的两个属性
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
// 处理子标签
extendBeanDefinition(element, parserContext);
return null;
}
}

AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary 方法如下:


public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(ParserContext parserContext, Element sourceElement) {
// 注册 AnnotationAwareAspectJAutoProxyCreator
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
// 解析标签的两个属性expose-proxy 和 proxy-target-class
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
// 注册组件并通知,便于监听器进一步处理,这里可以不用看
registerComponentIfNecessary(beanDefinition, parserContext);
}

在该方法中,主要完成三个功能,每行代码完成一个功能:



  1. 注册 AnnotationAwareAspectJAutoProxyCreator

  2. 处理 expose-proxy 和 proxy-target-class 属性

  3. 注册组件并通知

    注册 AnnotationAwareAspectJAutoProxyCreator



public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
// 注册
private static BeanDefinition registerOrEscalateApcAsRequired(Class cls, BeanDefinitionRegistry registry, Object source) {
//如果已经注册且与现在的不一致,则需要根据优先级来判断到底需要使用哪一个
//AUTO_PROXY_CREATOR_BEAN_NAME=org.springframework.aop.config.internalAutoProxyCreator
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
// 如果缓存中和现在注册的class不一样
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
// 判断优先级,如果现在的优先级比缓存中的大,则取现在的这个
if (currentPriority apcDefinition.setBeanClassName(cls.getName());
}
}
//如果相同,则无需再创建
return null;
}
// 如果还没有注册,则进行注册
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
// 注册
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}

处理 expose-proxy 和 proxy-target-class 属性


处理 expose-proxy 和 proxy-target-class 属性
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry,Element sourceElement) {
if (sourceElement != null) {
// 获取proxy-target-class的值
boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
if (proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
// 获取 expose-proxy的值
boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
if (exposeProxy) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
//设置属性 proxyTargetClass 为true
public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
}
}
//设置属性 exposeProxy为true
public static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) {
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
}
}

到这里,就完成了AnnotationAwareAspectJAutoProxyCreator 的注册,上面说过, AOP 的功能,基本上都是靠 AnnotationAwareAspectJAutoProxyCreator 来完成的,接下来看看这个类是如何完成AOP操作的。


解析 Advce

先来看看 AnnotationAwareAspectJAutoProxyCreator 的类图如下所示:

Spring AOP 注解方式源码解析
从上面的类图可知,AnnotationAwareAspectJAutoProxyCreator 实现了 BeanPostProcessor ,在 Spring 中实现了该接口的bean,当 Spring 在加载该 bean 时会在初始化之前调用它的 postProcessAfterInitializatio方法;父类 AbstractAutoProxyCreator的 postProcessAfterInitialization 方法实现如下:


public Object postProcessAfterInitialization(Object bean, String beanName) {
if (bean != null) {
// 根据beanClass 和 beanName 创建缓存的 key
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
// 如果该bean适合被代理,则必须包装
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
// 包装bean
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 如果已经处理过,则直接返回
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// 该bean无需增强,则直接返回
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
//如果bean是Advice.class, Pointcut.class, Advisor.class, AopInfrastructureBean.class, 则直接返回
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
// 添加该bean不需要增强的标志到缓存中
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// 获取bean所有的增强
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 如果获取到增强,则需要对增强创建代理
Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
// 不需要增强,直接返回
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}

从上述代码可知,在实例化 AnnotationAwareAspectJAutoProxyCreator 之前会对 AOP 增强进行解析,解析到增强后,会对增强创建代理;这篇文章先来看看增强的获取,关于代理的创建,则在下一篇文章进行讲解。


获取增强

根据 bean 对应的 class 和 beanName 来获取它所有的增强,对于方法为 getAdvicesAndAdvisorsForBean()


protected Object[] getAdvicesAndAdvisorsForBean(Class beanClass, String beanName, TargetSource targetSource) {
// 找出所有符合条件的增强
List advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}

findEligibleAdvisors() 方法:


protected List findEligibleAdvisors(Class beanClass, String beanName) {
// 获取所有增强
List candidateAdvisors = findCandidateAdvisors();
// 获取所有增强中适用于 bean 的增强并应用
List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
// 对增强进行扩展和排序
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}

其中获取所有增强的方法 findCandidateAdvisors() 经过大量复杂的逻辑判断,AOP 增强的获取和切点表达式的解析都在该方法内部进行实现 :


protected List findCandidateAdvisors() {
// 调用父类方法加载配置文件中的AOP声明
List advisors = super.findCandidateAdvisors();
// 创建所有AspectJ增强
if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
//父类 findCandidateAdvisors
protected List findCandidateAdvisors() {
return this.advisorRetrievalHelper.findAdvisorBeans();
}
// 寻找所有符合增强的bean,this.advisorRetrievalHelper.findAdvisorBeans
public List findAdvisorBeans() {
String[] advisorNames = this.cachedAdvisorBeanNames;
if (advisorNames == null) {
// 寻找Advisor注解的beanName
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Advisor.class, true, false);
this.cachedAdvisorBeanNames = advisorNames;
}
List advisors = new ArrayList<>();
for (String name : advisorNames) {
// 该bean符合增强
if (isEligibleBean(name)) {
if (this.beanFactory.isCurrentlyInCreation(name)) {
// 该bean正创建,则忽略
}
else {
advisors.add(this.beanFactory.getBean(name, Advisor.class));
}
}
}
return advisors;
}

获取 bean 的注解增强,对应方法 this.aspectJAdvisorsBuilder.buildAspectJAdvisors(),查找所有 AspectJ 注解的bean,对于每一个增强方法,都会创建对应的Advisor,即一个方法对于一个Advisor


// 查找所有 AspectJ 注解的bean,对于每一个增强方法,都会创建对应的Advisor,即一个方法对于一个Advisor
public List buildAspectJAdvisors() {
List aspectNames = this.aspectBeanNames;
// .... 省略一些null判断
List advisors = new ArrayList<>();
aspectNames = new ArrayList<>();
// 获取所有的 beanName
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);
for (String beanName : beanNames) {
// 如果该 bean不符合条件,则跳过
if (!isEligibleBean(beanName)) {
continue;
}
Class beanType = this.beanFactory.getType(beanName);
// 如果该 bean 存在 Aspect 注解
if (this.advisorFactory.isAspect(beanType)) {
aspectNames.add(beanName);
// 根据beanType和beanName创建AspectMetadata ,表示增强的元数据
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
MetadataAwareAspectInstanceFactory factory = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
// 解析标记了 AspectJ 注解中的增强方法
List classAdvisors = this.advisorFactory.getAdvisors(factory);
if (this.beanFactory.isSingleton(beanName)) {
// 如果该 bean是单例,则直接把解析到增强方法放到缓存中
this.advisorsCache.put(beanName, classAdvisors);
}else {
//否则把对于的工厂放到缓存中
this.aspectFactoryCache.put(beanName, factory);
}
advisors.addAll(classAdvisors);
}else {
tadataAwareAspectInstanceFactory factory =new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
this.aspectFactoryCache.put(beanName, factory);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
this.aspectBeanNames = aspectNames;
return advisors;
}
}
}
if (aspectNames.isEmpty()) {
return Collections.emptyList();
}
// 记录缓存
List advisors = new ArrayList<>();
for (String aspectName : aspectNames) {
List 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;
}

上述方法已经完成了 Advisor 的提取,其中增强器的获取则交给了 advisorFactory.getAdvisors() 方法,如下:


public List getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
//获取标记为 AspectJ 的类
Class aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
// 获取name
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
//验证aspectClass
validate(aspectClass);
//AOP 可以将增强延迟初始化,这里使用装饰器对工厂将包装
MetadataAwareAspectInstanceFactory lazySingletOnAspectInstanceFactory= new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
List advisors = new ArrayList<>();
// 处理每个增强方法,getAdvisorMethods 返回该增强类的所有增强方法
for (Method method : getAdvisorMethods(aspectClass)) {
// 每个方法对应一个 advisor
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
// 如果寻找的增强器不为空且配置了增强延迟初始化,那么需要在首位添加同步实例化增强器
if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
Advisor instantiatiOnAdvisor= new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
advisors.add(0, instantiationAdvisor);
}
// 获取 DeclareParents 注解
for (Field field : aspectClass.getDeclaredFields()) {
Advisor advisor = getDeclareParentsAdvisor(field);
if (advisor != null) {
advisors.add(advisor);
}
}
return advisors;
}
//获取增强类的所有增强方法 getAdvisorMethods
private List getAdvisorMethods(Class aspectClass) {
final List methods = new ArrayList<>();
ReflectionUtils.doWithMethods(aspectClass, method -> {
// 排除掉 Pointcut 方法
if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
methods.add(method);
}
});
methods.sort(METHOD_COMPARATOR);
return methods;
}

普通增强器的获取

普通增强器的获取是通过 getAdvisor() 方法来获取的,其中包括了对切点注解的获取和注解信息生成增强,如下:


public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrderInAspect, String aspectName) {
// 切点信息的获取,如@After, @Before
AspectJExpressionPointcut expressiOnPointcut= getPointcut(candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
// 根据切点信息,生成不同的增强器
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod, this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}

获取切点信息 getPonitcut:


private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class candidateAspectClass) {
// 获取方法上的注解
AspectJAnnotation aspectJAnnotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
// 使用 AspectJExpressionPointcut 封装切点信息
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class[0]);
// 设置切点表达式如:execution(* *Service*(..))
ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
if (this.beanFactory != null) {
ajexp.setBeanFactory(this.beanFactory);
}
return ajexp;
}
// 获取方法上的注解 findAspectJAnnotationOnMethod
protected static AspectJAnnotation findAspectJAnnotationOnMethod(Method method) {
// ASPECTJ_ANNOTATION_CLASSES 是一个数组:{Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class}
for (Class clazz : ASPECTJ_ANNOTATION_CLASSES) {
AspectJAnnotation foundAnnotation = findAnnotation(method, (Class) clazz);
if (foundAnnotation != null) {
return foundAnnotation;
}
}
return null;
}
// 获取注解
private static AspectJAnnotation findAnnotation(Method method, Class toLookFor) {
A result = AnnotationUtils.findAnnotation(method, toLookFor);
if (result != null) {
return new AspectJAnnotation<>(result);
}
else {
return null;
}
}

上述方法获取到具体的切点信息后,会根据切点信息生成对应的增强器,每一种切点信息如 @After, @Before 都对应一种 InstantiationModelAwarePointcutAdvisorImpl 对象,如下:


new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod, this, aspectInstanceFactory, declarationOrderInAspect, aspectName)

在该对象实例化的过程中,就是一些赋值过程,此外,根据不同的增强类型,如 @After, @Before,需要创建不同的增强器,如下所示:


public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
// .... 一些属性的赋值操作
// A singleton aspect.
this.pointcut = this.declaredPointcut;
this.lazy = false;
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}

instantiateAdvice 方法如下,会根据不同的增强注解来创建不同的增强器:


private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut, this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
return (advice != null ? advice : EMPTY_ADVICE);
}
// 创建不同的增强器
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
// 获取 Aspect 注解对应的class
Class candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
validate(candidateAspectClass);
// 再次获取Aspect注解类的所有增强方法来进行判断
AspectJAnnotation aspectJAnnotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
// 最终的增强器
AbstractAspectJAdvice springAdvice;
// 根据注解类型创建不同的增强器
switch (aspectJAnnotation.getAnnotationType()) {
// Pointcut注解 不处理
case AtPointcut:
return null;
case AtAround:
// around 注解,对应AspectJAroundAdvice增强器
springAdvice = new AspectJAroundAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtBefore:
// Before注解,对应AspectJMethodBeforeAdvice增强器
springAdvice = new AspectJMethodBeforeAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfter:
// After注解,对应AspectJAfterAdvice增强器
springAdvice = new AspectJAfterAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfterReturning:
// AfterReturning注解,对应AfterReturning增强器
springAdvice = new AspectJAfterReturningAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
// 设置返回值
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
springAdvice.setReturningName(afterReturningAnnotation.returning());
}
break;
case AtAfterThrowing:
// AtAfterThrowing注解,对应AspectJAfterThrowingAdvice增强器
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);
}
// 对获取到增强器进行一些配置
springAdvice.setAspectName(aspectName);
springAdvice.setDeclarationOrder(declarationOrder);
String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
if (argNames != null) {
springAdvice.setArgumentNamesFromStringArray(argNames);
}
springAdvice.calculateArgumentBindings();
return springAdvice;
}

接下来看下增强器的实现:

@Before 注解对应的增强器 AspectJMethodBeforeAdvice :


springAdvice = new AspectJMethodBeforeAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
public class AspectJMethodBeforeAdvice extends AbstractAspectJAdvice implements MethodBeforeAdvice, Serializable {
public AspectJMethodBeforeAdvice(Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
super(aspectJBeforeAdviceMethod, pointcut, aif);
}
// before 方法
@Override
public void before(Method method, Object[] args, @Nullable Object target) throws Throwable {
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
// .......
}
// invokeAdviceMethod 方法
protected Object invokeAdviceMethod(JoinPointMatch jpMatch, @Nullable Object returnValue, @Nullable Throwable ex){
return invokeAdviceMethodWithGivenArgs(argBinding(getJoinPoint(), jpMatch, returnValue, ex));
}
// invokeAdviceMethodWithGivenArgs 方法:
protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
Object[] actualArgs = args;
if (this.aspectJAdviceMethod.getParameterCount() == 0) {
actualArgs = null;
}
ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
// 激活增强方法
return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
}

上述几种不同类型的增强器都是 AbstractAspectJAdvice 的子类,最终都会在该类的 invokeAdviceMethod 方法中去激活增强方法。

上述的几个方法逻辑已经完成了所有增强器的解析,但是对于所有的增强器来说,并不一定都适用于当前的bean,所以还需要选出适合的增强器,

也就是上述 findEligibleAdvisors 方法的第二步,即 findAdvisorsThatCanApply 方法:


protected List findEligibleAdvisors(Class beanClass, String beanName) {
// 获取所有增强
List candidateAdvisors = findCandidateAdvisors();
// 获取所有增强中适用于 bean 的增强并应用
List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
// 对增强进行扩展和排序
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}

findAdvisorsThatCanApply 方法:


protected List findAdvisorsThatCanApply(List candidateAdvisors, Class beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
// 过滤已经得到的 advisors
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
public static List findAdvisorsThatCanApply(List candidateAdvisors, Class clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List eligibleAdvisors = new ArrayList<>();
for (Advisor candidate : candidateAdvisors) {
// 首先处理引介增强
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductiOns= !eligibleAdvisors.isEmpty();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
// 上面已经处理过了
continue;
}
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}

findAdvisorsThatCanApply 的主要作用是根据beanClass和方法增强来判断该增强是否适用于当前的bean,对应方法为 canAppley() ,如下:


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 {
return true;
}
}
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;
}
IntroductionAwareMethodMatcher introductiOnAwareMethodMatcher= null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductiOnAwareMethodMatcher= (IntroductionAwareMethodMatcher) methodMatcher;
}
Set> 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 (introductionAwareMethodMatcher != null ?
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}

以上就是 Spring AOP 增强的解析,它包括了 Aspect 注解类的解析和该类下所有增强方法的解析。


总结

Spring AOP 功能,对应的解析类实现了 BeanPostProcessor 接口,这可以让我们在 bean 初始化之前可以对 bean 进行一些操作,对于 注解的 AOP 来说,在实例化 AnnotationAwareAspectJAutoProxyCreator bean 之前,会去解析 Aspect 注解的类,以及该类下所有的增强方法,每个增强方法都会对应一个 Advisor ,在解析增强方法得到 Advisor 时,则会根据方法不同的注解类型来创建不同的增强器。

上述主要介绍了如何去获取bean 对应的增强器,我们知道, Spring AOP 是通过动态代理来实现,在获取到增强器之后,就可以来创建对应的代理了,关于代理的创建,下篇文章介绍。


推荐阅读
  • spring boot使用jetty无法启动 ... [详细]
  • 本文探讨了如何通过Service Locator模式来简化和优化在B/S架构中的服务命名访问,特别是对于需要频繁访问的服务,如JNDI和XMLNS。该模式通过缓存机制减少了重复查找的成本,并提供了对多种服务的统一访问接口。 ... [详细]
  • 本文介绍了如何通过C#语言调用动态链接库(DLL)中的函数来实现IC卡的基本操作,包括初始化设备、设置密码模式、获取设备状态等,并详细展示了将TextBox中的数据写入IC卡的具体实现方法。 ... [详细]
  • 入门指南:使用FastRPC技术连接Qualcomm Hexagon DSP
    本文旨在为初学者提供关于如何使用FastRPC技术连接Qualcomm Hexagon DSP的基础知识。FastRPC技术允许开发者在本地客户端实现远程调用,从而简化Hexagon DSP的开发和调试过程。 ... [详细]
  • Web动态服务器Python基本实现
    Web动态服务器Python基本实现 ... [详细]
  • 本文将从基础概念入手,详细探讨SpringMVC框架中DispatcherServlet如何通过HandlerMapping进行请求分发,以及其背后的源码实现细节。 ... [详细]
  • 本文深入探讨了WPF框架下的数据验证机制,包括内置验证规则的使用、自定义验证规则的实现方法、错误信息的有效展示策略以及验证时机的选择,旨在帮助开发者构建更加健壮和用户友好的应用程序。 ... [详细]
  • 本文探讨了如何在PHP与MySQL环境中实现高效的分页查询,包括基本的分页实现、性能优化技巧以及高级的分页策略。 ... [详细]
  • td{border:1pxsolid#808080;}参考:和FMX相关的类(表)TFmxObjectIFreeNotification ... [详细]
  • 处理Android EditText中数字输入与parseInt方法
    本文探讨了如何在Android应用中从EditText组件安全地获取并解析用户输入的数字,特别是用于设置端口号的情况。通过示例代码和异常处理策略,展示了有效的方法来避免因非法输入导致的应用崩溃。 ... [详细]
  • Maven + Spring + MyBatis + MySQL 环境搭建与实例解析
    本文详细介绍如何使用MySQL数据库进行环境搭建,包括创建数据库表并插入示例数据。随后,逐步指导如何配置Maven项目,整合Spring框架与MyBatis,实现高效的数据访问。 ... [详细]
  • 长期从事ABAP开发工作的专业人士,在面对行业新趋势时,往往需要重新审视自己的发展方向。本文探讨了几位资深专家对ABAP未来走向的看法,以及开发者应如何调整技能以适应新的技术环境。 ... [详细]
  • 本文详细介绍了如何在Oracle VM VirtualBox中实现主机与虚拟机之间的数据交换,包括安装Guest Additions增强功能,以及如何利用这些功能进行文件传输、屏幕调整等操作。 ... [详细]
  • 一、Advice执行顺序二、Advice在同一个Aspect中三、Advice在不同的Aspect中一、Advice执行顺序如果多个Advice和同一个JointPoint连接& ... [详细]
  • 1.绑定htmlcss1.1对象语法:  传给v-bind:class一个对象,以动态地切换class   ... [详细]
author-avatar
mobiledu2502934191
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有