Spring AOP框架学习笔记(1):AOP代理对象的建立

Aop的几个概念:

1.Advice(通知)定义在连接点做什么,为切面增强提供织入接口。在Spring AOP中,主要描述Spring AOP围绕方法调用而注入的切面行为。下图是Advice的类层次图。

 

2.Pointcut(切点)决定Advice通知应该作用于哪个连接点,也就是说通过Pointcut来定义需要增强方法的集合。

 

3.Advisor(通知器)用来完成对目标方法的切面增强设计(Advice)和关注点设计(Pointcut)的结合。

 

4.Joinpoint(连接点)程序执行过程中明确的点,如方法的调用或特定的异常被抛出。

 

 

首先明确一点,SpringBeanFactoryFactoryBean的区别,BeanFactory是类工厂,主要方法是getBean(String beanName),而对于FactoryBean而言,用户可以通过该接口的getObject方法定制实例化Bean的逻辑。

AopProxy代理对象的建立

SpringAOP模块中,一个主要的部分就是代理对象的生成,而对于Spring应用,可以看到,是通过配置和调用SpringProxyFactoryBean来完成这个任务的。在ProxyFactoryBean中封装了主要代理对象的生成过程。在这个生成过程中,可以使用JDKProxyCGLIB两种生成方式。

首先关注一下ProxyFactoryBean的类继承图


ProxyConfig提供了在创建代理过程中需要用到的配置属性。

AdvisedSupport封装了AOP对通知和通知器的相关操作,这些操作对于不同的AOP的代理对象都是一样的,但对于具体的AOP代理对象的建立,AdvisedSupport把它交给具体的子类去完成。

ProxyCreatorSupport是代理工厂的基类,具体的AOP代理对象的生成,根据需要分别由ProxyFactoryBeanAspectJProxyFactoryProxyFactory来完成。

 

下面分析一下ProxyFactoryBean是如何生成AopProxy代理对象的。下图是生成AopProxy的大概的顺序图。


首先配置ProxyFactroyBean,如下


从以上配置可以看出,ProxyFactoryBean类有两个重要的成员变量,targetinterceptorNames。其中target正是需要进行AOP代理的对象,而interceptorNames则定义好了通知器Advisor

FactoryBean获取对象,是以getObject()方法作为入口完成的,对ProxyFactoryBean来说,需要把target目标对象增加的增强处理,都通过getObject方法进行封装。如下代码所示,getObject方法首先对通知器链进行初始化,通知器链封装了一系列的拦截器,这些拦截器都要从配置中读取,然后为代理对象的生成做好准备。

public Object getObject() throws BeansException {
		initializeAdvisorChain();//初始化Advisor链,在后续的文章中,我们将会来详细介绍通知器的配置
		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();
		}
	}
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;
	}

protected Object getProxy(AopProxy aopProxy) {
		return aopProxy.getProxy(this.proxyClassLoader);
	}


 

这里出现了AopProxy类型的对象,Spring利用这个AopProxy接口类把Aop代理对象的实现与框架的其他部分有效地分离开来。AopProxy接口有两个子类实现,一个是Cglib2AopProxy,另一个是JdkDynamicProxy

ProxyCreatorSupport中可以看到,具体的AopProxy是通过AopProxyFactory来生成的。生成代理对象需要的所有信息都封装在AdvisedSupport,这个对象是生成AopProxy的输入参数。

	protected final synchronized AopProxy createAopProxy() {
		if (!this.active) {
			activate();//用于激活AdivisedSupportListener
		}
		return getAopProxyFactory().createAopProxy(this);
	}

这里AopProxyFactory使用的是DefaultAopProxyFactory,它是在ProxyCreatorSupport中被创建的。于是问题就转换为在DefaultAopProxyFactory中,AopProxy是怎样生成的了。

	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()) {
				<strong>return new JdkDynamicAopProxy(config);</strong>
			}
			if (!cglibAvailable) {
				throw new AopConfigException(
						"Cannot proxy target class because CGLIB2 is not available. " +
						"Add CGLIB to the class path or specify proxy interfaces.");
			}
			<strong>return CglibProxyFactory.createCglibProxy(config);</strong>
		}
		else {
			return new JdkDynamicAopProxy(config);
		}
	}

从这段代码可以看出,对于具体的AopProxy对象的生成,最终并没有由DefaultAopProxyFactory来完成,而是由JdkDynamicAopProxyCglibProxyFactory来完成的。

JdkDynamicAopProxy中,使用JDKProxy类来生成代理对象,首先需要从advised对象中取得代理对象的代理接口配置,然后调用ProxynewProxyInstance方法,最终得到对应的Proxy代理对象。

	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);
		findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
		return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
	}

CGLIB生成AopProxy代理对象的过程,这里就不进行分析了,有兴趣的读者可以查看Spring的相关源代码。








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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值