您的位置:首页 > 编程语言 > Java开发

Spring AOP获取Proxy对象的代码流程

2010-12-10 01:06 309 查看
前面一篇给出了一个模拟springAOP的小例子,大家可以看到大概流程,今天我们从spring源码中分析获取Proxy对象的代码流程



当我们有了advice和pointcut之后,需要一个通知器来通知在哪应用切点以及一些处理动作advice。

我们会通过ProxyFactoryBean来配置我们的代理对象和方面行为,获得代理对象即靠下面的代码

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();
		}
	}




生成单例代理对象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);
//生成我们需要的Proxy
			this.singletonInstance = getProxy(createAopProxy());
		}
		return this.singletonInstance;
	}




我们接着看这个方法createAopProxy

/**
	 * Subclasses should call this to get a new AOP proxy. They should <b>not</b>
	 * create an AOP proxy with <code>this</code> as an argument.
	 */
	protected final synchronized AopProxy createAopProxy() {
		if (!this.active) {
			activate();
		}
		return getAopProxyFactory().createAopProxy(this);
	}


然后进入AopProxy org.springframework.aop.framework.AopProxyFactory.createAopProxy(AdvisedSupport config)

Create an
AopProxy
for the given AOP configuration.



public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
//如果目标类不是接口,进入cglib的方法
		if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
			Class targetClass = config.getTargetClass();
//如果没有cglib的包  抛出异常
			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()) {
				return new JdkDynamicAopProxy(config);
			}
			if (!cglibAvailable) {
				throw new AopConfigException(
						"Cannot proxy target class because CGLIB2 is not available. " +
						"Add CGLIB to the class path or specify proxy interfaces.");
			}
//返回cglib类型的AopProxy
			return CglibProxyFactory.createCglibProxy(config);
		}
		else {
//如果目标类为接口,返回JDK类型的AopProxy
			return new JdkDynamicAopProxy(config);
		}
	}




JDK类型的AopProxy的方法如下

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);
//生成需要的Proxy实例
		return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
	}






下面为cglib类型的AopProxy方法

public static AopProxy createCglibProxy(AdvisedSupport advisedSupport) {
			return new Cglib2AopProxy(advisedSupport);
		}

/**
	 * Create a new Cglib2AopProxy for the given AOP configuration.
	 * @param config the AOP configuration as AdvisedSupport object
	 * @throws AopConfigException if the config is invalid. We try to throw an informative
	 * exception in this case, rather than let a mysterious failure happen later.
	 */
	public Cglib2AopProxy(AdvisedSupport config) throws AopConfigException {
		Assert.notNull(config, "AdvisedSupport must not be null");
		if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
			throw new AopConfigException("No advisors and no TargetSource specified");
		}
		this.advised = config;
		this.advisedDispatcher = new AdvisedDispatcher(this.advised);
	}




这样用Proxy包装target之后,通过ProxyFactoryBean得到对其方法的调用就被Proxy拦截了, ProxyFactoryBean的getObject()方法得到的

实际上是一个Proxy了,我们的target对象已经被封装了。对 ProxyFactoryBean这个工厂bean而言,其生产出来的对象是封装了目标对

象的代理对象。



参考资料:《Spring技术内幕 - 深入解析Spring架构与设计原理》 ,spring源码。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: