6.Spring揭秘-原始工具ProxyFactory

6.Spring揭秘-原始工具ProxyFactory

萤火虫 813 2021-10-22

Spring中AOP的实现

原始工具ProxyFactory

上回说到ProxyFactory,并未说明内部如何实现的,本文就来揭秘一下是如何实现的。

在看ProxyFactory之前先看看下它的继承关系。

image-20201213220352928

ProxyCreatorSupport

这个类是一个封装了共性方法的实现的基础类。

比较重要的三点:

  • 内部封装了AdvisedSupportListener集合
  • 内部有一个AopProxyFactory引用,默认是DefaultAopProxyFactory实现类
  • 继承了AdvisedSupport
public class ProxyCreatorSupport extends AdvisedSupport {

  //持有AopProxyFactory的引用
	private AopProxyFactory aopProxyFactory;

  //一个AdvisedSupportListener的集合
	private final List<AdvisedSupportListener> listeners = new LinkedList<>();

  ... ...
	public ProxyCreatorSupport() {
		this.aopProxyFactory = new DefaultAopProxyFactory();
	}

	
	public AopProxyFactory getAopProxyFactory() {
		return this.aopProxyFactory;
	}

	
	public void addListener(AdvisedSupportListener listener) {
		Assert.notNull(listener, "AdvisedSupportListener must not be null");
		this.listeners.add(listener);
	}

	... ...
  
  //此处加synchronized防止并发情况下出现调用多次activate()方法
  //同时也保证工厂方法创建AopProxy代理时内部共享属性的线程安全性
	protected final synchronized AopProxy createAopProxy() {
		if (!this.active) {
      //在active默认为false,因此首次调用createAopProxy方法必然会调用activate()方法
			activate();
		}
    //调用getAopProxyFactory()方法则是this.aopProxyFactory,传递的参数是自身
		return getAopProxyFactory().createAopProxy(this);
	}

	private void activate() {
    //首次调用后active属性为true防止再次调用
		this.active = true;
		for (AdvisedSupportListener listener : this.listeners) {
			listener.activated(this);
		}
	}

	
	@Override
	protected void adviceChanged() {
    //调用父类的方法实现,其实自身并不想改变逻辑,只是需要通知一下自身的AdvisedSupportListener而已
		super.adviceChanged();
		synchronized (this) {
			if (this.active) {
				for (AdvisedSupportListener listener : this.listeners) {
					listener.adviceChanged(this);
				}
			}
		}
	}

	protected final synchronized boolean isActive() {
		return this.active;
	}

}
  • AdvisedSupportListener用于监听AopProxy第一次创建和AdvisedSupport属性的改变。可以提前看一眼AdvisedSupportListener接口简简单单的两个方法,简单明了。类似bean的生命周期回调,可以在生成AopProxy前通过AdvisedSupport中属性的修改达到定制的目的。
public interface AdvisedSupportListener {
	//首次生产AopProxy
	void activated(AdvisedSupport advised);
	//AdvisedSupport属性改变
	void adviceChanged(AdvisedSupport advised);
}
  • AopProxyFactory则是前文说过的用于生产AopProxy的工厂。而AopProxy则是真正生产代理对象的类。因此在此处createAopProxy方法被调用时可以说,就已经确定了生成的代理是谁,代理类生成过程,使用什么代理方式生成的三个关键因素。

这里为啥敢说创建代理三要素已经确定了呢?

先来看看AopProxyFactory接口

AopProxyFactory

/**
 * 接口实现类是一个工厂,根据AdvisedSupport的配置可以去创建一个AopProxy
 *
 * 代理应该遵守以下规则
 * 代理应该实现配置的所有接口
 * 代理应该实现Advised接口
 * 代理应该实现equals方法来兼容被代理的接口,advice,目标类的比较
 * 如果所有advisors和目标可序列化,则它们应可序列化
 * 如果advisor和target是线程安全的,则它们应该是线程安全的
 *
 * 代理可以允许也可以不允许更改advice
 * 如果配置不允许更改advice(例如,由于配置被frozen(意思是frozen参数为true))
 * 则代理应在尝试更改advice时抛出AopConfigException。
 *
 */
