Spring之AOP中代理对象创建时机

目录

1. 前言

2.动态代理对象创建的时机

3.循环依赖

4.AOP责任链的先后顺序

5.AOP代理失效原因


1. 前言

上一篇文章已经讲解过AOP责任链的实现原理(Spring之AOP的实现),这一篇文章主要讲解AOP中代理对象创建的时机,普通的IOC对象的创建流程见:Spring依赖注入(DI)之注解形式

2.动态代理对象创建的时机

我们回到Bean的创建过程,主要看AbstractAutowireCapableBeanFactory的doCreateBean方法

	protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {

		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
        //省略部分代码

		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isTraceEnabled()) {
				logger.trace("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			populateBean(beanName, mbd, instanceWrapper);
            //初始化bean
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		catch (Throwable ex) {
			
		}
        //省略部分代码

		return exposedObject;
	}

主要是看initializeBean方法

	protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
		if (mbd == null || !mbd.isSynthetic()) {
            //后置处理器
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}

AbstractAutowireCapableBeanFactory中的applyBeanPostProcessorsAfterInitialization方法,如下:

	@Override
	public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
            //调用其postProcessAfterInitialization
			Object current = processor.postProcessAfterInitialization(result, beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}

这里会有AnnotationAwareAspectJAutoProxyCreator它是专门用于生成AOP代理对象的处理器

但是AnnotationAwareAspectJAutoProxyCreator中并没有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;
	}

调用wrapIfNecessary方法去判断是需要创建代理对象

	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);
            //创建代理对象
			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方法先获取是否有增强,我们这里是有做around增强,我们看看这个方法:

	@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方法获取是否有增强

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

这里调用的是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;
	}

这个时候aspectJAdvisorsBuilder其实就是我们的LogAspect,buildAspectJAdvisors方法如下:

	public List<Advisor> buildAspectJAdvisors() {
		List<String> aspectNames = this.aspectBeanNames;
        
        //省略部分代码
		if (aspectNames.isEmpty()) {
			return Collections.emptyList();
		}
		List<Advisor> advisors = new ArrayList<>();
		for (String aspectName : aspectNames) {
            //获得的是logAround
			List<Advisor> 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;
	}

所以这里获得的是LogAspect中的logAround

这个时候回到了AbstractAdvisorAutoProxyCreator的findEligibleAdvisors方法中,会继续调用extendAdvisors方法,如下:

	@Override
	protected void extendAdvisors(List<Advisor> candidateAdvisors) {
		AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors);
	}

看,惊喜不,看方法名业知道是要在代理链上增加一个特殊的advisor,我们来看看这个方法:

	public static boolean makeAdvisorChainAspectJCapableIfNecessary(List<Advisor> advisors) {
		// Don't add advisors to an empty list; may indicate that proxying is just not required
		if (!advisors.isEmpty()) {
			boolean foundAspectJAdvice = false;
			for (Advisor advisor : advisors) {
				// Be careful not to get the Advice without a guard, as this might eagerly
				// instantiate a non-singleton AspectJ aspect...
				if (isAspectJAdvice(advisor)) {
					foundAspectJAdvice = true;
					break;
				}
			}
			if (foundAspectJAdvice && !advisors.contains(ExposeInvocationInterceptor.ADVISOR)) {
                //把ExposeInvocationInterceptor增加到第一个
				advisors.add(0, ExposeInvocationInterceptor.ADVISOR);
				return true;
			}
		}
		return false;
	}

看我们往advisors中增加了 ExposeInvocationInterceptor对象,放入到第一个元素,这个时候chain一共是有2个元素,如下所示:

我们再回到findEligibleAdvisors方法,增加了ExposeInvocationInterceptor之后,会调用sortAdvisors方法进行拦截器的排序,这里的排序涉及到责任链的顺序问题,先不展开,后面会详细讲到,这里只要知道排序后ExposeInvocationInterceptor会在第一个,然后就返回了Advisor列表,这时候只有两个元素。

我们就回到了AbstractAdvisorAutoProxyCreator的getAdvicesAndAdvisorsForBean方法中,如下:

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

如果增强列表为空,则返回一个null,表示不需要进行代理。这里我们知道返回的是有2个增强的持有增强列表。

