Spring源码-AOP(八)-创建代理

上一篇结束了增强器的获取,接下来我们看下代理是如何创建的。

Spring源码-AOP(八)-创建代理

通过时序图可以看出该模块主要是由AbstractAutoProxyCreator和ProxyFactory来完成的相应功能,下面进行详细分析

初始化操作

接上一章wrapIfNecessary()方法,我们看下createProxy()这个方法的内部实现

【AbstractAutoProxyCreator】

············

Object proxy = createProxy(
		bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
············
}

接下来我们看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);
	/**
	 *决定对给定的bean是否使用targetClass,而不是他的接口代理
	 *检查proxyTargetClass设置以及presserveTargetClass属性
	 */

	if (!proxyFactory.isProxyTargetClass()) {
		if (shouldProxyTargetClass(beanClass, beanName)) {
			proxyFactory.setProxyTargetClass(true);
		}
		else {
			//添加代理接口
			evaluateProxyInterfaces(beanClass, proxyFactory);
		}
	}

	Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
	for (Advisor advisor : advisors) {
		//添加增强器
		proxyFactory.addAdvisor(advisor);
	}
	//设置要被代理的类
	proxyFactory.setTargetSource(targetSource);
	//定制代理
	customizeProxyFactory(proxyFactory);
	/**
	 * 用来控制代理工厂被配置之后,是否允许修改通知
	 * 缺省值为false()
	 */
	proxyFactory.setFrozen(this.freezeProxy);
	if (advisorsPreFiltered()) {
		proxyFactory.setPreFiltered(true);
	}

	return proxyFactory.getProxy(getProxyClassLoader());
}

对于代理类的创建及处理,spring委托给了ProxyFactory去处理,而在函数中主要是对ProxyFactory的初始化操作,包括如下

  • 1、获取当前类中的属性
  • 2、添加代理接口。
  • 3、封装Advisor并加入到proxyFactory中
  • 4、设置要代理的类
  • 5、当然在Spring中还未子类提供了定制的函数customizeProxyFactory,子类可以在此函数中对proxyFactory的进一步封装。
  • 6、进行获取代理操作

封装逻辑

其中,封装Advisor并加入到ProxyFactory中以及创建代理是两个相对繁琐的过程,可以通过ProxyFactory提供的addAdvisor方法直接将增强器置入代理创建工厂中,但是将拦截器封装为增强器还是需要一定的逻辑的。接下来我们看看buildAdvisors()的具体实现

【AbstractAutoProxyCreator】

 protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
	// Handle prototypes correctly...
	//解析出来所以的interceptorName
	Advisor[] commonInterceptors = resolveInterceptorNames();

	List<Object> allInterceptors = new ArrayList<>();
	if (specificInterceptors != null) {
		//加入拦截器
		allInterceptors.addAll(Arrays.asList(specificInterceptors));
		if (commonInterceptors.length > 0) {
			if (this.applyCommonInterceptorsFirst) {
				allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
			}
			else {
				allInterceptors.addAll(Arrays.asList(commonInterceptors));
			}
		}
	}
	if (logger.isDebugEnabled()) {
		int nrOfCommonInterceptors = commonInterceptors.length;
		int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0);
		logger.debug("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +
				" common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
	}

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

【DefaultAdvisorAdapterRegistry】

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

由于Spring中涉及过多的拦截器、通知器、增强方法等方式来对逻辑进行增强,所以非常有必要统一封装成Advisor来进行代理的创建,完成了增强的封装过程,那么解析最重要的移步就是代理的创建与获取了。

【ProxyFactory】

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

创建代理

【ProxyCreatorSupport】

protected final synchronized AopProxy createAopProxy() {
	if (!this.active) {
		activate();
	}
	//创建代理
	return getAopProxyFactory().createAopProxy(this);
}

该方法封装在AopProxyFactory 接口中,由实现类DefaultAopFactory完成相应实现

Spring源码-AOP(八)-创建代理

【DefaultAopFactory】

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
	//此处判断是JDKProxy的实现还是CGLIB的实现
	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)) {
			return new JdkDynamicAopProxy(config);
		}
		return new ObjenesisCglibAopProxy(config);
	}
	else {
		return new JdkDynamicAopProxy(config);
	}
}

