Spring AOPソース(下)
38747 ワード
前言
前回はSpringのaop配置の処理について説明しましたが、Springではこれらの構成がどのように使われていますか?今日はSpringがどのようにこれらのものを作用させているかを見ました.
BeanPostProcessor
説明する前に、まずビーンPostProcessorインターフェースを知っておく必要があります.
私たちはAbstractAplication Contectのrefresh方法に戻ります.
私達は続けて見ます.レギターのBeanPostProcessorsがあります.方法
この方法は、すべてのBeanPostProcessorインターフェースを実現するBeanをAbstractBenFactoryのbeanPostProcessors属性に注入することです.これはinvokeBenFactoryPostProcessorsと同じ方法で、BenFactory PostProcessorインターフェースを実現したBeanが対応するリストセットに注入され、postProcession Factoryメソッドを呼び出すという方法の実現はほぼ同じです.ここではもう言わないで、以前のSpring解析属性ファイルのソース解析部分を見てもいいです.
そして、私達は直接に実用化されたbeanのコードセグメントを見ます.refreshではfinish BeanFactoryInitializationです.具体的な実現については、私たちは層を見ていません.直接にAbstractAutowireCable BeanFactory類を見ます.
initializaBen
appyBenPostProcessors BeforeInitializationとappyBenPostProcessors AfterInitialization方法.
同じように、appyBeanPostProcessors AfterInitialization方法であれば、遍歴後にpostProcess After Initializationを呼び出す方法です.
ここまで分析すれば、明らかに私たちはAspect JAwareAdviso AutoProxyCreatorに目を向けることができます.
AsppectJAwareAdvisoorAutoxyCreator
前のページでConfigBenDefinitionParseの方法を説明した時、configreAutoxyCreatorと言いました.という時はともかく、この編はここから入手します.
2.elementノードの関連属性に応じていくつかの属性を設定します.
3.1で得られたビーム定義をSpring容器に登録する.
詳しく話します.
register Aspect JAtoxyCreatorifNecessary
対応するBean定義を取得し、このBean定義のClass NameとAspectJAwareAdvisor AutoProxCreatorを比較し、異なる場合は二つのClass Nameの優先度を比較します.AspectJAwareAdvisoorAutoProxCreatorの優先度が高い場合、現在のBean定義のClass NameをAsppectJAwareAdvisoorAutoxyCreatorに設定します.優先度:
AnnotationAwareAspect JAtoxyCreator>AsppectJAwareAdvisor AutoxyCreator>Infrastructure AdvisoorAutoxyCreator.
2)現在の容器にこのBeanNameが存在しない場合.AspectJAwareAdvisoorAutoxyCreatorを使ってビーン定義を作り、関連属性を登録して、order優先度を最低にするなどします.そして戻ってきます
useClass ProxygingIfNecessary
この方法は実は彼の主な役割は上記のBeanのために二つの属性を登録することです.それぞれプロxyTarget ClassとexposeProxyです.
さて、これまでSpring容器にAspectJAwareAdvisor AutoProxyCreatorからなるBen定義を注入しました.
Aspect JAwareAdvisoorAutoxyCreatorの継承構造を見に来ました.
ソースコードを見ると、AsppectJAwareAdvisoorAutoxyCreatorと彼の祖先類はpostProcess Before Initializationの方法に対して具体的な実現がありません.
この方法の実現は祖先型AbstractAutoxyCreatorにある.
2.Adviice Beanが空でない場合は、動的エージェントクラスを作成し、最後にキャッシュに入れて返します.
getAdvice AndAdvisors ForBen
AbstractAdvisor AutoxyCreator
2)findAdvisors ThaCanplyを呼び出し、すべてのAdvisorで条件に合うAdvisorを見つけます.
canApple
createProxy
get Proxy
私達は先に私達の熟知しているJDKダイナミックエージェントの具体的な実現を見ます.
JdkDynamicAopProxy
これで動的エージェントのインスタンスを作成するプロセスは分析済みです.
しかし、より重要なのは、動的エージェントのインスタンスを呼び出すと、JdkDynamicAopProxyのInvocationHandlerインターフェースの具体的な実装です.
invoke
this.advised.get Interceptors AndynamicInterception Adviceを呼び出します.現在の方法で一致するAdvisor集合を求めます.
Advisor集合が空いていない場合は、実行します.
私たちはReflective MethodInvocationのprocedを重点的に見ます.
だから私たちはこのchainがどんなものなのかを見に来たらいいです.具体的にどのようにしてこのchainを得たのかは詳しく話しません.ソースコード(DefaultAdvisors AdapterRegistryのget Interceptors方法)を見ることができます.chain集合はMethodInterceptorの集合です.
このInterceportの集合は主に以下の種類が含まれています.
AsppectJAfter ThrowingAdviceはaop配置の中/ノード内の方法に対応しています.
AsppectJAfter Advice対応しています\
AsppectJAroundAddvice対応しています\
AfterReturningAdvice InterceptorはAfterReturningAdviceに対応しています\
MethodBefore Advice InterceptorはMethodBefore Adviceに対応しています\
これらのMethodInterceptorが呼び出した順序は、設定ファイルにOrderを指定していない場合、設定ファイルに表示される順序で実行されます.実行する過程は責任連鎖モードの応用で、興味がある学生は先に例のdebugを示して深く研究することができます.
前回はSpringのaop配置の処理について説明しましたが、Springではこれらの構成がどのように使われていますか?今日はSpringがどのようにこれらのものを作用させているかを見ました.
BeanPostProcessor
説明する前に、まずビーンPostProcessorインターフェースを知っておく必要があります.
私たちはAbstractAplication Contectのrefresh方法に戻ります.
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
logger.warn("Exception encountered during context initialization - cancelling refresh attempt", ex);
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
}
}
aopの構成を解析する操作はCofigrable Listable BeanFactory=btainFresh BeanFactory()です.で完成しました私達は続けて見ます.レギターのBeanPostProcessorsがあります.方法
この方法は、すべてのBeanPostProcessorインターフェースを実現するBeanをAbstractBenFactoryのbeanPostProcessors属性に注入することです.これはinvokeBenFactoryPostProcessorsと同じ方法で、BenFactory PostProcessorインターフェースを実現したBeanが対応するリストセットに注入され、postProcession Factoryメソッドを呼び出すという方法の実現はほぼ同じです.ここではもう言わないで、以前のSpring解析属性ファイルのソース解析部分を見てもいいです.
そして、私達は直接に実用化されたbeanのコードセグメントを見ます.refreshではfinish BeanFactoryInitializationです.具体的な実現については、私たちは層を見ていません.直接にAbstractAutowireCable BeanFactory類を見ます.
initializaBen
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction
この方法は私達はもう慣れなくなりました.SpringMVCを説明する時にInitializingBenインターフェースに言及しました.Beanがこのインターフェースを実現すれば、Beanを実際化する時にこの方法の中のinvoke InitMethodsを通じてafterProptiesset()を呼び出します.今日は私達が注目しているBeanPostProcessorインターフェイスの中で、このような対応の方法は明らかです.appyBenPostProcessors BeforeInitializationとappyBenPostProcessors AfterInitialization方法.
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
一目でわかるように、すべてのBenPostProcessor(すでにregister BenPostProcessorsですべての実現クラスの集合を獲得しました)を遍歴して、そして現在のBeanの情報をパラメータとして彼のpostProcess BeforeInitiazation方法を呼び出します.同じように、appyBeanPostProcessors AfterInitialization方法であれば、遍歴後にpostProcess After Initializationを呼び出す方法です.
ここまで分析すれば、明らかに私たちはAspect JAwareAdviso AutoProxyCreatorに目を向けることができます.
AsppectJAwareAdvisoorAutoxyCreator
前のページでConfigBenDefinitionParseの方法を説明した時、configreAutoxyCreatorと言いました.という時はともかく、この編はここから入手します.
private void configureAutoProxyCreator(ParserContext parserContext, Element element) {
AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(parserContext, element);
}
public static void registerAspectJAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
registerComponentIfNecessary(beanDefinition, parserContext);
}
1.AspectJAwareAdvisor AutoxyCreatorのインスタンスを含むBean定義を得る.2.elementノードの関連属性に応じていくつかの属性を設定します.
3.1で得られたビーム定義をSpring容器に登録する.
詳しく話します.
register Aspect JAtoxyCreatorifNecessary
public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
return registerOrEscalateApcAsRequired(AspectJAwareAdvisorAutoProxyCreator.class, registry, source);
}
private static BeanDefinition registerOrEscalateApcAsRequired(Class> cls, BeanDefinitionRegistry registry, Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
1)Spring容器の中ではすでにorg.springframe ebook.aop.com fig.internal AutoxyCreatorとして知られています.対応するBean定義を取得し、このBean定義のClass NameとAspectJAwareAdvisor AutoProxCreatorを比較し、異なる場合は二つのClass Nameの優先度を比較します.AspectJAwareAdvisoorAutoProxCreatorの優先度が高い場合、現在のBean定義のClass NameをAsppectJAwareAdvisoorAutoxyCreatorに設定します.優先度:
AnnotationAwareAspect JAtoxyCreator>AsppectJAwareAdvisor AutoxyCreator>Infrastructure AdvisoorAutoxyCreator.
2)現在の容器にこのBeanNameが存在しない場合.AspectJAwareAdvisoorAutoxyCreatorを使ってビーン定義を作り、関連属性を登録して、order優先度を最低にするなどします.そして戻ってきます
useClass ProxygingIfNecessary
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, Element sourceElement) {
if (sourceElement != null) {
boolean proxyTargetClass = Boolean.valueOf(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
if (proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
boolean exposeProxy = Boolean.valueOf(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
if (exposeProxy) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
おなじみのものを見ましたか?proxy-targt-class属性は私達がaop構成を勉強し始めた時によく言われます.普通はクラスに直接動的を使いたいなら、ノードに属性を配置できます.proxy-target-class=trueで結構です.動的エージェントはcglibを使って完成します.cglibは直接クラスに対して動的代理を実現できます.もし私たちがaopで設定していない場合、またはfalseに設定すると、JDKダイナミックエージェントが使用されます.この場合は、インターフェースに対してのみ動的エージェントが実現されます.この方法は実は彼の主な役割は上記のBeanのために二つの属性を登録することです.それぞれプロxyTarget ClassとexposeProxyです.
さて、これまでSpring容器にAspectJAwareAdvisor AutoProxyCreatorからなるBen定義を注入しました.
Aspect JAwareAdvisoorAutoxyCreatorの継承構造を見に来ました.
public class AspectJAwareAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator {
public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator {
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor {
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
public class ProxyProcessorSupport extends ProxyConfig implements Ordered, BeanClassLoaderAware, AopInfrastructureBean {
彼の祖先類がビーンPostProcessorインターフェースを実現したことを発見しました.ソースコードを見ると、AsppectJAwareAdvisoorAutoxyCreatorと彼の祖先類はpostProcess Before Initializationの方法に対して具体的な実現がありません.
この方法の実現は祖先型AbstractAutoxyCreatorにある.
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
方法のポイントを見ます.wrapIfNecessaryprotected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
1.getAdvice AndAdAdvisors ForBenを通じて、現在のBeanを代理とするAdvice Beanを取得する.2.Adviice Beanが空でない場合は、動的エージェントクラスを作成し、最後にキャッシュに入れて返します.
getAdvice AndAdvisors ForBen
AbstractAdvisor AutoxyCreator
@Override
protected Object[] getAdvicesAndAdvisorsForBean(Class> beanClass, String beanName, TargetSource targetSource) {
List advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
現在のbeanのクラスとbeanNameを利用してマッチングのAdvisorsを見つけます. protected List findEligibleAdvisors(Class> beanClass, String beanName) {
List candidateAdvisors = findCandidateAdvisors();
List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
1)とりあえずすべてのAdvisorを取得する2)findAdvisors ThaCanplyを呼び出し、すべてのAdvisorで条件に合うAdvisorを見つけます.
protected List findAdvisorsThatCanApply(
List candidateAdvisors, Class> beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
public static List findAdvisorsThatCanApply(List candidateAdvisors, Class> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List eligibleAdvisors = new LinkedList();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
私たちは適当なAdvisorを選ぶ主な方法がcanAppleyであることを見ることができます.私たちは主にこの方法を見ます.canApple
public static boolean canApply(Pointcut pc, Class> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
MethodMatcher methodMatcher = pc.getMethodMatcher();
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
Set> classes = new LinkedHashSet>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
classes.add(targetClass);
for (Class> clazz : classes) {
Method[] methods = clazz.getMethods();
for (Method method : methods) {
if ((introductionAwareMethodMatcher != null &&
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
続いて、プロキシオブジェクトの作成を見ます.createProxy
protected Object createProxy(
Class> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
for (Advisor advisor : advisors) {
proxyFactory.addAdvisor(advisor);
}
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(getProxyClassLoader());
}
この方法の大体の意味はProxyFactoryオブジェクトを新規作成し、条件を満たすAdvisor情報をこの対象に注入し、最終的にproxyFactory.get Proxy(get ProxyClass Loader)を呼び出します.を選択します.get Proxy
public Object getProxy(ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
createAopProxy protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
最終的に呼び出したのはDefaultAopProxyFactoryのcreateAopProxy方法です.@Override
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.");
}
if (targetClass.isInterface()) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
方法は分かりやすいです.もしproxy-target-class属性がtrueに指定されていて、しかもインターフェースを動的に代行していない場合、Objnese isCglibAopProxyを呼び出して動的エージェントを完了します.すなわちCGLOIBを使用して動的エージェントを完成します.そうでなければ、JdkDynamicAopProxyを呼び出して動的エージェントを完成します.すなわちJDKダイナミックエージェントを使って実現します.私達は先に私達の熟知しているJDKダイナミックエージェントの具体的な実現を見ます.
JdkDynamicAopProxy
@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);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
get Proxyの方法は簡単で、現在のClass Loaderを使用して、現在のBeanで実現されるすべてのインターフェースをロードし、最後に対応する動的エージェントインスタンスを生成することである.これで動的エージェントのインスタンスを作成するプロセスは分析済みです.
しかし、より重要なのは、動的エージェントのインスタンスを呼び出すと、JdkDynamicAopProxyのInvocationHandlerインターフェースの具体的な実装です.
invoke
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Class> targetClass = null;
Object target = null;
try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
return equals(args[0]);
}
if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
return hashCode();
}
if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// Service invocations on ProxyConfig with the proxy config...
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// May be null. Get as late as possible to minimize the time we "own" the target,
// in case it comes from a pool.
target = targetSource.getTarget();
if (target != null) {
targetClass = target.getClass();
}
// Get the interception chain for this method.
List
私たちは直接的に重点を見て,強化法を実行する必要がない方法に対する処理をスキップした.this.advised.get Interceptors AndynamicInterception Adviceを呼び出します.現在の方法で一致するAdvisor集合を求めます.
Advisor集合が空いていない場合は、実行します.
// We need to create a method invocation...
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
retVal = invocation.proceed();
この二つの行が鍵です.私たちはReflective MethodInvocationのprocedを重点的に見ます.
@Override
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
}
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
ここの主な操作は責任連鎖モードを使ってchain集合のinterceptr属性のinvoke方法を呼び出すことです.だから私たちはこのchainがどんなものなのかを見に来たらいいです.具体的にどのようにしてこのchainを得たのかは詳しく話しません.ソースコード(DefaultAdvisors AdapterRegistryのget Interceptors方法)を見ることができます.chain集合はMethodInterceptorの集合です.
このInterceportの集合は主に以下の種類が含まれています.
AsppectJAfter ThrowingAdviceはaop配置の中/ノード内の方法に対応しています.
AsppectJAfter Advice対応しています\
AsppectJAroundAddvice対応しています\
AfterReturningAdvice InterceptorはAfterReturningAdviceに対応しています\
MethodBefore Advice InterceptorはMethodBefore Adviceに対応しています\
これらのMethodInterceptorが呼び出した順序は、設定ファイルにOrderを指定していない場合、設定ファイルに表示される順序で実行されます.実行する過程は責任連鎖モードの応用で、興味がある学生は先に例のdebugを示して深く研究することができます.