·

老生常谈系列之Aop--Spring Aop源码解析(二)

老生常谈系列之Aop--Spring Aop源码解析(二)

前言

上一篇文章老生常谈系列之Aop--Spring Aop源码解析(一)已经介绍完Spring Aop获取advice切面增强方法的逻辑,那这篇会介绍Spring Aop是怎么根据上面获取的advice生产动态代理的,并且会介绍advice是怎么执行的,例如怎么确保@Before的逻辑在@After前面执行。

源码分析

以下代码分析基于Spring版本5.2.x,另外部分地方我摘抄保留了英文注释,希望看官可以用心体会。

我们回到AbstractAutoProxyCreator#wrapIfNecessary()方法里,上面的部分已经分析完成,下面从Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean))开始。

	protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		// 省略部分逻辑...
		// 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;
	}

跟进createProxy()方法,对于代理类的创建及处理, Spring 委托给了 ProxyFactory去处理,而在此函数中主要是对 ProxyFactory的初始化操作,进而对真正的创建代理做准备。

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

		// 决定对于给定的 bean 是否应该使用 targetClass 而不是它的接口代理,
		// 检查 proxyTargetClass 设置以及 preserveTargetClass 属性
		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);

		// 用来控制代理工厂被配置之后,是否还允许修改通知
		// 缺省值为 false 即在代理被配置之后, 不允许修改代理的配置
		proxyFactory.setFrozen(this.freezeProxy);
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}

		return proxyFactory.getProxy(getProxyClassLoader());
	}

可以上到上面的准备工作包括了以下几步:

  • 获取当前类中的属性。
  • 添加代理接口 。
  • 封装 Advisor 并加入到 ProxyFactory 中。
  • 设置要代理的类。
  • 当然在 Spring 中还为子类提供了定制的函数 customizeProxyFactory,子类可以在此函数中进行对 ProxyFactory的进一步封装。
  • 设置frozen和preFiltered
  • 进行获取代理操作。

其中,封装 Advisor 并加入到 ProxyFactory 中以及创建代理是两个相对繁琐的过程,可以通过ProxyFactory提供的 addAdvisor 方法直接将增强器置人代理创建工厂中,但是将拦截器封装为增强器还是需要一定的逻辑的。ProxyFactory类提供了非常好的一个抽象操作,addAdvisorgetProxy()两个方法完成了我们所有的创建代理,里面隐藏了非常多的细节操作,那下面的分析会从准备工作的几步开始,分析每一步的代码做了什么。

1.获取当前类中的属性

这段逻辑只是简单的一句,入参为本身this,跟进copyFrom()方法。

proxyFactory.copyFrom(this);

可以看到只是简单的赋值操作,入参类型为ProxyConfig,由于AbstractAutoProxyCreator间接实现了ProxyConfig接口,这里只是把AbstractAutoProxyCreator里的几个属性赋值到接下来要使用的ProxyFactory 中。

	public void copyFrom(ProxyConfig other) {
		Assert.notNull(other, "Other ProxyConfig object must not be null");
		this.proxyTargetClass = other.proxyTargetClass;
		this.optimize = other.optimize;
		this.exposeProxy = other.exposeProxy;
		this.frozen = other.frozen;
		this.opaque = other.opaque;
	}

2.添加代理接口

添加属性完成后,接下来是根据proxyTargetClass属性设置ProxyFactoryproxyTargetClass属性和添加代理接口。这是个啥属性呢?没印象?那说明前面的文章根本没看。proxyTargetClass 定义是否强制使用CGLIB代理,默认是false,不使用。所以如果开了强制使用CGLIB的话,这段逻辑会被跳过,不会进行代理接口的添加。

		if (!proxyFactory.isProxyTargetClass()) {
                        // 是否基于类代理 preserveTargetClass = true 则是基于类代理
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {
				// 添加代理接口
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}

如果proxyTargetClass = false的话,会进入这段逻辑。简单看一下shouldProxyTargetClass()代码,这里摘取了方法上的注解,可以品味一下。

	/**
	 * Determine whether the given bean should be proxied with its target class rather than its interfaces.
	 * <p>Checks the {@link AutoProxyUtils#PRESERVE_TARGET_CLASS_ATTRIBUTE "preserveTargetClass" attribute}
	 * of the corresponding bean definition.
	 * @param beanClass the class of the bean
	 * @param beanName the name of the bean
	 * @return whether the given bean should be proxied with its target class
	 * @see AutoProxyUtils#shouldProxyTargetClass
	 */
	protected boolean shouldProxyTargetClass(Class<?> beanClass, @Nullable String beanName) {
		return (this.beanFactory instanceof ConfigurableListableBeanFactory &&
				AutoProxyUtils.shouldProxyTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName));
	}