然后我们再回到AbstractAutoProxyCreator的 wrapIfNecessary方法:

	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);
            //创建代理对象
			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;
	}

我们知道,我们获取到特定的增强拦截器不为DO_NOT_PROXY,则会调用createProxy方法去创建代理对象proxy,最终则返回这个代理对象。我们来createProxy方法:

	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 = new ProxyFactory();
		proxyFactory.copyFrom(this);

		if (!proxyFactory.isProxyTargetClass()) {
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}

		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		proxyFactory.addAdvisors(advisors);
		proxyFactory.setTargetSource(targetSource);
		customizeProxyFactory(proxyFactory);

		proxyFactory.setFrozen(this.freezeProxy);
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}
        //创建代理对象
		return proxyFactory.getProxy(getProxyClassLoader());
	}

我们主要看最后一行代码,getProxy方法得到代理对象

	public Object getProxy(@Nullable ClassLoader classLoader) {
		return createAopProxy().getProxy(classLoader);
	}

我们先看createAopProxy()方法,这个就是创建一个AopProxy对象,然后去调用它的getProxy方法得到代理对象,createAopProxy方法如下:

	protected final synchronized AopProxy createAopProxy() {
		if (!this.active) {
			activate();
		}
		return getAopProxyFactory().createAopProxy(this);
	}

这里的getAopProxyFactory获取到的是DefaultAopProxyFactory对象,我们来看看它的createAopProxy方法

	@Override
	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        //optimize为true或者proxyTargetClass为ture或者是没有实现
		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)) {
                //使用jdk动态代理
				return new JdkDynamicAopProxy(config);
			}
            //使用cglib动态代理
			return new ObjenesisCglibAopProxy(config);
		}
		else {
            //使用jdk动态代理
			return new JdkDynamicAopProxy(config);
		}
	}

可以看到,根据不同的规则去选择使用JDK动态代理还是使用CGLIB动态代理,因为我们这里本身有实现接口,且proxy-target-class: false设置为false,则使用的是JDK动态代理,即生成了JdkDynamicAopProxy对象。

然后需要调用其getProxy方法

	@Override
	public Object getProxy(@Nullable ClassLoader classLoader) {
		if (logger.isTraceEnabled()) {
			logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
		}
		Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
		findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
		return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
	}

可以看到,这里是调用了Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);方法去创建代理对象,需要注意的是第三个参数,传递的是this,因为JdkDynamicAopProxy本身实现了InvocationHandler接口,这就是上一章中讲到的Spring之AOP的实现_旭日的芬芳-CSDN博客,为什么在目标方法调用之前会先回调JdkDynamicAopProxy的invoke方法。

