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.csdn.net/qq1641530151/article/details/83036756

中提到的动态链接。这里我们也可以看到,spring的底层实际上也调用了jdk的代理模式。

这个地方为我们返回了目标对象的代理对象。

关于CGLIB对于代理对象的生成方式,是类似的。书上也有相应的代码。

下次我将来讲述关于Spring AOP的拦截器的调用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值