## AutoProxyUtils#shouldProxyTargetClass
	public static boolean shouldProxyTargetClass(
			ConfigurableListableBeanFactory beanFactory, @Nullable String beanName) {

		if (beanName != null && beanFactory.containsBeanDefinition(beanName)) {
			BeanDefinition bd = beanFactory.getBeanDefinition(beanName);
			return Boolean.TRUE.equals(bd.getAttribute(PRESERVE_TARGET_CLASS_ATTRIBUTE));
		}
		return false;
	}

首先会通过shouldProxyTargetClass()判断是否基于类代理,这个方法是通过判断preserveTargetClass属性是否为true。如果是,则设置proxyTargetClass = true,看到这菊花一紧。preserveTargetClass的字面意思是保留目标类,摘取属性上的描述如下:

	/**
	 * Bean definition attribute that may indicate whether a given bean is supposed
	 * to be proxied with its target class (in case of it getting proxied in the first
	 * place). The value is {@code Boolean.TRUE} or {@code Boolean.FALSE}.
	 * <p>Proxy factories can set this attribute if they built a target class proxy
	 * for a specific bean, and want to enforce that bean can always be cast
	 * to its target class (even if AOP advices get applied through auto-proxying).
	 * @see #shouldProxyTargetClass
	 */
	public static final String PRESERVE_TARGET_CLASS_ATTRIBUTE =
			Conventions.getQualifiedAttributeName(AutoProxyUtils.class, "preserveTargetClass");

翻译一下:这是BeanDefinition定义的属性,它可以指示给定的 bean 是否应该与其目标类一起代理(以防它首先被代理)。该值为Boolean.TRUEBoolean.FALSE。如果代理工厂为特定 bean 构建了目标类代理,并且希望强制该 bean 始终可以转换为其目标类(即使 AOP 建议通过自动代理应用),则可以设置此属性。

这一段翻译看完,应该就比较明了了。这是有特殊的要求希望代理类可以强制转换为目标类,可以设置这个属性。

举个例子如下,如果A和B是接口,C是实现类,那么走自动代理的时候会走JDK动态代理,代理会实现A、B接口,如果想把这个代理强制转换成C类型,可能会报错。这时候可以设置preserveTargetClass = true,直接代理目标类,这时候再转换,就不会出错。当然这是我猜测的原因,因为很少有人提及这个属性,我只是参考源码注释和实现给出的原因,错了轻拍。

1641802884258

以前只知道proxyTargetClass能够设置是否强制进行类代理,而不知道preserveTargetClass也能设置强制进行类代理。可能是由于这是BeanDefinition的属性,这是比注解上的属性更底层的属性,所以露面的机会少点。可能Spring不希望大部分人直接使用,但是如果要用,还是可以设置,相当于留了个后门。

如果没有设置preserveTargetClass,那么就进入evaluateProxyInterfaces(beanClass, proxyFactory)方法,添加代理接口。

	/**
	 * Check the interfaces on the given bean class and apply them to the {@link ProxyFactory},
	 * if appropriate.
	 * <p>Calls {@link #isConfigurationCallbackInterface} and {@link #isInternalLanguageInterface}
	 * to filter for reasonable proxy interfaces, falling back to a target-class proxy otherwise.
	 * @param beanClass the class of the bean
	 * @param proxyFactory the ProxyFactory for the bean
	 */
	protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
		Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
                // 是否存在符合条件的接口
		boolean hasReasonableProxyInterface = false;
		for (Class<?> ifc : targetInterfaces) {
			if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) &&
					ifc.getMethods().length > 0) {
				hasReasonableProxyInterface = true;
				break;
			}
		}
		if (hasReasonableProxyInterface) {
			// Must allow for introductions; can't just set interfaces to the target's interfaces only.
                        // 加入接口,同时要允许introductions也能加入接口,不能仅仅设置当前类的接口,introductions类型的接口什么时候加入,下面第三点会说到
			for (Class<?> ifc : targetInterfaces) {
				proxyFactory.addInterface(ifc);
			}
		}
		else {
			proxyFactory.setProxyTargetClass(true);
		}
	}

