春AOPコアソースProxyFactory

春AOPのソースディレクトリ

春AOP出典01:基本となるソースのJDKの動的プロキシ
春AOP出典02:ProxyFactory
春AOP出典03:JdkDynamicAopProxy
春AOP出典04:インターセプターMethodInvocationコール
春AOP出典05:DefaultAdvisorAutoProxyCreator
春の最終試験の質問フィナーレ:春AOPは、循環依存に会ったとき
ノートgitのソースアドレスします。https://github.com/chaitou/spring-framework-master.git

序文

取引はの分析に焦点を当てるこの記事ProxyFactoryクラスのソースコードを使用すると、エネルギーの大部分を説明したい理由は、多くの人が理解していないが費やされているProxyFactory上、すべての後、誰もが、このような低レベルのSpring AOPの実装を使用しないのでしょうか?

達成するために手動で設定プロキシへProxyFactory必要性Traget(対象物)、 Interfaceインターフェース)、 Advice拡張)、次いでコールはgetProxy、プロキシオブジェクトを生成します。春AOPの形での注釈の使用は、複合体を想像していなかったが、すべてを探している@Aspect注釈付きクラスとのすべて@Beforeおよびその他の機能強化、そしてを通じて@Pointcut試合の整合条件、そして最終的に全てのマッチングを取得Advice(強化)プロキシを生成しました。そのため、コメントフォームのAOP難解ではない、ただ自動的に私たちを支援する寻找匹配增强と春Iocの中を探しているのプロセスビーンを作成する合适的时机より、コールgetProxy発生剤、何を。だから、(私たちは手動でハードコードされた場合ProxyFactory)、徹底的に、そして基本的にも習得春AOPは、ノートの形にとして、我々はちょうど約探求する必要がありAdvice、それを取得し、一致する方法

ノート破断XML構成、スプリングAOPをするコアProxyFactoryより良好な把握するために、ソースコードのコンテキストをメインラインをつかむ、コーナーの詳細によって乱されることはありません

ProxyFactory

サンプルコード

我々は書き込むUserService定義することインターフェースfindUser方法が有する前に使用した後ながらAdvice強化(拡張)、最後に使用する方法をProxyFactoryプロキシを生成したが。

ここでは、広く長いようなアドバイス(拡張)とアドバイザ(セクション)、二つの単語ビットを導入することが必要であるが、彼らは集約関係です。

  • 強化された(Advice):共通Before adviceAfter returning advice接続点での事業を拡大することですが
  • カットポイント(Pointcut):すなわち、接続点、現在のメソッドまたはクラスを高めるかどうかを決定するため
  • セクションは、( Advisor):で見ることができる增强切点結合します。強化する方法のニーズを想定し、すべての通話を切断Pointcut適用は、現在呼び出された場合、現在のセクションでは、適用されるかどうかを判断するためのAdvice強化

インタフェース:

public interface UserService {
	public void findUser();
}

クラスの実装:

public class UserServiceImpl implements UserService {
	@Override
	public void findUser() {
		System.out.println("findUser...");
	}
}

2つの機能強化:

// 前置增强
public class LogBeforeAdvice implements MethodBeforeAdvice {
	@Override
	public void before(Method method, Object[] args, Object target) throws Throwable {
		System.out.println("before log...");
	}
}

// 后置增强
public class LogAfterAdvice implements AfterReturningAdvice {
	@Override
	public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
		System.out.println("after log...");
	}
}

テスト:

public class UserServiceImplImplTest {
    @Test
    public void findUser() {

		// 1. 创建代理工厂
		ProxyFactory factory = new ProxyFactory();
		// 2. 设置代理目标对象
		factory.setTarget(new UserServiceImpl());
		// 3. 设置接口
		factory.setInterfaces(new Class[]{UserService.class});
		// 4. 设置增强
		factory.addAdvice(new LogBeforeAdvice());
		factory.addAdvice(new LogAfterAdvice());
		// 5. 获取代理对象
		UserService userService = (UserService) factory.getProxy();

		userService.findUser();
    }
}