public interface AopProxyFactory {

	//为给定的AOP配置创建一个AopProxy 
	AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException;

}

从接口来看简单的不得了,就一个方法创建createAopProxy,参数是AdvisedSupport。现在往前翻看刚刚说过的ProxyCreatorSupport这个接口中的createAopProxy方法,这个方法里调用了AopProxyFactory的createAopProxy方法参数是自身。

protected final synchronized AopProxy createAopProxy() {
	... ...
	return getAopProxyFactory().createAopProxy(this);
}

为啥参数直接传递自身呢?

很简单因为它继承了AdvisedSupport类。

那就来看看AdvisedSupport是何方神圣?

AdvisedSupport

老样子先奉上类图

image-20201213224306071

这个类图是不是很熟悉,在最开始已经看过了。现在来详细说说ProxyConfig这个类。

这个类内部只有5个boolen值和对应的get/set方法来看看。

//用于创建代理的配置的便利超类,以确保所有代理创建者都具有一致的属性。
public class ProxyConfig implements Serializable {

  //否直接代理目标类,而不是仅代理特定的接口。就是说不光增强接口的方法,还把类内的它方法也增强了。
	//将此设置为“true”,可强制代理TargetSource的Public目标类。
	//如果该目标类是接口,则将为给定接口创建一个JDK代理。
	//如果该目标类是任何其他类,则将为给定类创建CGLIB代理。
	//注意:如果未指定接口(并且未激活接口自动检测),则根据具体代理工厂的配置,也会相应的代理目标类方法。
	private boolean proxyTargetClass = false;

  //设置代理是否应执行积极的优化。 代理之间“积极优化”的确切含义会有所不同,但通常会有一些权衡。
	//例如,优化通常将意味着在创建代理后更改advice不会生效。advice不更改意味着创建出来的代理对象是可以缓存的。
	//因此,默认情况下禁用优化。 
  //如果其他设置的干扰导致无法进行优化,则会忽略优化。
  //例如,如果“ exposeProxy”设置为“ true”,则不会优化。
	private boolean optimize = false;

  //设置是否应防止将此配置创建的代理Advised转换为“Advised查询代理状态”。
	//默认值为“ false”,表示任何AOP代理都可以转换为Advised 。
	//就是说是否容许创建出来的代理类强转为Advised
	boolean opaque = false;

  //设置代理是否应由AOP框架公开为ThreadLocal以便通过AopContext类进行检索。 
  //如果advised对象需要调用另一个advised方法,这将很有用。一个类中有两个被代理方法AB,在方法A中调用直接调用方法B。方法B是否被代理
	//默认值为“ false”,以避免不必要的额外拦截。 这意味着,不能保证AopContext访问将在advised对象的任何方法中都能一致地工作。
	boolean exposeProxy = false;

  //设置是否应冻结此配置。
	//冻结配置后,advice集合将无法更改。 
  //这对于优化很有用,在我们不希望调用者在转换为Advised之后能够操纵配置时有用。
	private boolean frozen = false;

  ... ...
}

为啥要弄出来一个ProxyConfig配置类呢?直接将属性方法到AdvisedSupoort中不也可以嘛?

我这里猜测应该是将控制代理对象生成过程的属性单独提取出来。

Advised

//被代理接口的实现类同时内部保留AOP代理工厂的配置,配置包含Interceptor、advice、Advisors和代理接口
//从Spring获得的任何AOP代理都可以转换为此接口,以允许对其AOP进行操作和获取数据
public interface Advised extends TargetClassAware {

  //1、ProxyConfig的属性
	boolean isFrozen();
	boolean isProxyTargetClass();
  boolean isExposeProxy();
  void setExposeProxy(boolean exposeProxy);
  