这段逻辑也简单明了,获取beanClass的所有接口,判断这些接口是否值得代理。如果有hasReasonableProxyInterface = true,就通过proxyFactory.addInterface(ifc)加入到this.interfaces里,随后通过adviceChanged()刷新缓存。

3.封装 Advisor 并加入到 ProxyFactory 中

封装Advisor

设置完相关属性后,这里才进入正题,开始封装Advisor ,并加入到ProxyFactory 中。

	/**
	 * Determine the advisors for the given bean, including the specific interceptors
	 * as well as the common interceptor, all adapted to the Advisor interface.
	 * @param beanName the name of the bean
	 * @param specificInterceptors the set of interceptors that is
	 * specific to this bean (may be empty, but not null)
	 * @return the list of Advisors for the given bean
	 */
	protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
		// Handle prototypes correctly...
		// 解析通用的拦截器interceptorNames,interceptorNames是通过setInterceptorNames()设置的
		Advisor[] commonInterceptors = resolveInterceptorNames();

		List<Object> allInterceptors = new ArrayList<>();
		if (specificInterceptors != null) {
			// 加入指定的拦截器
			allInterceptors.addAll(Arrays.asList(specificInterceptors));
                        // 如果有通用拦截器,加入通用的拦截器,通常情况下commonInterceptors.length=0
			if (commonInterceptors.length > 0) {
                                // 如果是先应用通用拦截器,则加到前面,否则加到后面
				if (this.applyCommonInterceptorsFirst) {
					allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
				}
				else {
					allInterceptors.addAll(Arrays.asList(commonInterceptors));
				}
			}
		}
		// 省略日志...
		Advisor[] advisors = new Advisor[allInterceptors.size()];
		for (int i = 0; i < allInterceptors.size(); i++) {
			// 对拦截然进行封装转化为 Advisor
			advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
		}
		return advisors;
	}

这段代码的逻辑主要分为两部分:

  • 将获取到的通用拦截器commonInterceptors和方法传入的specificInterceptors加入到allInterceptors
  • allInterceptors进行封装,返回advisors

首先看第一部分,跟进resolveInterceptorNames()方法。

	/**
	 * Resolves the specified interceptor names to Advisor objects.
	 * @see #setInterceptorNames
	 */
	private Advisor[] resolveInterceptorNames() {
		BeanFactory bf = this.beanFactory;
		ConfigurableBeanFactory cbf = (bf instanceof ConfigurableBeanFactory ? (ConfigurableBeanFactory) bf : null);
		List<Advisor> advisors = new ArrayList<>();
		for (String beanName : this.interceptorNames) {
			if (cbf == null || !cbf.isCurrentlyInCreation(beanName)) {
				Assert.state(bf != null, "BeanFactory required for resolving interceptor names");
				Object next = bf.getBean(beanName);
				advisors.add(this.advisorAdapterRegistry.wrap(next));
			}
		}
		return advisors.toArray(new Advisor[0]);
	}

主要是对interceptorNames属性进行遍历,根据beanName到容器中获取这个bean,然后封装成advisors返回。

那这个interceptorNames是个啥呢?这就是通用拦截器的名字,默认是空。可以通过调用setInterceptorNames()方法设置,搜索了一下Spring里调用这个方法的地方,发现没有,所以这个地方默认就是空的,可以是看做Spring留了个扩展点。

	/** Default is no common interceptors. */
	private String[] interceptorNames = new String[0];

	/**
	 * Set the common interceptors. These must be bean names in the current factory.
	 * They can be of any advice or advisor type Spring supports.
	 * <p>If this property isn't set, there will be zero common interceptors.
	 * This is perfectly valid, if "specific" interceptors such as matching
	 * Advisors are all we want.
	 */
	public void setInterceptorNames(String... interceptorNames) {
		this.interceptorNames = interceptorNames;
	}

