スプリングソースコード解析(D)(AOPの実現)(1)

著作権:著作権:この記事はブロガーオリジナル記事ですが、許可ブロガーなく再生してはなりません。https://blog.csdn.net/qq_37598011/article/details/89971937

    春AOPの実装では、コア技術は、動的プロキシの使用です。あなたは、動的プロキシ機能を使用して、任意のJavaオブジェクトへのプロキシオブジェクトを作成することができます。春では、特定のJDK CGLIBエージェントとエージェントに分けることができます。

    春AOPに、このクラスはコアクラスProxyFactoryBeanは、このクラスは、春IocをAOP環境は、春が使用AOPのこのクラスを介してパッケージを完成基礎となるアプリケーションの方法で作成され、そこにあります。

AopProxyプロキシオブジェクトを確立します

    ProxyFactoryBeanでは、設定された属性はinterceptorNames通知アドバイザによって定義されています。ProxyFactoryBeanには、ターゲットとするユーザーのためのプロキシのプロキシオブジェクトを生成するので、AOP織りの断面のための準備作業を行う必要があります。
    またはProxyFactoryBean AOPの実装が提供するJDK CGLIBにプロキシに依存します。FactoryBeanのからオブジェクトを取得し、完成したエントリなどのgetObject()メソッドです。当該ProxyFactoryBean、ターゲットオーディエンス強調処理は、getObjectスルー()メソッドは、カプセル化大きくする必要のために、これらの拡張機能は、AOPの機能を実現するための処理サービスを提供します。次のようにのgetObject()を達成:

	public Object getObject() throws BeansException {
		//初始化通知器链
		initializeAdvisorChain();
		//对singleton和prototype类型做区分,生成对应的proxy
		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();
		}
	}

    通知を初期化する第1のチェーンののgetObject()メソッドは、通知パッケージ鎖インターセプターのシリーズは、インターセプタは、構成から読み出され、その後、プロキシオブジェクトを生成する準備ができなければなりません。シングルトンスプリングタイプとプロトタイプは豆の二つの異なるタイプがあるので、それほど区別をするためにプロキシオブジェクトを生成するために、プロキシオブジェクトを生成するとき。

	private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
		//判断是否是第一次
		if (this.advisorChainInitialized) {
			return;
		}

		if (!ObjectUtils.isEmpty(this.interceptorNames)) {
			if (this.beanFactory == null) {
				throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
						"- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));
			}

			// Globals can't be last unless we specified a targetSource using the property...
			if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) &&
					this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {
				throw new AopConfigException("Target required after globals");
			}

			// 添加Advisor链的调用,通过interceptorNames属性进行配置的
			for (String name : this.interceptorNames) {
				if (logger.isTraceEnabled()) {
					logger.trace("Configuring advisor or advice '" + name + "'");
				}

				if (name.endsWith(GLOBAL_SUFFIX)) {
					if (!(this.beanFactory instanceof ListableBeanFactory)) {
						throw new AopConfigException(
								"Can only use global advisors or interceptors with a ListableBeanFactory");
					}
					addGlobalAdvisor((ListableBeanFactory) this.beanFactory,
							name.substring(0, name.length() - GLOBAL_SUFFIX.length()));
				}

				else {
					// If we get here, we need to add a named interceptor.
					// We must check if it's a singleton or prototype.
					//如果程序在这里被调用,那么需要加入命名的拦截器advice,并检查这个bean是singleton还是prototype类型
					Object advice;
					if (this.singleton || this.beanFactory.isSingleton(name)) {
						// Add the real Advisor/Advice to the chain.
						advice = this.beanFactory.getBean(name);
					}
					else {
						// It's a prototype Advice or Advisor: replace with a prototype.
						// Avoid unnecessary creation of prototype bean just for advisor chain initialization.
						advice = new PrototypePlaceholderAdvisor(name);
					}
					addAdvisorOnChainCreation(advice, name);
				}
			}
		}

		this.advisorChainInitialized = true;
	}

    プロキシ構成アドバイザチェーンinitializeAdvisorchainプロキシオブジェクトがプロセスで行われ、初期化プロセスは、通知チェーンを初期化するかどうかを示すフラグadvisorChainInitialized、このフラグを持っています。あなたは既に初期化されている場合は、それが初期化されませんが、直接戻りました。換言すれば、この初期化作業はProxyFactoryBean時間によってプロキシオブジェクトを取得する初めてのアプリケーションで発生しました。初期化が完了した後、そしてその後、これはIoCコンテナの実装のためのコールバックによって行われ、このプロセスがそれにコンテナに通知する通知の名前getBeanメソッドを取得することです内のすべての通知の設定が表示されます読み込み完了します。その後のIoCが通知チェーンを通知添加容器から取り出され、これが実現するaddAdvisorOnChainCreation()メソッドです。

    OK〜さんは、彼が特定のプロキシオブジェクトを取得する方法を見てみましょう。 

    戻る一つのケースの場合で彼を見るためのgetObject()メソッドを実行する方法で、この方法では、コードgetSingletonInstanceを()完了するために、シングルトンプロキシオブジェクトを生成することAopProxy ProxyFactoryBeanプロキシオブジェクトのコールエントリを生成することです。プロキシオブジェクトは、ターゲットとするユーザーへの呼び出しをカプセル化する対象オブジェクトの振る舞いは、ここで生成されたプロキシオブジェクトを傍受されるため、そのメソッドを呼び出します。具体的な生成処理は、まず、ProxyFactoryBean構成を読み取るようなプロキシメソッド呼び出しインタフェースの設定などプロキシオブジェクトを生成するために必要な準備を行うことです。詳細な春AopProxyは、プロキシオブジェクトクラスを生成しました。
 

	private synchronized Object getSingletonInstance() {
		if (this.singletonInstance == null) {
			this.targetSource = freshTargetSource();
			if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
				//根据AOP框架来判断需要代理的接口
				// 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);
			//这里通过ProxyFactory来生成需要的Proxy
			this.singletonInstance = getProxy(createAopProxy());
		}
		return this.singletonInstance;
	}



    //通过AopProxy 返回来获取代理对象
	protected Object getProxy(AopProxy aopProxy) {
		return aopProxy.getProxy(this.proxyClassLoader);
	}


	protected final synchronized AopProxy createAopProxy() {
		if (!this.active) {
			activate();
		}
		//通过AopProxyFactory获取AopProxy,这个AopProxyFactory是在初始化中定义
		//使用的是DefaultAopProxyFactory
		return getAopProxyFactory().createAopProxy(this);
	}


	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.");
			}
			//如果targetClass是接口类,使用JDK来生成Proxy
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
				return new JdkDynamicAopProxy(config);
			}
			//不是接口类,通过CGLIB生成
			return new ObjenesisCglibAopProxy(config);
		}
		else {
			return new JdkDynamicAopProxy(config);
		}
	}


    JdkDynamicAopProxyとObjenesisCglibAopProxy:2つの特定の実装を有しAopProxyインターフェイスクラスによって分離されたプロキシオブジェクトで達成するスプリングフレームワークAOP。これら2つのサブクラスはCGLIBプロキシプロキシオブジェクトであり、所望のJDKを生成します。

    またはJDKによって生成CGLIBするAopProxyFactoryによって生成された特定のプロキシオブジェクト。AopProxyは、ターゲットオブジェクトがそれ以外の場合は、ターゲット・オブジェクトを生成するために、春CGLIBプロキシオブジェクトを使用しますが、プロキシオブジェクトを生成するために使用JDKに適した、インタフェースクラスである場合は、使用を生成するためにどの方法を検討する必要があり、プロキシオブジェクトを生成しました。生成された別のプロキシオブジェクト,, AopProxyオブジェクトとしてDefaultAopProxyFactory製造工場の要件を満たすために、オブジェクトがAopProxy両方の異なるニーズに応じて生成されてもよいです。