結果:

before log...
findUser...
after log...

Process finished with exit code 0

ProxyFactory継承

ProxyFactory
私たちは、インタフェースを無視して、クラスの焦点を気に

  • ProxyConfig:そのような物質exposeProxyなどにさらされると、アグレッシブモード、最適化、強制的に開かれたCGLIBエージェントproxyTargetClassを使用するかどうかなど、関連インフラを保存するためのプロキシ設定は、のような、XML構成で非常に一般的です<aop:aspectj-autoproxy proxy-target-class="true"/>CGLIBエージェントに強制します
  • AdvisedSupport:AOP構成管理クラス、また保持比較ProxyConfig、targetSourceカットの収集advisors、インターフェースのセットinterfacesなど、
  • ProxyCreatorSupport:設定可能なを提供するエージェントベース・クラスの施設、AopProxyFactoryおよび容易なアクセス

ソースコード解析

  1. デフォルトコンストラクタ直接空気を呼び出し、プロキシファクトリを作成
  2. プロキシターゲットオブジェクトを設定し、targetオブジェクトが内にカプセル化されたTargetSourceオブジェクト、なぜわざわざでしょうか?実際には、TargetSource目的は、各エージェントがプールからオブジェクトを取得すること、利用オブジェクトプーリングとより多くのケースを作ることです。そしてここで我々は唯一の使用SingletonTargetSource上、TargetSource説明するために、休暇バック。ただ、これらの属性がに保存されます言及AdvisedSupport
	public void setTarget(Object target) {
		setTargetSource(new SingletonTargetSource(target));
	}

	@Override
	public void setTargetSource(@Nullable TargetSource targetSource) {
		this.targetSource = (targetSource != null ? targetSource : EMPTY_TARGET_SOURCE);
	}
  1. インターフェースのアレイを設定も記憶されているAdvisedSupportプロパティ
	public void setInterfaces(Class<?>... interfaces) {
		Assert.notNull(interfaces, "Interfaces must not be null");
		// 先清空再添加
		this.interfaces.clear();
		for (Class<?> ifc : interfaces) {
			addInterface(ifc);
		}
	}

	public void addInterface(Class<?> intf) {
		Assert.notNull(intf, "Interface must not be null");
		// 校验如果不是接口则抛出异常
		if (!intf.isInterface()) {
			throw new IllegalArgumentException("[" + intf.getName() + "] is not an interface");
		}
		if (!this.interfaces.contains(intf)) {
			this.interfaces.add(intf);
			adviceChanged();
		}
	}
  1. セットには、Advice我々が言ったように、Advice我々はにパッケージ化する必要がありますので、単に、増加Advisorに追加セクションのコレクション。そして、そこにいずれかの構成に注意を払う必要がないので、私たちは使用されます作成しますAdvisedSupportadvisorsPointcutDefaultPointcutAdvisor
	@Override
	public void addAdvice(Advice advice) throws AopConfigException {
		int pos = this.advisors.size();
		addAdvice(pos, advice);
	}

	@Override
	public void addAdvice(int pos, Advice advice) throws AopConfigException {
		Assert.notNull(advice, "Advice must not be null");
		
		if (advice instanceof IntroductionInfo) {
			// We don't need an IntroductionAdvisor for this kind of introduction:
			// It's fully self-describing.
			// 单独处理引介增强
			addAdvisor(pos, new DefaultIntroductionAdvisor(advice, (IntroductionInfo) advice));
		}
		else if (advice instanceof DynamicIntroductionAdvice) {
			// We need an IntroductionAdvisor for this kind of introduction.
			// DynamicIntroductionAdvice只能作为IntroductionAdvisor的一部分
			throw new AopConfigException("DynamicIntroductionAdvice may only be added as part of IntroductionAdvisor");
		}
		else {
			// 普通增强
			addAdvisor(pos, new DefaultPointcutAdvisor(advice));
		}
	}

