春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 advice
、After 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継承
私たちは、インタフェースを無視して、クラスの焦点を気に
ProxyConfig
:そのような物質exposeProxyなどにさらされると、アグレッシブモード、最適化、強制的に開かれたCGLIBエージェントproxyTargetClassを使用するかどうかなど、関連インフラを保存するためのプロキシ設定は、のような、XML構成で非常に一般的です<aop:aspectj-autoproxy proxy-target-class="true"/>
CGLIBエージェントに強制しますAdvisedSupport
:AOP構成管理クラス、また保持比較ProxyConfig、targetSource
カットの収集advisors
、インターフェースのセットinterfaces
など、ProxyCreatorSupport
:設定可能なを提供するエージェントベース・クラスの施設、AopProxyFactory
および容易なアクセス
ソースコード解析
- デフォルトコンストラクタ直接空気を呼び出し、プロキシファクトリを作成
- プロキシターゲットオブジェクトを設定し、
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);
}
- インターフェースのアレイを設定も記憶されている
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();
}
}
- セットには、
Advice
我々が言ったように、Advice
我々はにパッケージ化する必要がありますので、単に、増加Advisor
に追加セクションのコレクション。そして、そこにいずれかの構成に注意を払う必要がないので、私たちは使用されます作成しますAdvisedSupport
advisors
Pointcut
DefaultPointcutAdvisor
@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);
}
- エージェントを作成し、これは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
、したがって従うことを続ける方法をDefaultAopProxyFactory
createAopProxy
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の動的プロキシをコンテンツ、それが最も重要であるgetProxy
とinvoke
方法、次のセクションでは、我々は次のようになりますJdkDynamicAopProxy
にgetProxy
し、invoke
ソースコードの解析方法