如果是CGLIB的动态代理呢?我们来看看CglibAopProxy中getProxy方法

	public Object getProxy(@Nullable ClassLoader classLoader) {
		if (logger.isTraceEnabled()) {
			logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
		}

		try {
			Class<?> rootClass = this.advised.getTargetClass();
			Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

			Class<?> proxySuperClass = rootClass;
			if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
				proxySuperClass = rootClass.getSuperclass();
				Class<?>[] additionalInterfaces = rootClass.getInterfaces();
				for (Class<?> additionalInterface : additionalInterfaces) {
					this.advised.addInterface(additionalInterface);
				}
			}

			// Validate the class, writing log messages as necessary.
			validateClassIfNecessary(proxySuperClass, classLoader);

			// Configure CGLIB Enhancer...
			Enhancer enhancer = createEnhancer();
			if (classLoader != null) {
				enhancer.setClassLoader(classLoader);
				if (classLoader instanceof SmartClassLoader &&
						((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
					enhancer.setUseCache(false);
				}
			}
			enhancer.setSuperclass(proxySuperClass);
			enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
			enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
			enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
            //得到callback回调
			Callback[] callbacks = getCallbacks(rootClass);
			Class<?>[] types = new Class<?>[callbacks.length];
			for (int x = 0; x < types.length; x++) {
				types[x] = callbacks[x].getClass();
			}
			// fixedInterceptorMap only populated at this point, after getCallbacks call above
			enhancer.setCallbackFilter(new ProxyCallbackFilter(
					this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
			enhancer.setCallbackTypes(types);

			// Generate the proxy class and create a proxy instance.
            //创建代理对象
			return createProxyClassAndInstance(enhancer, callbacks);
		}
		catch (CodeGenerationException | IllegalArgumentException ex) {
			throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
					": Common causes of this problem include using a final class or a non-visible class",
					ex);
		}
		catch (Throwable ex) {
			// TargetSource.getTarget() failed
			throw new AopConfigException("Unexpected AOP exception", ex);
		}
	}

我们先看getCallbacks方法,这个方法里会包装拦截器,如下:

	private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
		// Parameters used for optimization choices...
		boolean exposeProxy = this.advised.isExposeProxy();
		boolean isFrozen = this.advised.isFrozen();
		boolean isStatic = this.advised.getTargetSource().isStatic();

		// Choose an "aop" interceptor (used for AOP calls).
		Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);

		// Choose a "straight to target" interceptor. (used for calls that are
		// unadvised but can return this). May be required to expose the proxy.
		Callback targetInterceptor;
		if (exposeProxy) {
			targetInterceptor = (isStatic ?
					new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
					new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
		}
		else {
			targetInterceptor = (isStatic ?
					new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
					new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
		}

		// Choose a "direct to target" dispatcher (used for
		// unadvised calls to static targets that cannot return this).
		Callback targetDispatcher = (isStatic ?
				new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());

		Callback[] mainCallbacks = new Callback[] {
                //AOP的拦截器
				aopInterceptor,  // for normal advice
				targetInterceptor,  // invoke target without considering advice, if optimized
				new SerializableNoOp(),  // no override for methods mapped to this
				targetDispatcher, this.advisedDispatcher,
				new EqualsInterceptor(this.advised),
				new HashCodeInterceptor(this.advised)
		};

		Callback[] callbacks;

		// If the target is a static one and the advice chain is frozen,
		// then we can make some optimizations by sending the AOP calls
		// direct to the target using the fixed chain for that method.
		if (isStatic && isFrozen) {
			Method[] methods = rootClass.getMethods();
			Callback[] fixedCallbacks = new Callback[methods.length];
			this.fixedInterceptorMap = new HashMap<>(methods.length);

			// TODO: small memory optimization here (can skip creation for methods with no advice)
			for (int x = 0; x < methods.length; x++) {
				Method method = methods[x];
				List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass);
				fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
						chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
				this.fixedInterceptorMap.put(method, x);
			}

			// Now copy both the callbacks from mainCallbacks
			// and fixedCallbacks into the callbacks array.
			callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
			System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
			System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
			this.fixedInterceptorOffset = mainCallbacks.length;
		}
		else {
			callbacks = mainCallbacks;
		}
		return callbacks;
	}

我们主要是关心下面这个拦截器,它是用于普通的aop增强的拦截

Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);

这个对象不就是上一章中我们讲到的CGLIB动态实现中的回调类么?在获取到拦截器后,再调用了createProxyClassAndInstance方法去创建代理类。方法如下:

	protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
		enhancer.setInterceptDuringConstruction(false);
		enhancer.setCallbacks(callbacks);
		return (this.constructorArgs != null && this.constructorArgTypes != null ?
				enhancer.create(this.constructorArgTypes, this.constructorArgs) :
				enhancer.create());
	}

可以看到,就是通过Enhancer的setCallback去设置回调,并调用它的create方法去创建代理对象。

这个时候,代理对象就创建出来了。我们再回到AbstractAutoProxyCreator的wrapIfNecessary方法,然后一步一步返回这个代理对象就回到了AbstractAutowireCapableBeanFactory的doCreateBean方法

exposedObject = initializeBean(beanName, exposedObject, mbd);

这个时候,exposedObject就是一个代理对象了,我们继续往下看,会调用addSingleton方法,把创建的代理对象放入到内存缓存singletonObjects中

protected void addSingleton(String beanName, Object singletonObject) {
   synchronized (this.singletonObjects) {
      this.singletonObjects.put(beanName, singletonObject);
      this.singletonFactories.remove(beanName);
      this.earlySingletonObjects.remove(beanName);
      this.registeredSingletons.add(beanName);
   }
}

