Spring AOP的实现:建立AopProxy代理对象
前面我们讲述了AOP的基本知识以及在Spring AOP机制中的一些基本的数据结构及其功能。下面开始正式的讲述Spring AOP的实现部分。
来看一下这个以ProxyFactory为中心的继承关系图
可以将ProxyConfig看做是一个数据基类,这个基类为ProxyFactoryBean这样的子类提供了属性的配置。而AdvisedSupport则是实现了对于通知器和通知的相关操作。
在分析Spring AOP的实现原理中。原书是以ProxyFactoryBean的实现作为例子的。通过这个工程Bean,生产出了我们需要的AopProxy代理对象。
那么书上首先给了我们这样的关于ProxyFactoryBean的配置方法。
我们可以看到,我们需要给我们的ProxyFactoryBean配置一个通知器,这个通知器是它的interceptorNames属性。当然还需要配置proxyInterfaces,这个是目标接口,也就是被代理的接口。target ,目标对象。
值得注意一点,虽然这里声明了interceptorNames属性,但是这个不是之后我会提到的拦截器。这个属性声明的是供AOP应用配置通知器的地方,需要为target目标对象生成Proxy代理对象,从而为AOP横切面的编织做好准备工作。
在ProxyFactoryBean中,它的AOP实现需要依赖JDK或者CGLIB提供的Proxy特性(也就是我前面所说的代理模式)。从FactoryBean中获取对象,是使用getObject()方法来完成的
@Override
public Object getObject() throws BeansException {
initializeAdvisorChain();
if (isSingleton()) {
return getSingletonInstance();
}
else {
if (this.targetName == null) {
logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +
"Enable prototype proxies by setting the 'targetName' property.");
}
return newPrototypeInstance();
}
}
首先要对通知器链进行初始化操作,通知器链封装了一系列的拦截器,这些拦截器都要从配置中读取,然后为代理对象的生成做好准备。Spring中有singleton和prototype类型这两种不同的bean,所以这里对代理对象的生成需要做一个区分。
现在来看一下initializeAdvisorChain();这个方法,它为Proxy代理对象配置Advistor链是在这个方法中完成的。从代码中我们可以看到,从ListableBeanFactory中取得相应的通知器并把这些通知器加入到通知器链中。
生成singleton代理对象是在getSingletonInstance()中实现的。
private synchronized Object getSingletonInstance() {
if (this.singletonInstance == null) {
this.targetSource = freshTargetSource();
if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
// Rely on AOP infrastructure to tell us what interfaces to proxy.
Class<?> targetClass = getTargetClass();
if (targetClass == null) {
throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
}
setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
}
// Initialize the shared singleton instance.
super.setFrozen(this.freezeProxy);
this.singletonInstance = getProxy(createAopProxy());
}
return this.singletonInstance;
}
首先需要设置代理对象的接口
setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
之后我们会使用ProxyFactory来生成我们需要的Proxy。
this.singletonInstance = getProxy(createAopProxy());
protected Object getProxy(AopProxy aopProxy) {
return aopProxy.getProxy(this.proxyClassLoader);
}
这里使用的时候AopProxy的getProxy()方法生成代理对象。AopProxy的获得方法是由
org.springframework.aop.framework.ProxyCreatorSupport.createAopProxy()
实现的
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
在DefaultAopProxyFactory中创建AopProxy
@Override
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.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
接下里具体的代理对象的生成可以由两种方式。AOP代理对象的生成,是根据我们的目标对象的类型。如果是接口类,那么就使用JDK来生成代理对象,否则Spring使用CGLIB来生成目标对象的代理对象。当返回的是JDKDynamicAopProxy对象时。它的getProxy()方法如下所示
@Override
public Object getProxy(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);
}
在这个地方我们看到了
Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
这就是我之前的一篇博客https://blog.****.net/qq1641530151/article/details/83036756
中提到的动态链接。这里我们也可以看到,spring的底层实际上也调用了jdk的代理模式。
这个地方为我们返回了目标对象的代理对象。
关于CGLIB对于代理对象的生成方式,是类似的。书上也有相应的代码。
下次我将来讲述关于Spring AOP的拦截器的调用。