  //2、代理的接口
  //返回由AOP代理代理的接口。
  //将不包括目标类,也可以将其作为代理
	Class<?>[] getProxiedInterfaces();
  //确定是否代理给定的接口
	boolean isInterfaceProxied(Class<?> intf);

  //3、TargetSource目标类
	//通过Advised改变TargetSource
	//仅在isFrozen为false时才可以更改
	void setTargetSource(TargetSource targetSource);
  //通过Advised获取TargetSource
	TargetSource getTargetSource();

  //4、预过滤
	//设置此代理配置是否已预先过滤,以使其仅包含适用的advisors对象(与该代理的目标类匹配)。
	//默认值为“ false”。
	//如果已经对advisors进行了预过滤,则将其设置为“ true”,这意味着在为代理调用构建实际的advisors链时可以跳过ClassFilter检查。
  boolean isPreFiltered();
	void setPreFiltered(boolean preFiltered);

  //5、advisor集合,添加的advice也会转换为advisor
	Advisor[] getAdvisors();
  
	void addAdvisor(Advisor advisor) throws AopConfigException;
	void addAdvisor(int pos, Advisor advisor) throws AopConfigException;
	boolean removeAdvisor(Advisor advisor);
	void removeAdvisor(int index) throws AopConfigException;
	int indexOf(Advisor advisor);
	boolean replaceAdvisor(Advisor a, Advisor b) throws AopConfigException;

	void addAdvice(Advice advice) throws AopConfigException;
	void addAdvice(int pos, Advice advice) throws AopConfigException;
	boolean removeAdvice(Advice advice);
	int indexOf(Advice advice);

	//由于toString()通常将委托给目标,因此它返回AOP代理的等效项。
	String toProxyConfigString();

}

如果说ProxyConfig类决定对象创建过程,那么Advised则决定创建的是什么对象,对象的增强有那些。

AdvisedSupport

//AOP代理配置管理器的基类。 这些本身不是AOP代理,但是此类的子类通常是工厂,可以直接从中获取AOP代理实例。
public class AdvisedSupport extends ProxyConfig implements Advised {

	//默认的空实现TargetSource
	public static final TargetSource EMPTY_TARGET_SOURCE = EmptyTargetSource.INSTANCE;
	TargetSource targetSource = EMPTY_TARGET_SOURCE;

	private boolean preFiltered = false;

	//1、一个重量级类,将advisor生成调用链的工厂。
	AdvisorChainFactory advisorChainFactory = new DefaultAdvisorChainFactory();

	//2、缓存代理类中方法的调用链的缓存,将方法包装成MethodCacheKey后成为key
	private transient Map<MethodCacheKey, List<Object>> methodCache;

	//3、需要代理的接口
	private List<Class<?>> interfaces = new ArrayList<>();

	//4、Advisor
	private List<Advisor> advisors = new ArrayList<>();

	//5、Advisor集合,在advisors更改后更新集合
	private Advisor[] advisorArray = new Advisor[0];

	public AdvisedSupport() {
		this.methodCache = new ConcurrentHashMap<>(32);
	}
	public AdvisedSupport(Class<?>... interfaces) {
		this();
		setInterfaces(interfaces);
	}

... ...

	//增加代理接口,内部调用adviceChanged()回调
	public void addInterface(Class<?> intf) {
		Assert.notNull(intf, "Interface must not be null");
		if (!intf.isInterface()) {
			throw new IllegalArgumentException("[" + intf.getName() + "] is not an interface");
		}
		if (!this.interfaces.contains(intf)) {
			this.interfaces.add(intf);
			adviceChanged();
		}
	}
... ...
  //增加Advisor
	@Override
	public void addAdvisor(Advisor advisor) {
		int pos = this.advisors.size();
		addAdvisor(pos, advisor);
	}
... ...
  //增加Advisor,如果是Introduction则直接增加接口
	@Override
	public void addAdvisor(int pos, Advisor advisor) throws AopConfigException {
		if (advisor instanceof IntroductionAdvisor) {
			validateIntroductionAdvisor((IntroductionAdvisor) advisor);
		}
		addAdvisorInternal(pos, advisor);
	}

