Skip to content

Instantly share code, notes, and snippets.

@wreulicke
Last active October 20, 2018 06:42
Show Gist options
  • Select an option

  • Save wreulicke/c7a82747692b5c72683f4762c9bee3ba to your computer and use it in GitHub Desktop.

Select an option

Save wreulicke/c7a82747692b5c72683f4762c9bee3ba to your computer and use it in GitHub Desktop.

メモ

このドキュメントはSpring AOPとaspectjの断面を調べるためのドキュメントです。 Spring BootからSpringのProxy周りについては メモ書きしかないけどこちらをどうぞ

みんなだいすき AspectJAwareAdvisorAutoProxyCreatorから。 一番名前がそれっぽいからそこから見ていく。

AspectJAwareAdvisorAutoProxyCreatorのメソッドで、org.springframework.aop.Advisorのを受け取っているメソッドがあった。

org.springframework.aop.Advisorというクラスがorg.aopalliance.aop.Adviceを返却していた。 AOP AllianceはAOPの実装の標準化のために使われているライブラリだと思っている。

Advice自体がcglibのinterceptorみたいなものになるはず。

今度はProxyの周りを見ていく

AspectJAwareAdvisorAutoProxyCreator の親を辿っていく。 --> AbstractAdvisorAutoProxyCreator --> AbstractAutoProxyCreator

AbstractAutoProxyCreatorにcreateProxyメソッドが存在する。 このメソッドの中で以下のような記述が出てくる

``java ProxyFactory proxyFactory = new ProxyFactory(); ... // 中略 Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); proxyFactory.addAdvisors(advisors);


今度はProxyFactoryのメソッドを見ていく。
getProxyというメソッドがある。

この中ではcreateAopProxyというメソッドを呼んでいる
このメソッドの中では
`getAopProxyFactory().createAopProxy(this)` という記述が出てくる

ちなみに、aopProxyFactoryは単にgetterで、コンストラクタではDefaultAopProxyFactoryが登場している。
このクラスではObjenesisCglibAopProxyとJdkDynamicAopProxyが出てきて
いい感じにProxyを作ってくれるようだ。

戻ってProxyFactoryのgetProxyへ。

次はcreateAopProxyの戻り値のgetProxyメソッドを追っていく。
GglibAopProxyの実装を見る。

getProxyメソッドを見ていく。
この中では以下のような記述が出てくる。

```java
			Callback[] callbacks = getCallbacks(rootClass);

今度はgetCallbacksを見る なんかこの辺でAOPのインターセプターが設定されてそう。

じゃあどこからinterceptorの受け渡しをしているんだろう。 これはAbstractAutoProxyCreatorのcreateProxy経由で ProxyFactoryにaddAdvisorsしている この部分。

ProxyFactoryは ProxyFactory --> ProxyCreatorSupport --> AdvisedSupportの継承関係になっている。

AdvisedSupportはCglibAopProxy.advisedというフィールドの型と一致する。 そういうことなんだろう。 で、終わらすのももったいないので DefaultAopProxyFactoryを見直すとcreateAopProxyメソッドの引数にAdvisedSupportを受けている。

ここまでが、AdviseとCGLIB周りの話。

ここからAspectjの話を見ていく。

雑にaopallianceのInterceptorインターフェースの実装を調べる するとAspectJAfterAdviceとかが出てくる。 とりあえずこれを見て、今度はこのクラスのコンストラクタを呼び出しているところを調べる ReflectiveAspectJAdvisorFactoryというクラスのgetAdviceメソッドにたどりつく。 switch文でアノテーションによって分岐してAOPのAdviceへと変換されている部分が出てきた。

aspectjからAOP Allianceのインターフェースへ変換している部分はこの辺になるらしい。

getAdviceを呼び出す処理を探していこう。 AspectJAwareAdvisorAutoProxyCreatorのshouldSkipから呼ばれている。

以下のようなメソッドになっていた。

	@Override
	protected boolean shouldSkip(Class<?> beanClass, String beanName) {
		// TODO: Consider optimization by caching the list of the aspect names
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
		for (Advisor advisor : candidateAdvisors) {
			if (advisor instanceof AspectJPointcutAdvisor) {
				if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {
					return true;
				}
			}
		}
		return super.shouldSkip(beanClass, beanName);
	}

ここで重要なのはfindCandidateAdvisors()だろう。 メソッドを読んでいく。

以下のような実装になっていた。 AbstractAdvisorAutoProxyCreatorの中にあるようだ。

	protected List<Advisor> findCandidateAdvisors() {
		return this.advisorRetrievalHelper.findAdvisorBeans();
	}

advisorRetrievalHelperはBeanFactoryAdvisorRetrievalHelper型のフィールドらしい。 このクラスのfindAdvisorBeansを読んでみる。 advisorNamesをキャッシュしつつ、AdvisorのBeanを探しているらしい。

それはそれとして普段はaspectjのポイントカットとインターセプターしか書かずにAOPの実現が出来ている。 この辺を変換しているクラスはどこなのか気になってきた。

今度はaspectjのアノテーションの探索とAdvisorへの変換をしているクラスを探していく。

org.aspectj.lang.annotation.Around のアノテーションを使っているところを探していこう。 なにやら、AbstractAspectJAdvisorFactoryのfindAspectJAnnotationOnMethodなどで使っているようだ。 この辺で迷子になった

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment