首页 > 编程语言 >@aspectJ机制剖析

@aspectJ机制剖析

时间:2024-08-28 17:50:40浏览次数:4  
标签:return beanName method 剖析 bean shadowMatch 机制 null aspectJ

@aspectJ机制剖析

@aspectj通过修改字节码文件来实现目标方法的增强。

image

image

org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization

AbstractAutoProxyCreator的对应实现

@Override
	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (this.earlyProxyReferences.remove(cacheKey) != bean) {
				// 如果它有资格被代理
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}
/**
	 * * 如有必要,包装给定的 bean,即如果它有资格被代理。
	 * Wrap the given bean if necessary, i.e. if it is eligible for being proxied.
	 * @param bean the raw bean instance
	 * @param beanName the name of the bean
	 * @param cacheKey the cache key for metadata access
	 * @return a proxy wrapping the bean, or the raw bean instance as-is
	 */
	protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
		// 如果是 基础设施类(Pointcut、Advice、Advisor 等) 或 需要 skip, 则不需要增强
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

		// Create proxy if we have advice.
		// 为目标 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;
	}

org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessBeforeInstantiation

AbstractAutoProxyCreator的对应实现

@Override
	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
		Object cacheKey = getCacheKey(beanClass, beanName);

		if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
			if (this.advisedBeans.containsKey(cacheKey)) {
				return null;
			}
            // 判断是不是基础设施类
            // 如果是 基础设施类(Pointcut、Advice、Advisor 等) 或 需要 skip, 则不需要增强
			if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
				this.advisedBeans.put(cacheKey, Boolean.FALSE);
				return null;
			}
		}

		// Create proxy here if we have a custom TargetSource.
		// Suppresses unnecessary default instantiation of the target bean:
		// The TargetSource will handle target instances in a custom fashion.
		TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
		if (targetSource != null) {
			if (StringUtils.hasLength(beanName)) {
				this.targetSourcedBeans.add(beanName);
			}
			Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
			Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		return null;
	}

org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator#shouldSkip