处理完了通用拦截器部分,接下来直接把specificInterceptors加入到allInterceptors里。通常情况下,可以认为allInterceptors的内容就是传进来的specificInterceptors

到这里处理完了第一部分获取allInterceptors,接下来是第二部分对allInterceptors进行封装,返回advisors

advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));

这一部分委托给了DefaultAdvisorAdapterRegistry#wrap()去实现,直接跟进代码,这里比较简单,只是简单封装为Advisor

	public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
		// 如果要封装的对象本身就是 Advisor类型的,那么无须再做过多处理
		if (adviceObject instanceof Advisor) {
			return (Advisor) adviceObject;
		}
		// 因为此封装方法只对 Advisor 与 Advice 两种类型的数据有效, 如果不是将不能封装
		if (!(adviceObject instanceof Advice)) {
			throw new UnknownAdviceTypeException(adviceObject);
		}
		Advice advice = (Advice) adviceObject;
		if (advice instanceof MethodInterceptor) {
			// So well-known it doesn't even need an adapter.
			// 如果是 MethodInterceptor 类型则使用 DefaultPointcutAdvisor 封装
			return new DefaultPointcutAdvisor(advice);
		}
		// 如果存在 Advisor 的适配器那么也同样需要进行封装
		for (AdvisorAdapter adapter : this.adapters) {
			// Check that it is supported.
			if (adapter.supportsAdvice(advice)) {
				return new DefaultPointcutAdvisor(advice);
			}
		}
		throw new UnknownAdviceTypeException(advice);
	}

到这里已经把所有的拦截器转换成统一的Advisor,下面就准备设置进ProxyFactory 里。

将Advisor加入ProxyFactory

一行代码,跟进addAdvisors()

proxyFactory.addAdvisors(advisors);

可以看到也是简单的赋值操作,把入参的advisors赋值到this.advisors,注意这里有个特殊操作validateIntroductionAdvisor(),这是用来处理IntroductionAdvisor类型的Advisor,核心操作就是校验IntroductionAdvisor的接口,如果符合,那就加入到this.interfaces里,这跟上面添加代理接口evaluateProxyInterfaces(beanClass, proxyFactory)逻辑是类似的。最后会更新this.advisorArraythis.methodCache,这两个缓存主要用于内部操作,节省时间。

	/**
	 * Add all of the given advisors to this proxy configuration.
	 * @param advisors the advisors to register
	 */
	public void addAdvisors(Advisor... advisors) {
		addAdvisors(Arrays.asList(advisors));
	}

	/**
	 * Add all of the given advisors to this proxy configuration.
	 * @param advisors the advisors to register
	 */
	public void addAdvisors(Collection<Advisor> advisors) {
		if (isFrozen()) {
			throw new AopConfigException("Cannot add advisor: Configuration is frozen.");
		}
		if (!CollectionUtils.isEmpty(advisors)) {
			for (Advisor advisor : advisors) {
				if (advisor instanceof IntroductionAdvisor) {
					validateIntroductionAdvisor((IntroductionAdvisor) advisor);
				}
				Assert.notNull(advisor, "Advisor must not be null");
				this.advisors.add(advisor);
			}
                        // 更新this.advisorArray
			updateAdvisorArray();
                        // 更新this.methodCache
			adviceChanged();
		}
	}

4.设置要代理的类

这一步也比较简单,把传入的targetSource设置到proxyFactory中,如果为空,则将targetSource设为EMPTY_TARGET_SOURCEEMPTY_TARGET_SOURCE是一个特殊的TargetSource它是在没有目标类或者只有advisors或者interfaces的时候使用。

	public void setTargetSource(@Nullable TargetSource targetSource) {
		this.targetSource = (targetSource != null ? targetSource : EMPTY_TARGET_SOURCE);
	}

5.定制的函数 customizeProxyFactory