AopProxy生成されたJDKプロキシオブジェクト

    ここでは、AopProxyはJDK JdkDynamicAopProxyとCGLIBベースObjenesisCglibAopProxyに基づいて、それぞれ、2に実装され見ることができます。

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

    プロキシオブジェクトを生成するために使用JdkDynamicAopProxy JDKプロキシクラスは、プロキシオブジェクトを生成する前に、オブジェクトからオブジェクトを助言配置された第一のプロキシインターフェイスエージェントを取得する必要があり、その後newProxylnstanceプロキシメソッド、オブジェクトに対応する最終的に得られたプロキシエージェントを呼び出します。プロキシオブジェクトを生成するとき、三つのパラメータ、クラスローダを指定する必要があり、プロキシ・インターフェースであり、他の一つはオブジェクトであるプロキシコールバックメソッドであり、オブジェクトはのInvocationHandlerインタフェースを実現する必要があります。これのInvocationHandlerインタフェースは、コールバック入口プロキシオブジェクトを提供し、invokeメソッドを定義します。自体は()メソッドを呼び出すのInvocationHandlerインタフェースを実装し、JdkDynamicProxyについては、呼び出し()メソッドがコールバックメソッドプロキシプロキシオブジェクトがある、あなたはJdkDynamicAopproxyオブジェクト自体、プロキシエージェントであるプロキシオブジェクトに割り当てられJdkDynamicAopProxyを置くためにこれを使用することができますインターフェイスメソッドが呼び出されたとき、それはコールバックのinvoke()メソッドをトリガーする、コールバックメソッドは、パッケージAOP織りが達成完了します。
 

AopProxy生成されたCGLIBプロキシオブジェクト

    AopProxyインターフェースにCGLIBプロキシプロキシオブジェクトを生成するために使用見ることができ、プロキシオブジェクトプロキシ生成は同じAopProxy getProxyインターフェースの実装で行われる、ObjenesisCglibAopProxyためのコードで見ることができます。ObjenesisCglibAopProxyはコンストラクタ関数によってサポートなしでオブジェクトをインスタンス化するcreateProxyClassAndInstance()メソッドを書き換えるCglibAopProxyを継承しました。

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

    AOPの実現を補助二部のインフラストラクチャおよび動作を調製すると見なすことができるためAOPは、ここでAopProxyプロキシオブジェクトが構築された静的プロセスAOPインフラとして見ることができる生成します。この準備プロセスを通じて、これらの呼び出しは、プロキシオブジェクトの一部であることを、インターセプタは、これらのインフラストラクチャの操作で使用されるAOPプロセスを待って、準備ができています。

おすすめ

転載: blog.csdn.net/qq_37598011/article/details/89971937