Spring 5.x Source trip forty-six AOP proxy details of a wrapIfNecessary

After postProcessAfterInitialization proxy initialization

Real proxy AOP is to create an instance of, and proxy after initialization, which is in the inside by the AbstractAutoProxyCreatoradvanced postProcessAfterInitializationprocessing method:
Here Insert Picture Description
First check whether earlyProxyReferencesthere is there, that is has been processed, it does not exist to consider whether to packaging, but also It is the agent.

	@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;
	}

What is earlyProxyReferences

Recall that this fact in order to solve the circular dependency of a single embodiment, in the example of the beanfollowing, the method requires a factory applied to singletonFactoriesthe collection:
Here Insert Picture Description
getEarlyBeanReferenceThis method is actually processed by the processor, the processor typically what not, return directly, only AOPthe processor will do the deal:
Here Insert Picture Description

AbstractAutoProxyCreator的getEarlyBeanReference

Is placed in the collection, and then determine whether or not the packaging, in fact, in the cycle of dependency injection property of time if there is AOPa proxy, then, will be the agent, and then return.
Here Insert Picture Description

wrapIfNecessary agent

The talk with the front Aspect annotation resolve almost, will first determine whether that has been treated, whether to skip, then skip directly into the advisedBeansinside, it means no proxy, but this beantreated, otherwise get notifications interceptors, then began a proxy.

	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;
		}
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

		// Create proxy if we have advice. 获取拦截器
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		if (specificInterceptors != DO_NOT_PROXY) {
			this.advisedBeans.put(cacheKey, Boolean.TRUE);//要代理的就添加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;
	}

getAdvicesAndAdvisorsForBean

In fact, the front section to check whether there notifier resolve advisorsto create, have returned, is no null.

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

		List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
		if (advisors.isEmpty()) {
			return DO_NOT_PROXY;
		}
		return advisors.toArray();
	}

findEligibleAdvisors

The first is to get all facets where Advisor, because analytical section on the article mentioned, the first custom beanbefore instantiation to parse out, so this time the general is acquired directly from the cache. Then find a suitable beanClass Advisor, and then expand, will add a ExposeInvocationInterceptorinternal instance DefaultPointcutAdvisor, in order to expose AOPcall, in case some AspectJtype of matching cut-off point, and finally, the sort here is very important, a direct impact on the method of notification after the call to order and then return.

	protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
		List<Advisor> candidateAdvisors = findCandidateAdvisors();//获取所有切面中的Advisor
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
		extendAdvisors(eligibleAdvisors);
		if (!eligibleAdvisors.isEmpty()) {
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);//排序
		}
		return eligibleAdvisors;
	}
findAdvisorsThatCanApply
	protected List<Advisor> findAdvisorsThatCanApply(
			List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {

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

AopUtils of findAdvisorsThatCanApply

The front is to determine IntroductionAdvisorthe type, this is with introductionfunctionally related, will use DeclareParentsannotations to say is that all classes in one package implements an interface, the specific implementation method will be used to achieve another class, you can put a class into an interface type, but also to achieve, do not need to change the original class, it is amazing, of course, we do not say that. We say in general. It is generally through each Advisor, and then determines whether applied to the target class clazz, the words can be added to the candidate list.

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

The canApply can be applied whether AopUtils

In fact, it can not be used, the cut-off point are defined Yeah, so just come here to match the cut point to be all right, he is really doing, specific internal code involved aspectj, interested to see it, now I know the general process is like, what I want to know what the point of tangency class in what package, what with the notification method, so you passed in class, I have to check to see advisorcan not be used:

	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) {
		Assert.notNull(pc, "Pointcut must not be null");
		if (!pc.getClassFilter().matches(targetClass)) {//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)) {//不是JDK的代理类
			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;
	}

Get results:

Here Insert Picture Description

Well, get notifications is basically finished, in fact, to match the definition of the class and you pass the point of tangency expression, then it will return in line with the corresponding notifier in preparation for the agent.

Well, here today, we hope to help study and understand, do not spray the Great God see, understand only their own learning, limited capacity, please excuse.

Published 235 original articles · won praise 74 · views 30000 +

Guess you like

Origin blog.csdn.net/wangwei19871103/article/details/105224019