目前是个空实现,交由子类实现,提供了自定义扩展的点。

	customizeProxyFactory(proxyFactory);

AbstractAutoProxyCreator中的实现为空。


	/**
	 * Subclasses may choose to implement this: for example,
	 * to change the interfaces exposed.
	 * <p>The default implementation is empty.
	 * @param proxyFactory a ProxyFactory that is already configured with
	 * TargetSource and interfaces and will be used to create the proxy
	 * immediately after this method returns
	 */
	protected void customizeProxyFactory(ProxyFactory proxyFactory) {
	}

6.设置frozen和preFiltered

这里的代码也比较简单

		// 用来控制代理工厂被配置之后,是否还允许修改通知
		// 缺省值为 false 即在代理被配置之后, 不允许修改代理的配置 )
		proxyFactory.setFrozen(this.freezeProxy);
		// 是否已经被预过滤,如果是预过滤,可以不执行Pointcut持有的ClassFilter
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}

frozen用来冻结advice的修改。这里主要是用来作为内部一些性能的优化,摘取描述如下:

	/**
	 * Set whether this config should be frozen.
	 * <p>When a config is frozen, no advice changes can be made. This is
	 * useful for optimization, and useful when we don't want callers to
	 * be able to manipulate configuration after casting to Advised.
	 */
	public void setFrozen(boolean frozen) {
		this.frozen = frozen;
	}

preFiltered可能相对难理解一点, 设置当前AOP配置信息是否已被超前过滤过了,如果是的话,可以不执行Pointcut持有的ClassFilter 。

	/**
	 * Set whether this proxy configuration is pre-filtered so that it only
	 * contains applicable advisors (matching this proxy's target class).
	 * <p>Default is "false". Set this to "true" if the advisors have been
	 * pre-filtered already, meaning that the ClassFilter check can be skipped
	 * when building the actual advisor chain for proxy invocations.
	 * @see org.springframework.aop.ClassFilter
	 */
	void setPreFiltered(boolean preFiltered);

7.进行获取代理操作

获取JDK动态代理或CGLIB代理

完成了上面的步骤之后,开始进入了本文章的重头戏,创建代理。

进入getProxy()方法,这里就会根据上面设置的属性生成代理对象,生成的对象会因为添加或删除interfacesinterceptors而不同。

	/**
	 * Create a new proxy according to the settings in this factory.
	 * <p>Can be called repeatedly. Effect will vary if we've added
	 * or removed interfaces. Can add and remove interceptors.
	 * <p>Uses the given class loader (if necessary for proxy creation).
	 * @param classLoader the class loader to create the proxy with
	 * (or {@code null} for the low-level proxy facility's default)
	 * @return the proxy object
	 */
	public Object getProxy(@Nullable ClassLoader classLoader) {
		/**
		 * 首先获取AopProxy对象,主要有两个实现JdkDynamicAopProxy和ObjenesisCglibAopProxy
		 * 分别用于jdk和Cglib动态代理生成,其getProxy()方法用于获取具体的代理类对象
		 */
		return createAopProxy().getProxy(classLoader);
	}

跟进createAopProxy(),如果this.active=false,首先调用activate()激活所有的AdvisedSupportListener,然后通过getAopProxyFactory()获取一个aopProxyFactory,再调用createAopProxy(this)获取AopProxy

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

getAopProxyFactory()用于获取aopProxyFactoryaopProxyFactory会在new ProxyFactory()的时候创建this.aopProxyFactory = new DefaultAopProxyFactory(),逻辑比较简单,这里不再分析。接下来看createAopProxy(this)

	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
		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.");
			}
			/**
			 * 如果要代理的类本身就是接口
			 * 或者它已经是个jdk的代理类(Proxy的子类,所有的jdk代理类都是此类的子类)
			 * 也会用jdk动态代理
			 */
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
				return new JdkDynamicAopProxy(config);
			}
                        // 返回一个CglibAopProxy
			return new ObjenesisCglibAopProxy(config);
		}
		else {
			//如果有接口,就会跑到这个分支
			return new JdkDynamicAopProxy(config);
		}
	}

可以跟着注释看一下,这里决定了是使用JDK动态代理还是CGLIB代理。