到此已经完成了代理的创建。这里最终的实现是由JDKProxy或者CGLIB代理实现。这里需要注意三个判断条件

  • 1、optimize:用了控制通过CGLIB创建的代理是否使用激进的优化策略。除非完全了解AOP。否则不统计。目前这个属性也仅仅用于CGLIB。
  • 2、proxyTargetClass:这个属性为true时,目标本身被代理而不是目标类的接口,如果这个属性为true,CGLIB代理将被创建,设置方式
  • 3、hasNoUserSuppliedProxyInterfaces:是否存在代理接口。

创建代理的方法

根据之前的分析得知,SpringAop动态生成代理有两种方式:JDK和CGLIB。

  • 1、目标对象实现了接口,默认采用JDK动态代理实现,也可强制使用CGLIB。
  • 2、若没有实现接口,必须采用CGLIB,Spring会自动在JDK动态代理和CGLIB之间转换。而且,jdk动态接口只能对实现了接口类生产代理,而不能针对类。CGLIB是针对类实现代理的,覆盖其中的方法,是继承实现,所以该类或方法最后不要声明诚final。
    这里需要注意:
    AopProxy才是生产代理的主要位置,而前面看到的ProxyFactory在AopProxy代理对象和IOC容器配置之间仅仅是一个桥梁作用。AopProxy代理对象可以由JDK或者CGLIB生产,如下图
    Spring源码-AOP(八)-创建代理

    JDK动态代理

    在JDK代理的使用中,其实现类是JdkDynamicAopProxy,而JdkDynamicAopProxy类最为核心的是InvocationHandler接口。而在JdkDynamicAopProxy的方法中最为重要的有以下三个

  • 构造函数
  • invoke
  • getProxy()

    构造函数

    【JdkDynamicAopProxy】

    public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
    	Assert.notNull(config, "AdvisedSupport must not be null");
    	if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
    		throw new AopConfigException("No advisors and no TargetSource specified");
    	}
    	this.advised = config;
    }
    

源码可以看出构造函数主要用于值的传递

【JdkDynamicAopProxy】

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

该方法主要用于获取生成的代理对象,是必不可少的方法

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
	MethodInvocation invocation;
	Object oldProxy = null;
	boolean setProxyContext = false;

	TargetSource targetSource = this.advised.targetSource;
	Object target = null;

	try {
		//equals方法的处理
		if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
			// The target does not implement the equals(Object) method itself.
			return equals(args[0]);
		}
		//hash方法的处理
		else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
			// The target does not implement the hashCode() method itself.
			return hashCode();
		}
		else if (method.getDeclaringClass() == DecoratingProxy.class) {
			// There is only getDecoratedClass() declared -> dispatch to proxy config.
			return AopProxyUtils.ultimateTargetClass(this.advised);
		}
		else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
				method.getDeclaringClass().isAssignableFrom(Advised.class)) {
			// Service invocations on ProxyConfig with the proxy config...
			return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
		}

		Object retVal;
		/**
		 * 有时候目标对象内部的自我调用将无法实施切面中的增强
		 * 则需要通过属性暴露代理
		 */
		if (this.advised.exposeProxy) {
			// Make invocation available if necessary.
			oldProxy = AopContext.setCurrentProxy(proxy);
			setProxyContext = true;
		}

		// Get as late as possible to minimize the time we "own" the target,
		// in case it comes from a pool.
		target = targetSource.getTarget();
		Class<?> targetClass = (target != null ? target.getClass() : null);

		// Get the interception chain for this method.
		//获取当前方法的拦截器
		List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

		// Check whether we have any advice. If we don't, we can fallback on direct
		// reflective invocation of the target, and avoid creating a MethodInvocation.
		if (chain.isEmpty()) {
			// We can skip creating a MethodInvocation: just invoke the target directly
			// Note that the final invoker must be an InvokerInterceptor so we know it does
			// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
			//如果没有发现任何拦截器那么直接调入切点方法
			Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
			retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
		}
		else {
			// We need to create a method invocation...
			//将拦截器封装在ReflectiveMethodInvocation
			//以便于使用期processd进行链接表拦截器
			invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
			// Proceed to the joinpoint through the interceptor chain.
			//执行拦截器链
			retVal = invocation.proceed();
		}

		// Massage return value if necessary.
		//返回结果
		Class<?> returnType = method.getReturnType();
		if (retVal != null && retVal == target &&
				returnType != Object.class && returnType.isInstance(proxy) &&
				!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
			// Special case: it returned "this" and the return type of the method
			// is type-compatible. Note that we can't help if the target sets
			// a reference to itself in another returned object.
			retVal = proxy;
		}
		else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
			throw new AopInvocationException(
					"Null return value from advice does not match primitive return type for: " + method);
		}
		return retVal;
	}
	finally {
		if (target != null && !targetSource.isStatic()) {
			// Must have come from TargetSource.
			targetSource.releaseTarget(target);
		}
		if (setProxyContext) {
			// Restore old proxy.
			AopContext.setCurrentProxy(oldProxy);
		}
	}
}

