栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

springAop原理之查找和原始bean关联的Advisor

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

springAop原理之查找和原始bean关联的Advisor

spring如何判断bean是否需要被代理
  1. spring在创建完bean原始实例后,需要判断是否需要给当前bean创建代理对象。
  2. initializeBean时会调用applyBeanPostProcessorsAfterInitialization方法,该方法会调用所有BeanPostProcessor的postProcessAfterInitialization。
  3. AbstractAutoProxyCreator就是一个BeanPostProcessor,该类的postProcessAfterInitialization会调用wrapIfNecessary方法,即该bean是否需要被包装成代理对象。是否需要代理原则就是该bean有没有与之相关的Advisor,有就代理。
spring如何查找所有Advisor源码及如何判断某个bean与之关联的Advisor有哪些 wrapIfNecessary部分源码
// Create proxy if we have advice.
//获取bean有关的Advisor
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;
}

getAdvicesAndAdvisorsForBean会调用AbstractAdvisorAutoProxyCreator#findEligibleAdvisors

protected List findEligibleAdvisors(Class beanClass, String beanName) {
  //查找所有的Advisor
   List candidateAdvisors = findCandidateAdvisors();
  //查找所有的Advisor中可应用的某个bean的Advisor
   List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
   extendAdvisors(eligibleAdvisors);
   if (!eligibleAdvisors.isEmpty()) {
      eligibleAdvisors = sortAdvisors(eligibleAdvisors);
   }
   return eligibleAdvisors;
}

findCandidateAdvisors()源码简单可总结为:从容器中获取所有实现了Advisor的类,在加上aspectJ创建的Advisor。
接下来我们看下findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName)源码

protected List findAdvisorsThatCanApply(
      List candidateAdvisors, Class beanClass, String beanName) {
   //在ThreadLocal中标记当前beanName
   ProxyCreationContext.setCurrentProxiedBeanName(beanName);
   try {
      return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
   }
   finally {
     //在ThreadLocal中移除当前beanName
      ProxyCreationContext.setCurrentProxiedBeanName(null);
   }
}

AopUtils findAdvisorsThatCanApply源码分析

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);
      }
   }
   //目前用不到IntroductionAdvisor ,所以值为false,看常用的就行
   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;
}

接着看canApply方法

	public static boolean canApply(Advisor advisor, Class targetClass, boolean hasIntroductions) {
	//这里也不关注引入Advisor
		if (advisor instanceof IntroductionAdvisor) {
			return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
		}
		//只要看PointcutAdvisor就行
		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;
		}
	}

接着看canApply方法

	public static boolean canApply(Pointcut pc, Class targetClass, boolean hasIntroductions) {
		Assert.notNull(pc, "Pointcut must not be null");
		//1
		if (!pc.getClassFilter().matches(targetClass)) {
			return false;
		}
		//2
		MethodMatcher methodMatcher = pc.getMethodMatcher();
		if (methodMatcher == MethodMatcher.TRUE) {
			// No need to iterate the methods if we're matching any method anyway...
			return true;
		}
		//3
		IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
		if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
			introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
		}
		//4
		Set> classes = new LinkedHashSet<>();
		if (!Proxy.isProxyClass(targetClass)) {
			classes.add(ClassUtils.getUserClass(targetClass));
		}
		classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
		//5
		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;
	}
  1. 先用PointcutAdvisor过滤,true继续
  2. 判断methodMatcher 是否为TrueMethodMatcher,因为TrueMethodMatcher永远匹配都是true。不是的话继续
  3. 如果是引入类型的methodMatcher则强转,这里也不讨论
  4. 查找当前类及其祖宗类实现的所有接口
  5. 遍历这些class。获取每个class方法列表包含从父类继承的的方法。接着调用2个参数的methodMatcher#matches方法,如果为true则返回,false则接着循环。
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/845791.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号