@Override
	protected boolean shouldSkip(Class<?> beanClass, String beanName) {
		// TODO: Consider optimization by caching the list of the aspect names
		// 获取候选 Advisor
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
		for (Advisor advisor : candidateAdvisors) {
			if (advisor instanceof AspectJPointcutAdvisor &&
					((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
				return true;
			}
		}
		return super.shouldSkip(beanClass, beanName);
	}

org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors

	@Override
	protected List<Advisor> findCandidateAdvisors() {
		// Add all the Spring advisors found according to superclass rules.
        // 先从父类中查找
		List<Advisor> advisors = super.findCandidateAdvisors();
		// Build Advisors for all AspectJ aspects in the bean factory.
		if (this.aspectJAdvisorsBuilder != null) {
			advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
		}
		return advisors;
	}

org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors

public List<Advisor> buildAspectJAdvisors() {
		List<String> aspectNames = this.aspectBeanNames;

		if (aspectNames == null) {
			synchronized (this) {
				aspectNames = this.aspectBeanNames;
				if (aspectNames == null) {
					List<Advisor> advisors = new ArrayList<>();
					aspectNames = new ArrayList<>();
                    // 获取spring容器中的所有bean实例对应的名称
					String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
							this.beanFactory, Object.class, true, false);
					for (String beanName : beanNames) {
						if (!isEligibleBean(beanName)) {
							continue;
						}
						// We must be careful not to instantiate beans eagerly as in this case they
						// would be cached by the Spring container but would not have been weaved.
						Class<?> beanType = this.beanFactory.getType(beanName, false);
						if (beanType == null) {
							continue;
						}
                        // 查看哪些bean是被@AspectJ注解进行修饰
						if (this.advisorFactory.isAspect(beanType)) {
                            // 将@AspectJ修饰的bean的名称添加到List<String> aspectNames集合中
							aspectNames.add(beanName); // beanName: myAspectJDemo
							AspectMetadata amd = new AspectMetadata(beanType, beanName);
							if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
								MetadataAwareAspectInstanceFactory factory =
										new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
								List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
								if (this.beanFactory.isSingleton(beanName)) {
									this.advisorsCache.put(beanName, classAdvisors);
								}
								else {
									this.aspectFactoryCache.put(beanName, factory);
								}
                                // 通过上面的逻辑进行查找,将所有的切面逻辑都添加到List<Advisor> advisor集合中
								advisors.addAll(classAdvisors);
							}
							else {
								// Per target or per this.
								if (this.beanFactory.isSingleton(beanName)) {
									throw new IllegalArgumentException("Bean with name '" + beanName +
											"' is a singleton, but aspect instantiation model is not singleton");
								}
								MetadataAwareAspectInstanceFactory factory =
										new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
								this.aspectFactoryCache.put(beanName, factory);
								advisors.addAll(this.advisorFactory.getAdvisors(factory));
							}
						}
					}
					this.aspectBeanNames = aspectNames;
                    // 里面放的是这些玩意
                   // 0 = {InstantiationModelAwarePointcutAdvisorImpl@4231} expression [pointCut()]; advice method [public java.lang.Object com.coding.spring.aop.aspectj.MyAspectJDemo.around(org.aspectj.lang.ProceedingJoinPoint) throws java.lang.Throwable]; 
// 1 = {InstantiationModelAwarePointcutAdvisorImpl@4232} expression [pointCut()]; advice method [public void com.coding.spring.aop.aspectj.MyAspectJDemo.before()]; 
// 2 = {InstantiationModelAwarePointcutAdvisorImpl@4233} expression [pointCut()]; advice method [public void com.coding.spring.aop.aspectj.MyAspectJDemo.after()]; 
// 3 = {InstantiationModelAwarePointcutAdvisorImpl@4234} expression [pointCut()]; advice method [public void com.coding.spring.aop.aspectj.MyAspectJDemo.afterReturning()]; 
// 4 = {InstantiationModelAwarePointcutAdvisorImpl@4235} expression [pointCut()]; advice method [public void com.coding.spring.aop.aspectj.MyAspectJDemo.afterThrowing()]; 
					return advisors; // 将切面逻辑集合进行返回
				}
			}
		}

通过以上步骤已经获取到了所有的通知器(也就是切面方法)List

// 为目标 bean 查找合适的通知器

getAdvicesAndAdvisorsForBean()逻辑

org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean

@Override
	@Nullable
	protected Object[] getAdvicesAndAdvisorsForBean(
			Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {

		// 查找所有符合条件的通知器 封装成 Advisor 的集合
		List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
		if (advisors.isEmpty()) {
			return DO_NOT_PROXY;
		}
		return advisors.toArray();
	}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
		// 查找所有的通知器
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
		// 筛选
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
		extendAdvisors(eligibleAdvisors);
		if (!eligibleAdvisors.isEmpty()) {
			// 排序
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}
		return eligibleAdvisors;
	}
	protected List<Advisor> findAdvisorsThatCanApply(
			List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {

		ProxyCreationContext.setCurrentProxiedBeanName(beanName);
		try {
			return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
		}
		finally {
			ProxyCreationContext.setCurrentProxiedBeanName(null);
		}
	}

org.springframework.aop.support.AopUtils#findAdvisorsThatCanApply

public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
		if (candidateAdvisors.isEmpty()) {
			return candidateAdvisors;
		}
		List<Advisor> 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) {
				// already processed
				continue;
			}
            // 进行筛选,重点,重点
			if (canApply(candidate, clazz, hasIntroductions)) {
				eligibleAdvisors.add(candidate);
			}
		}
		return eligibleAdvisors;
	}
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<>();
		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;
	}

org.springframework.aop.aspectj.AspectJExpressionPointcut#matches(java.lang.reflect.Method, java.lang.Class<?>, boolean)

@Override
	public boolean matches(Method method, Class<?> targetClass, boolean hasIntroductions) {
		obtainPointcutExpression();
		ShadowMatch shadowMatch = getTargetShadowMatch(method, targetClass);

		// Special handling for this, target, @this, @target, @annotation
		// in Spring - we can optimize since we know we have exactly this class,
		// and there will never be matching subclass at runtime.
		if (shadowMatch.alwaysMatches()) {
			return true;
		}
		else if (shadowMatch.neverMatches()) {
			return false;
		}
		else {
			// the maybe case
			if (hasIntroductions) {
				return true;
			}
			// A match test returned maybe - if there are any subtype sensitive variables
			// involved in the test (this, target, at_this, at_target, at_annotation) then
			// we say this is not a match as in Spring there will never be a different
			// runtime subtype.
			RuntimeTestWalker walker = getRuntimeTestWalker(shadowMatch);
			return (!walker.testsSubtypeSensitiveVars() || walker.testTargetInstanceOfResidue(targetClass));
		}
	}