这样,IOC容器就帮我们创建了一个代理对象,并存入到了singletonObjects中,它的key是AOPTestController,它的值是一个通过JDK动态代理生成的代理对象。如下:

3.循环依赖

我们在上一章Spring依赖注入(DI)之注解形式_旭日的芬芳-CSDN博客最后有讲到IOC循环依赖的问题,有用到三级缓存,但是为什么是三级缓存而不是两级缓存呢?(1个半成品的bean,1成品的bean)

我们先回顾下之前的三级缓存:

//一级缓存,成品bean
Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

//二级缓存,半成品bean
Map<String, Object> earlySingletonObjects = new HashMap<>(16);

//三级缓存, bean工厂
Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

其实,如果不考虑AOP的机制,通过二级缓存是可以解决循环依赖的问题的,如下:

可以看到,只要我们在创建a以后,把这个半成品放入二级缓存中,再在给b属性a复制时,从二级缓存中获取到a,就能完成b的创建,进而完成a的创建。

但如果我们a对象是一个代理对象,这个时候机制就不一样了,当给b属性赋值时,理论上是需要给它赋值一个a的代理对象,而从二级缓存中获取到的是a对象本身,这样就起不到代理作用了。

这也就是三级缓存的意义,如下图:

也就是完成A对象实例化后,把A的Bean工厂放到三级缓存中,当需要为b的属性a赋值时,是从三级缓存中拿到A的Bean工厂,创建A的代理对象,把A的代理对象放入到二级缓存中,并返回用于初始化b中的a属性。

所以,三级缓存的作用就是解决AOP中的循环依赖,把生成代理对象的过程提前了。

4.AOP责任链的先后顺序

再回到findEligibleAdvisors方法,增加了ExposeInvocationInterceptor之后,会调用sortAdvisors方法进行拦截器的排序,而这个方法是由它的子类AspectJAwareAdvisorAutoProxyCreator来实现的,我们来看看这个方法:

	@Override
	@SuppressWarnings("unchecked")
	protected List<Advisor> sortAdvisors(List<Advisor> advisors) {
		List<PartiallyComparableAdvisorHolder> partiallyComparableAdvisors = new ArrayList<>(advisors.size());
		for (Advisor element : advisors) {
			partiallyComparableAdvisors.add(
					new PartiallyComparableAdvisorHolder(element, DEFAULT_PRECEDENCE_COMPARATOR));
		}
		List<PartiallyComparableAdvisorHolder> sorted = PartialOrder.sort(partiallyComparableAdvisors);
		if (sorted != null) {
			List<Advisor> result = new ArrayList<>(advisors.size());
			for (PartiallyComparableAdvisorHolder pcAdvisor : sorted) {
				result.add(pcAdvisor.getAdvisor());
			}
			return result;
		}
		else {
			return super.sortAdvisors(advisors);
		}
	}

这里是使用AspectJPrecedenceComparator对象来创建了一个PartiallyComparableAdvisorHolder对象来进行比较,我们来看看这个比较器的compare方法:

	@Override
	public int compare(Advisor o1, Advisor o2) {
		int advisorPrecedence = this.advisorComparator.compare(o1, o2);
		if (advisorPrecedence == SAME_PRECEDENCE && declaredInSameAspect(o1, o2)) {
			advisorPrecedence = comparePrecedenceWithinAspect(o1, o2);
		}
		return advisorPrecedence;
	}

可以看到,先是调用advisorComparator的compare方法进行比较,如果比较出来是相同的优先级且声明在相同的切面里,则调用comparePrecedenceWithinAspect中继续比较。

我们先看advisorComparator的compare,advisorComparator是一个AnnotationAwareOrderComparator对象,但它并没有实现compare方法,而需要看它的父类OrderComparator,我来看看该方法

    public int compare(@Nullable Object o1, @Nullable Object o2) {
        return this.doCompare(o1, o2, (OrderComparator.OrderSourceProvider)null);
    }

    private int doCompare(@Nullable Object o1, @Nullable Object o2, @Nullable OrderComparator.OrderSourceProvider sourceProvider) {
        boolean p1 = o1 instanceof PriorityOrdered;
        boolean p2 = o2 instanceof PriorityOrdered;
        if (p1 && !p2) {
            return -1;
        } else if (p2 && !p1) {
            return 1;
        } else {
            int i1 = this.getOrder(o1, sourceProvider);
            int i2 = this.getOrder(o2, sourceProvider);
            return Integer.compare(i1, i2);
        }
    }