  //增加Advisor,内部调用adviceChanged()回调
	private void addAdvisorInternal(int pos, Advisor advisor) throws AopConfigException {
		Assert.notNull(advisor, "Advisor must not be null");
		if (isFrozen()) {
			throw new AopConfigException("Cannot add advisor: Configuration is frozen.");
		}
		if (pos > this.advisors.size()) {
			throw new IllegalArgumentException(
					"Illegal position " + pos + " in advisor list with size " + this.advisors.size());
		}
		this.advisors.add(pos, advisor);
		updateAdvisorArray();
		adviceChanged();
	}


  //增加Advice
	@Override
	public void addAdvice(Advice advice) throws AopConfigException {
		int pos = this.advisors.size();
		addAdvice(pos, advice);
	}

	//将Advice包装成Advisor添加到advisor集合中
	@Override
	public void addAdvice(int pos, Advice advice) throws AopConfigException {
		Assert.notNull(advice, "Advice must not be null");
		if (advice instanceof IntroductionInfo) {
			// We don't need an IntroductionAdvisor for this kind of introduction:
			// It's fully self-describing.
			addAdvisor(pos, new DefaultIntroductionAdvisor(advice, (IntroductionInfo) advice));
		}
		else if (advice instanceof DynamicIntroductionAdvice) {
			// We need an IntroductionAdvisor for this kind of introduction.
			throw new AopConfigException("DynamicIntroductionAdvice may only be added as part of IntroductionAdvisor");
		}
		else {
			addAdvisor(pos, new DefaultPointcutAdvisor(advice));
		}
	}


	//6、非常重要的方法,调用AdvisorChainFactory生成方法的代理集合,并且使用了methodCache缓存
	public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
		MethodCacheKey cacheKey = new MethodCacheKey(method);
		List<Object> cached = this.methodCache.get(cacheKey);
		if (cached == null) {
			cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
					this, method, targetClass);
			this.methodCache.put(cacheKey, cached);
		}
		return cached;
	}

	//这就是实现类AdvisedCreatorSupport中adviceChanged调用的super方法
	protected void adviceChanged() {
		this.methodCache.clear();
	}


	//复写了如集合时比较需要的几个方法
	private static final class MethodCacheKey implements Comparable<MethodCacheKey> {

		private final Method method;

		private final int hashCode;

		public MethodCacheKey(Method method) {
			this.method = method;
			this.hashCode = method.hashCode();
		}

		@Override
		public boolean equals(@Nullable Object other) {
			return (this == other || (other instanceof MethodCacheKey &&
					this.method == ((MethodCacheKey) other).method));
		}

		@Override
		public int hashCode() {
			return this.hashCode;
		}

		@Override
		public int compareTo(MethodCacheKey other) {
			int result = this.method.getName().compareTo(other.method.getName());
			if (result == 0) {
				result = this.method.toString().compareTo(other.method.toString());
			}
			return result;
		}
	}

}

AdvisedSupport是一个超级配置类

  • 有ProxyConfig配置,代理生成过程
  • 有Advisor知道,代理类如何增强
  • 有AdvisorChainFactory,有工具将Advisor转换为Intercept集合
  • 有要代理的接口Interface集合,并且作为AopProxyFactory接口的参数,知道使用什么代理方式
  • 有TargetSource,知道被代理的对象

可以说,有了AdvisedSupport类就已经完完全全的知道生成代理类的所有配置了。

但是在此处还有两个疑问?

  • AdvisorChainFactory是如何工作的?
  • getInterceptorsAndDynamicInterceptionAdvice这个方法有啥用?