private ShadowMatch getTargetShadowMatch(Method method, Class<?> targetClass) {
		Method targetMethod = AopUtils.getMostSpecificMethod(method, targetClass);
		if (targetMethod.getDeclaringClass().isInterface()) {
			// Try to build the most specific interface possible for inherited methods to be
			// considered for sub-interface matches as well, in particular for proxy classes.
			// Note: AspectJ is only going to take Method.getDeclaringClass() into account.
			Set<Class<?>> ifcs = ClassUtils.getAllInterfacesForClassAsSet(targetClass);
			if (ifcs.size() > 1) {
				try {
					Class<?> compositeInterface = ClassUtils.createCompositeInterface(
							ClassUtils.toClassArray(ifcs), targetClass.getClassLoader());
					targetMethod = ClassUtils.getMostSpecificMethod(targetMethod, compositeInterface);
				}
				catch (IllegalArgumentException ex) {
					// Implemented interfaces probably expose conflicting method signatures...
					// Proceed with original target method.
				}
			}
		}
        // 点进去	
		return getShadowMatch(targetMethod, method);
	}
private transient Map<Method, ShadowMatch> shadowMatchCache = new ConcurrentHashMap<>(32);

private ShadowMatch getShadowMatch(Method targetMethod, Method originalMethod) {
		// Avoid lock contention for known Methods through concurrent access...
		ShadowMatch shadowMatch = this.shadowMatchCache.get(targetMethod);
		if (shadowMatch == null) {
			synchronized (this.shadowMatchCache) {
				// Not found - now check again with full lock...
				PointcutExpression fallbackExpression = null;
				shadowMatch = this.shadowMatchCache.get(targetMethod);
				if (shadowMatch == null) {
					Method methodToMatch = targetMethod;
					try {
						try {
                            // 进行匹配 点进去
                            // 匹配上,就是YES,如果没有匹配上,就是NO
							shadowMatch = obtainPointcutExpression().matchesMethodExecution(methodToMatch);
						}
						catch (ReflectionWorldException ex) {
							// Failed to introspect target method, probably because it has been loaded
							// in a special ClassLoader. Let's try the declaring ClassLoader instead...
							try {
								fallbackExpression = getFallbackPointcutExpression(methodToMatch.getDeclaringClass());
								if (fallbackExpression != null) {
									shadowMatch = fallbackExpression.matchesMethodExecution(methodToMatch);
								}
							}
							catch (ReflectionWorldException ex2) {
								fallbackExpression = null;
							}
						}
						if (targetMethod != originalMethod && (shadowMatch == null ||
								(shadowMatch.neverMatches() && Proxy.isProxyClass(targetMethod.getDeclaringClass())))) {
							// Fall back to the plain original method in case of no resolvable match or a
							// negative match on a proxy class (which doesn't carry any annotations on its
							// redeclared methods).
							methodToMatch = originalMethod;
							try {
								shadowMatch = obtainPointcutExpression().matchesMethodExecution(methodToMatch);
							}
							catch (ReflectionWorldException ex) {
								// Could neither introspect the target class nor the proxy class ->
								// let's try the original method's declaring class before we give up...
								try {
									fallbackExpression = getFallbackPointcutExpression(methodToMatch.getDeclaringClass());
									if (fallbackExpression != null) {
										shadowMatch = fallbackExpression.matchesMethodExecution(methodToMatch);
									}
								}
								catch (ReflectionWorldException ex2) {
									fallbackExpression = null;
								}
							}
						}
					}
					catch (Throwable ex) {
						// Possibly AspectJ 1.8.10 encountering an invalid signature
						logger.debug("PointcutExpression matching rejected target method", ex);
						fallbackExpression = null;
					}
					if (shadowMatch == null) {
						shadowMatch = new ShadowMatchImpl(org.aspectj.util.FuzzyBoolean.NO, null, null, null);
					}
					else if (shadowMatch.maybeMatches() && fallbackExpression != null) {
						shadowMatch = new DefensiveShadowMatch(shadowMatch,
								fallbackExpression.matchesMethodExecution(methodToMatch));
					}
                    // 将该方法的匹配结果放到map集合中
                    // targetMethod:方法
                    // shadowMatch:YES 匹配成功 NO 没有匹配上
					this.shadowMatchCache.put(targetMethod, shadowMatch);
				}
			}
		}
		return shadowMatch;
	}

image

org.aspectj.weaver.internal.tools.PointcutExpressionImpl#matchesMethodExecution

    public ShadowMatch matchesMethodExecution(Method aMethod) {
        ShadowMatch match = this.matchesExecution(aMethod);
        return match;
    }
    private ShadowMatch matchesExecution(Member aMember) {
        Shadow s = ReflectionShadow.makeExecutionShadow(this.world, aMember, this.matchContext);
        ShadowMatchImpl sm = this.getShadowMatch(s);
        sm.setSubject(aMember);
        sm.setWithinCode((Member)null);
        sm.setWithinType(aMember.getDeclaringClass());
        return sm;
    }