上面函数主要工作是创建了一个拦截器链,并使用ReflectiveMethodInvocation类进行了链的封装,而在ReflectiveMethodInvocation类的proceed方法中实现了拦截器的逐一调用,接下来看看proceed方法怎么实现?

【ReflectiveMethodInvocation】

public Object proceed() throws Throwable {
	//	We start with an index of -1 and increment early.
	//执行完所有增强后执行切点方法
	if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
		return invokeJoinpoint();
	}
	//获取下一个要执行的拦截器
	Object interceptorOrInterceptionAdvice =
			this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
	if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
		// Evaluate dynamic method matcher here: static part will already have
		// been evaluated and found to match.
		//动态匹配
		InterceptorAndDynamicMethodMatcher dm =
				(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
		if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
			return dm.interceptor.invoke(this);
		}
		else {
			// Dynamic matching failed.
			// Skip this interceptor and invoke the next in the chain.
			//不匹配则不执行拦截器
			return proceed();
		}
	}
	else {
		// It's an interceptor, so we just invoke it: The pointcut will have
		// been evaluated statically before this object was constructed.
		//将this作为参数传递保证当前实例中调用连的执行
		return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
	}
}

在proceed方法中,ReflectiveMethodInvocation主要职责是维护了一个链接调用的计数器,记录着当前调用链接的位置,以便链可以有序的执行,那么在这个翻翻中并没有之前维护的各种增强的顺序,而是将工作委托给各个增强器,使各个增强器在内部进行逻辑实现

CGLIB代理

字节码生成代理:

CGLIB是一个强大的高性能的代码生成包。SpringAOP中完成CGLIB是通过委托给CglibAopProxy实现的,这个类的入口是getProxy。

public Object getProxy(@Nullable ClassLoader classLoader) {
	if (logger.isDebugEnabled()) {
		logger.debug("Creating CGLIB proxy: target source is " + 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 (ClassUtils.isCglibProxyClass(rootClass)) {
			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 ClassLoaderAwareUndeclaredThrowableStrategy(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
		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 class [" +
				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);
	}
}

CGLIB的实现最重要的就是EnHancer。以上函数完整的阐述了Spring中的Enhancer过程,这块是通过getCallBacks方法设置拦截器链的。接下来我们看看getCallBacks方法。

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).
	//将拦截器封装在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++) {
			List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass);
			fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
					chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
			this.fixedInterceptorMap.put(methods[x].toString(), 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的源码分析完成,下一篇我们会整体梳理下相关流程。


谢谢你请我吃糖果

Spring源码-AOP(八)-创建代理 微信

原文 

http://sunliangliang.com/2017/09/13/Spring源码-AOP-八-创建代理/

PS:如果您想和业内技术大牛交流的话,请加qq群(527933790)或者关注微信公众 号(AskHarries),谢谢!

转载请注明原文出处:Harries Blog™ » Spring源码-AOP(八)-创建代理

赞 (0)

分享到:更多 ()

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址