Spring中AOP的实现
原始工具ProxyFactory
上回说到ProxyFactory,并未说明内部如何实现的,本文就来揭秘一下是如何实现的。
在看ProxyFactory之前先看看下它的继承关系。
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
老样子先奉上类图
这个类图是不是很熟悉,在最开始已经看过了。现在来详细说说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这个方法有啥用?