image

image

标签:return,beanName,method,剖析,bean,shadowMatch,机制,null,aspectJ
From: https://www.cnblogs.com/dongyaotou/p/18385224

相关文章

  • spring aop底层源码执行逻辑剖析
    aop动态代理源码剖析aop增强逻辑的执行时机是在initializeBean方法中protectedObjectinitializeBean(StringbeanName,Objectbean,@NullableRootBeanDefinitionmbd){ if(beanName.indexOf("my")>=0){ System.out.println("=============[initializeBean]bean......
  • C#实现软件授权,限定MAC运行(软件license管理,简单软件注册机制)
    C#实现软件授权,限定MAC运行(软件license管理,简单软件注册机制) 一个绿色免安装软件,领导临时要求加个注册机制,不能让现场工程师随意复制。事出突然,只能在现场开发(离开现场软件就不受我们控了)。花了不到两个小时实现了简单的注册机制,稍作整理。 基本原理:1.软件一运行就把计算机......
  • Android面试高阶问题:Android屏幕刷新机制与优化指南
    目录1屏幕刷新基础概念1.1CPU与GPU的作用2.2SurfaceFlinger与图形合成2.3帧、帧率与屏幕刷新率2屏幕撕裂与双缓冲机制2.1屏幕撕裂的原因与影响2.2双缓冲机制的工作原理3优化策略与实践3.1性能分析工具与方法3.2优化案例分析与实施3.2.1案例四:异步加载与......
  • 【高等数学1:洛必达法则】洛必达法则使用的隐蔽误区:例题剖析
    洛必达法则是求标准未定式极限的一种较好方法,而且不少学者提出了一些洛必达法则使用时的注意点。尽管如此,还有一种情况却很少提及,成为一个应用的隐蔽误区,如果不加注意而去滥用,往往会得出错误的结论。因此,本文从洛必达法则的基本概念出来,以一道经典例题说明洛必达使用的条......
  • Android开发 - IInterface 接口 Binder 机制跨进程通信 (IPC)解析
    什么是IInterfaceIInterface一个接口,用于跨进程通信(IPC)。有时需要让一个应用程序与另一个应用程序或服务进行通信。这些应用程序可能运行在不同的进程中,使用Binder机制来实现这种通信,而IInterface就是Binder机制的一部分简单来说,IInterface是一个基础接口,它为跨......
  • 深度剖析:医疗行业财务报表的核心要素与解析策略
    在当今医疗行业中,财务报表分析扮演着至关重要的角色。医疗机构需要通过对财务数据的准确分析来做出关键决策,管理资源,改善效率,并确保最终提供高质量的医疗服务。本文将深入探讨医疗行业中财务报表分析的重要性、关键指标和分析方法,帮助大家更好地理解和了解财务报表在医疗行业中......
  • 【全面剖析】张宇1000题难度大吗?值不值得做?
    在考研数学的备考征程中,张宇考研数学题源探析经典1000题一直备受关注,许多考生都在纠结它的难度以及是否值得投入宝贵的复习时间去钻研。作为一个考研上岸的过来人,下面我将从以下几个方面来对这本习题集进行分析,希望能够对你有所帮助。一、题库分析知识覆盖全面且深入张......
  • 【深度剖析】李永乐 660 题与武忠祥 660 有何区别?推荐刷哪个?
    作为一名刚刚成功上岸的研0学子,在考研数学的备考过程中,李永乐660题和武忠祥660这两本习题集都给我留下了深刻的印象。今天就来和大家详细分享一下它们之间的区别以及我个人的使用感受和推荐建议。一、习题集介绍李永乐660题题目特点:注重基础概念的深入理解和灵活运......
  • 【JUC并发编程系列】深入理解Java并发机制:CAS算法与原子类在Java中的实践应用(二、CAS
    文章目录【JUC并发编程系列】深入理解Java并发机制:CAS算法与原子类在Java中的实践应用(二、CAS)1.同步之原子类(Atomic类)2.使用atomicInteger计数3.使用atomicInteger底层原理3.compareAndSet原理分析3.1手写AtomicInteger3.2手写Lock锁3.3CASaba的问题3.4Atomic......
  • 【JUC并发编程系列】深入理解Java并发机制:从用户态到内核态的探索(一、前置知识)
    文章目录【JUC并发编程系列】深入理解Java并发机制:从用户态到内核态的探索(一、前置知识)1.用户态与内核态区别2.线程安全同步的方式3.传统锁有哪些缺点4.发生CPU上下文切换的原因5.如何避免上下文切换6.详细总结6.1用户态与内核态6.2线程安全同步方式6.3传统锁的......