そして、DefaultPointcutAdvisor手段方法が一致しているかに関係なく、その、あなたが使用してポイントカットを見ることができるようにPointcut.TRUEする方法の一致に該当するものは何でも

new DefaultPointcutAdvisor(advice)
// Pointcut.TRUE
// 也就是说该Advisor的匹配均为true,匹配任何的方法,不做任何限制!
public DefaultPointcutAdvisor(Advice advice) {
	this(Pointcut.TRUE, advice);
}
  1. エージェントを作成し、これはBenpianのハイライトであります
	public Object getProxy() {
		return createAopProxy().getProxy();
	}

コードcreateAopProxy().getProxy()1、呼び出すgetProxy()前に、我々は、オブジェクトが呼び出されたかを把握しなければならないgetProxy()、つまり、createAopProxy()オブジェクトが作成されたものを最後に

protected final synchronized AopProxy createAopProxy() {
	if (!this.active) {
		activate();
	}
	return getAopProxyFactory().createAopProxy(this);
}
----------------------------------------------------------------
public AopProxyFactory getAopProxyFactory() {
	// 返回的是类中的成员变量aopProxyFactory
	return this.aopProxyFactory;
}
----------------------------------------------------------------
// 成员变量的实例化则是在默认构造器中
private AopProxyFactory aopProxyFactory;

// 构造器,调用了DefaultAopProxyFactory进行实例化,因此aopProxyFactory真正的类型是DefaultAopProxyFactory
public ProxyCreatorSupport() {
	this.aopProxyFactory = new DefaultAopProxyFactory();
}

見つかったトラッキングcreateAopProxy()を返す属性をaopProxyFactory、属性がaopProxyFactory上でProxyCreatorSupportインスタンス化されたクラスが本当で構築するためのDefaultAopProxyFactory、したがって従うことを続ける方法をDefaultAopProxyFactorycreateAopProxy

public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {

	@Override
	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
		// isOptimize开启激进模式 || proxyTargetClass=true(强制开启cglib代理) || 接口集合为空
		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);
			}
			// 没有接口,只能选择cglib代理
			return new ObjenesisCglibAopProxy(config);
		}
		else {
			// 使用JDK代理
			return new JdkDynamicAopProxy(config);
		}
	}
  ...
}

と見ることができるconfig.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)真のみ使用CGLIB剤であり、デフォルトのプロキシがあるCGLIB JDKプロキシ、使用されているに強制プロキシオブジェクトが実装インタフェース、およびないがあるときにJdkDynamicAopProxyクラスが。

言い換えれば、最終呼び出しは、実際にあるnew JdkDynamicAopProxy(config).getProxy()組み合わせ基本となるソースのJDKの動的プロキシコンテンツ、2つの方法が特別な注意が必要ですが期待されます。getProxyそしてinvoke方法

// JdkDynamicAopProxy.java
	@Override
	public Object getProxy(@Nullable ClassLoader classLoader) {
		if (logger.isTraceEnabled()) {
			logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
		}
		// 获取代理接口
		Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
		// 判断接口是否又hashCode和equals方法
		findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
		// 使用JDK代理(classLoader, 接口, 当前JdkDynamicAopProxy对象:用于回调invoke和target对象方法)
		return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
	}
// 上述代码
Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);

// 第一篇[Jdk动态代理底层源码]中学习的代码是一模一样的
return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);

図から分かるように、実際には、各知識点は、一緒に関連付けられているProxyFactory春AOPのコアとして、我々はまた、使用の検討Jdk动态代理達成するために。第一章組み合わせる基本となるソースのJDKの動的プロキシをコンテンツ、それが最も重要であるgetProxyinvoke方法、次のセクションでは、我々は次のようになりますJdkDynamicAopProxygetProxyし、invokeソースコードの解析方法

公開された42元の記事 ウォン称賛43 ビュー40000 +

おすすめ

転載: blog.csdn.net/chaitoudaren/article/details/105277908