这里会先判断比较的对象是否实现PriorityOrdered接口,这里都没有实现,则会分别调用getOrder方法去获取order的值,

	private int getOrder(@Nullable Object obj, @Nullable OrderSourceProvider sourceProvider) {
		Integer order = null;
		if (obj != null && sourceProvider != null) {
			Object orderSource = sourceProvider.getOrderSource(obj);
			if (orderSource != null) {
				if (orderSource.getClass().isArray()) {
					Object[] sources = ObjectUtils.toObjectArray(orderSource);
					for (Object source : sources) {
						order = findOrder(source);
						if (order != null) {
							break;
						}
					}
				}
				else {
					order = findOrder(orderSource);
				}
			}
		}
		return (order != null ? order : getOrder(obj));
	}

这里会调用getOrder方法

	protected int getOrder(@Nullable Object obj) {
		if (obj != null) {
			Integer order = findOrder(obj);
			if (order != null) {
				return order;
			}
		}
		return Ordered.LOWEST_PRECEDENCE;
	}

而在getOrder方法中会调用findOrder方法获取order,如果没有获取到则返回最低的优先级,这里findOrder实际调用的是子类AnnotationAwareOrderComparator的findOrder方法

	@Override
	@Nullable
	protected Integer findOrder(Object obj) {
		Integer order = super.findOrder(obj);
		if (order != null) {
			return order;
		}
		return findOrderFromAnnotation(obj);
	}

这里是先调用父类的findOrder方法,如下:

    @Nullable
    protected Integer findOrder(Object obj) {
        return obj instanceof Ordered ? ((Ordered)obj).getOrder() : null;
    }

如果实现了Ordered接口,则调用getOrder得到order,如果没有则返回null,我们自定义的切面增强其实是属于InstantiationModelAwarePointcutAdvisorImpl实体,下面是它的定义:

final class InstantiationModelAwarePointcutAdvisorImpl
		implements InstantiationModelAwarePointcutAdvisor, AspectJPrecedenceInformation, Serializable {

而AspectJPrecedenceInformation就是一个继承于Ordered的接口,定义如下:

public interface AspectJPrecedenceInformation extends Ordered {

所以我们的环绕增强,其实也是属于Ordered,所以会调用它的getOrder方法,但不管怎么样,最后会调用到OrderUtils中的getOrder方法

	public static int getOrder(Class<?> type, int defaultOrder) {
		Integer order = getOrder(type);
		return (order != null ? order : defaultOrder);
	}

会先调用getOrder方法,这里返回的为null,则是给定的默认排序,这里默认的排序是Integer的最大值,因为order定义为Integer,其实这里就是最低优先级

int LOWEST_PRECEDENCE = Integer.MAX_VALUE;

我们再回到AnnotationAwareOrderComparator的findOrder方法,这个时候order就有值了,然后我们再看ExposeInvocationInterceptor,它本身实现了PriorityOrdered(是Ordered接口的子接口)接口,并且实现了getOrder方法

	@Override
	public int getOrder() {
		return PriorityOrdered.HIGHEST_PRECEDENCE + 1;
	}

而HIGHEST_PRECEDENCE是在Ordered中定义的,表示最高优先级

public interface Ordered {
    int HIGHEST_PRECEDENCE = -2147483648;
    int LOWEST_PRECEDENCE = 2147483647;

    int getOrder();
}

这也是为什么ExposeInvocationInterceptor会排序到最前面的原因,我们回到AspectJPrecedenceComparator的compare方法

	@Override
	public int compare(Advisor o1, Advisor o2) {
		int advisorPrecedence = this.advisorComparator.compare(o1, o2);
		if (advisorPrecedence == SAME_PRECEDENCE && declaredInSameAspect(o1, o2)) {
			advisorPrecedence = comparePrecedenceWithinAspect(o1, o2);
		}
		return advisorPrecedence;
	}

这个时候advisorPrecedence=1,即环绕增强的优先级更低,如下图所示:

这个如果是两个没有实现Ordered接口或者实现了Ordered接口但是返回的order一致的情况下,

比如我们自己定义的切面,没有实现Ordered接口,则这里返回了null,则

核心方法是在comparePrecedenceWithinAspect中,会先判断是否是后置增强,如果是后置增强,则越晚声明权限越高,否则越早声明权限越高。

是直接调用的AnnotationAwareOrderComparator.sort方法进行排序,方法如下:

    public static void sort(List<?> list) {
        if (list.size() > 1) {
            list.sort(INSTANCE);
        }

    }

这里传入的是AnnotationAwareOrderComparator的实例,我们来看看它的findOrder方法

    @Nullable
    protected Integer findOrder(Object obj) {
        Integer order = super.findOrder(obj);
        return order != null ? order : this.findOrderFromAnnotation(obj);
    }

    @Nullable
    private Integer findOrderFromAnnotation(Object obj) {
        AnnotatedElement element = obj instanceof AnnotatedElement ? (AnnotatedElement)obj : obj.getClass();
        MergedAnnotations annotations = MergedAnnotations.from((AnnotatedElement)element, SearchStrategy.TYPE_HIERARCHY);
        Integer order = OrderUtils.getOrderFromAnnotations((AnnotatedElement)element, annotations);
        return order == null && obj instanceof DecoratingProxy ? this.findOrderFromAnnotation(((DecoratingProxy)obj).getDecoratedClass()) : order;
    }

会先调用super.findOrder方法,调用的是OrderComparator的findOrder方法,下面是这个类的源码

    @Nullable
    protected Integer findOrder(Object obj) {
        return obj instanceof Ordered ? ((Ordered)obj).getOrder() : null;
    }

这里就是判断我们的切面是否实现了Ordered接口,如果实现了,则直接调用其getOrder得到排序的循序。这其实就是上一讲当中讲到的,对相同连接点的多个切面的先后顺序的实现了。

5.AOP代理失效原因

在有些情况下,AOP会失效,我们在AOPTestController中创建a、b两个方法,如下:

@RestController
@RequestMapping("aop")
@Api(tags = "测试AOP")
public class AOPTestController {


    @Log
    @PostMapping(value = "a")
    public String a() {
        return "a";
    }

    @Log
    @PostMapping(value = "b")
    public String b() {
        return "b";
    }
}

我们分别请求下a、b接口,发现的确是有日志拦截的,证明AOP是生效了的。

但是我们如果,在a方法中去调用b方法,这个时候会有b方法被调用的日志输出么?代码如下:

    @Log
    @PostMapping(value = "a")
    public String a() {
        // 手动调用b方法
        b();
        return "a";
    }

下面是运行结果

我们发现只有a方法的日志,而没有b方法的日志,这个其实不难理解,AOP的实现原理是需要生成代理对象,当我们调用业务方法时,其实是先回调了DynamicAdvisedInterceptor中的intercept方法或者JdkDynamicAopProxy的invoke方法,然后会去遍历增强,并且会去调用业务方法,但是真正调用到业务方法时,在业务方法中去调用其他方法时,没有使用代理对象,而是直接调用的被代理对象的方法,所以就不会有拦截日志,像上面的就是直接调用的AOPTestController的b方法。这样,看起来好像AOPTestController的b方法的AOP失效了,虽然它也使用了@Log注解。

那要怎么做才能让b方法也能走日志拦截呢?

根据上面的分析,其实我们也知道答案了,就是需要通过AOPTestController的代理对象来调用b方法嘛。

Spring提供了一个AopContext类,它有一个currentProxy方法可以获取到当前类的代理对象,代码如下

    @Log
    @PostMapping(value = "a")
    public String a() {
        ((AOPTestController)AopContext.currentProxy()).b();
        return "a";
    }

调用结果如下:

发现报错了,是需要设置exposeProxy,我们可以在启动的Application中增加如下注解:

@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)

 这个时候,我们再调用a方法,结果如下:

可以看到,b也有拦截日志,并且是跟我们方法执行的顺序一致:a方法参数-> b方法参数->b方法返回->a方法返回

  • 12
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值