JdkDynamicAopProxy实现

接下来就以JdkDynamicAopProxy为例,分析一下真正生成动态代理的getProxy()逻辑。

直接看代码

	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);
                // 查找是否存在equals()和hashCode()方法
		findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
                // 调用JDK动态代理的API生成代理
		return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
	}

这里的逻辑也简单明了,先获取最终的完整的代理接口,查找是否存在equals()hashCode()方法,最后调用Proxy.newProxyInstance()生成动态代理。

先来看获取完整代理接口的方法AopProxyUtils.completeProxiedInterfaces(this.advised, true)。这个方法先获取了指定的代理接口,然后获取SpringProxyAdvisedDecoratingProxy三个接口,最后返回proxiedInterfaces

	static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised, boolean decoratingProxy) {
		Class<?>[] specifiedInterfaces = advised.getProxiedInterfaces();
		if (specifiedInterfaces.length == 0) {
			// No user-specified interfaces: check whether target class is an interface.
                        // 没有指定的代理接口,检查target class 是不是接口或者是不是Proxy的子类
			Class<?> targetClass = advised.getTargetClass();
			if (targetClass != null) {
				if (targetClass.isInterface()) {
					advised.setInterfaces(targetClass);
				}
				else if (Proxy.isProxyClass(targetClass)) {
					advised.setInterfaces(targetClass.getInterfaces());
				}
				specifiedInterfaces = advised.getProxiedInterfaces();
			}
		}
                // 判断是否加入这几个接口
		boolean addSpringProxy = !advised.isInterfaceProxied(SpringProxy.class);
		boolean addAdvised = !advised.isOpaque() && !advised.isInterfaceProxied(Advised.class);
		boolean addDecoratingProxy = (decoratingProxy && !advised.isInterfaceProxied(DecoratingProxy.class));
		int nonUserIfcCount = 0;
		if (addSpringProxy) {
			nonUserIfcCount++;
		}
		if (addAdvised) {
			nonUserIfcCount++;
		}
		if (addDecoratingProxy) {
			nonUserIfcCount++;
		}
		Class<?>[] proxiedInterfaces = new Class<?>[specifiedInterfaces.length + nonUserIfcCount];
		System.arraycopy(specifiedInterfaces, 0, proxiedInterfaces, 0, specifiedInterfaces.length);
		int index = specifiedInterfaces.length;
		if (addSpringProxy) {
			proxiedInterfaces[index] = SpringProxy.class;
			index++;
		}
		if (addAdvised) {
			proxiedInterfaces[index] = Advised.class;
			index++;
		}
		if (addDecoratingProxy) {
			proxiedInterfaces[index] = DecoratingProxy.class;
		}
		return proxiedInterfaces;
	}

findDefinedEqualsAndHashCodeMethods(proxiedInterfaces)比较简单,这里不贴代码了。

Proxy.newProxyInstance(),这里把代码贴出来,但是不做分析,详细原理看老生常谈系列之Aop--JDK动态代理的底层实现原理

    @CallerSensitive
    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
    {
        Objects.requireNonNull(h);

        final Class<?>[] intfs = interfaces.clone();
        final SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
        }

        /*
         * Look up or generate the designated proxy class.
         */
        Class<?> cl = getProxyClass0(loader, intfs);

        /*
         * Invoke its constructor with the designated invocation handler.
         */
        try {
            if (sm != null) {
                checkNewProxyPermission(Reflection.getCallerClass(), cl);
            }

            final Constructor<?> cons = cl.getConstructor(constructorParams);
            final InvocationHandler ih = h;
            if (!Modifier.isPublic(cl.getModifiers())) {
                AccessController.doPrivileged(new PrivilegedAction<Void>() {
                    public Void run() {
                        cons.setAccessible(true);
                        return null;
                    }
                });
            }
            return cons.newInstance(new Object[]{h});
        } catch (IllegalAccessException|InstantiationException e) {
            throw new InternalError(e.toString(), e);
        } catch (InvocationTargetException e) {
            Throwable t = e.getCause();
            if (t instanceof RuntimeException) {
                throw (RuntimeException) t;
            } else {
                throw new InternalError(t.toString(), t);
            }
        } catch (NoSuchMethodException e) {
            throw new InternalError(e.toString(), e);
        }
    }

CglibAopProxy实现

直接来看getProxy()方法,会比JDK动态代理的复杂一奈奈。

	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;
                        // 先获取rootClass,如果rootClass的name包含$$,继续获取它的父类,随后获取rootClass父类的接口,加入advised
			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.
                        // 校验class
			validateClassIfNecessary(proxySuperClass, classLoader);

			// Configure CGLIB Enhancer...
                        // 使用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[] 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
                        // 重点关注:设置CallbackFilter
			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);
		}
		// 省略异常捕获
	}

我们看重点方法,主要有getCallbacks()createProxyClassAndInstance(enhancer, callbacks)

来看一下getCallbacks()代码,方法虽长,但是很常规。就是获取主要的Callback,然后根据isStaticisFrozen进行优化,优化的方法很简单,就是获取rootClass的所有方法rootClass.getMethods(),然后加入到最后要返回的callbacks里。

	private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
		// Parameters used for optimization choices...
		// 对于 expose-proxy 属性的处理
		boolean exposeProxy = this.advised.isExposeProxy();
		boolean isFrozen = this.advised.isFrozen();
		boolean isStatic = this.advised.getTargetSource().isStatic();

                // 这一部分为获取Callback
		// Choose an "aop" interceptor (used for AOP calls).
		// 将拦截器封装在 DynamicAdvisedInterceptor中
		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[] {
				// 将拦截器链加入 Callback中
				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;
	}

获取了Callbacks,接下来就是调用createProxyClassAndInstance(enhancer, callbacks)生成代理了。

	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.create()生成一个动态代理,这一块讲得比较简单,Spring Aop对Enhancer的配置基本被略过,Enhancer的原理如同JDK动态代理的原理一样,也都略过。主要是限于篇幅,再写下去就会非常冗长。具体原理可以看补充文章老生常谈系列之Aop--CGLIB动态代理的底层实现原理

拦截器的执行顺序

切面增强方法获取到了,代理也生成了,那么在执行的时候,是怎么保证顺序的呢?@Before如何保证在@After前执行,从始至终我们看到,Spring Aop没有对切面进行任何的分类或许排序去保证执行顺序,那么这个顺序怎么保证呢?

其实这个由拦截器本身的实现来完成了。在方法执行的时候,如果有多个切面方法,那么这些会被组装成一个拦截链去执行。看到这里是不是更迷惑了,一个拦截链,又没有顺序,执行过去不就全乱了吗?其实不是的,我们来看一下代码的实现,这里摘取MethodBeforeAdviceInterceptorAspectJAfterAdviceinvoke()方法实现就一目了然了。

MethodBeforeAdviceInterceptor#invoke()代码

	@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
                // 先执行切面增强方法
		this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
                // 再执行下一个
		return mi.proceed();
	}

AspectJAfterAdvice#invoke()代码

	@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
		try {
                        // 直接执行下一个,处理完成返回后再执行切面增强方法
			return mi.proceed();
		}
		finally {
                        // 后执行切面增强方法
			invokeAdviceMethod(getJoinPointMatch(), null, null);
		}
	}

看到这里应该已经明白为啥顺序能保证了,Spring Aop这里是比较巧妙地利用了方法的执行位置来完成这个顺序的保证,简单明了,还不需要对增强方法进行排序分类执行。

总结

这一篇主要分析了Spring Aop生成动态代理的准备工作,以及JDK动态代理和CGLIB动态代理的过程。当然这里只是简单的跟着注释走马观花看了一下Spring Aop生成动态代理的逻辑,还是比较简单的。至此,Spring Aop部分的逻辑已经走完,接下来的原理就是JDK动态代理和CGLIB动态代理的生成原理。这一部分涉及的就是JVM的反射和字节码修改等操作,欲知后事如何,且听下回分解。

如果有人看到这里,那在这里老话重提。与君共勉,路漫漫其修远兮,吾将上下而求索。

posted @ 2022-01-10 21:37  Codegitz  阅读(148)  评论(0编辑  收藏  举报