Java Spring AOP之PointCut案例詳解
一、PointCut接口
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.aop;
/**
* Core Spring pointcut abstraction.
*
* <p>A pointcut is composed of a {@link ClassFilter} and a {@link MethodMatcher}.
* Both these basic terms and a Pointcut itself can be combined to build up combinations
* (e.g. through {@link org.springframework.aop.support.ComposablePointcut}).
*
* @author Rod Johnson
* @see ClassFilter
* @see MethodMatcher
* @see org.springframework.aop.support.Pointcuts
* @see org.springframework.aop.support.ClassFilters
* @see org.springframework.aop.support.MethodMatchers
*/
public interface Pointcut {
/**
* Return the ClassFilter for this pointcut.
* @return the ClassFilter (never {@code null})
*/
ClassFilter getClassFilter();
/**
* Return the MethodMatcher for this pointcut.
* @return the MethodMatcher (never {@code null})
*/
MethodMatcher getMethodMatcher();
/**
* Canonical Pointcut instance that always matches.
*/
Pointcut TRUE = TruePointcut.INSTANCE;
}
由源碼可知,PointCut接口就是定義了兩個元素,ClassFilter和MethodMatcher。PointCut接口就是為了獲得這兩個元素。換句話說,PointCut的功能,都包含在了這兩個元素里。下面看這 兩個元素源碼。
二、ClassFilter接口
/*
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.aop;
/**
* Filter that restricts matching of a pointcut or introduction to
* a given set of target classes.
*
* <p>Can be used as part of a {@link Pointcut} or for the entire
* targeting of an {@link IntroductionAdvisor}.
*
* <p>Concrete implementations of this interface typically should provide proper
* implementations of {@link Object#equals(Object)} and {@link Object#hashCode()}
* in order to allow the filter to be used in caching scenarios — for
* example, in proxies generated by CGLIB.
*
* @author Rod Johnson
* @see Pointcut
* @see MethodMatcher
*/
@FunctionalInterface
public interface ClassFilter {
/**
* Should the pointcut apply to the given interface or target class?
* @param clazz the candidate target class
* @return whether the advice should apply to the given target class
*/
boolean matches(Class<?> clazz);
/**
* Canonical instance of a ClassFilter that matches all classes.
*/
ClassFilter TRUE = TrueClassFilter.INSTANCE;
}
這個接口用來過濾要生成代理的類和給定的類是否匹配。
該接口的實現(xiàn)類應該提供正確的equals()方法和hashCode()方法,以便于能在緩存中使用。例如通過cglib生成的代理對象。(這句話什么意思,不理解)。
matches方法就是判斷參數(shù)中的class類是否和切點定義的類相匹配。如果匹配,則生成代理對象,如果不匹配,則過濾掉。
三、MethodMatcher接口
/*
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.aop;
import java.lang.reflect.Method;
/**
* Part of a {@link Pointcut}: Checks whether the target method is eligible for advice.
*
* <p>A MethodMatcher may be evaluated <b>statically</b> or at <b>runtime</b> (dynamically).
* Static matching involves method and (possibly) method attributes. Dynamic matching
* also makes arguments for a particular call available, and any effects of running
* previous advice applying to the joinpoint.
*
* <p>If an implementation returns {@code false} from its {@link #isRuntime()}
* method, evaluation can be performed statically, and the result will be the same
* for all invocations of this method, whatever their arguments. This means that
* if the {@link #isRuntime()} method returns {@code false}, the 3-arg
* {@link #matches(java.lang.reflect.Method, Class, Object[])} method will never be invoked.
*
* <p>If an implementation returns {@code true} from its 2-arg
* {@link #matches(java.lang.reflect.Method, Class)} method and its {@link #isRuntime()} method
* returns {@code true}, the 3-arg {@link #matches(java.lang.reflect.Method, Class, Object[])}
* method will be invoked <i>immediately before each potential execution of the related advice</i>,
* to decide whether the advice should run. All previous advice, such as earlier interceptors
* in an interceptor chain, will have run, so any state changes they have produced in
* parameters or ThreadLocal state will be available at the time of evaluation.
*
* <p>Concrete implementations of this interface typically should provide proper
* implementations of {@link Object#equals(Object)} and {@link Object#hashCode()}
* in order to allow the matcher to be used in caching scenarios — for
* example, in proxies generated by CGLIB.
*
* @author Rod Johnson
* @since 11.11.2003
* @see Pointcut
* @see ClassFilter
*/
public interface MethodMatcher {
/**
* Perform static checking whether the given method matches.
* <p>If this returns {@code false} or if the {@link #isRuntime()}
* method returns {@code false}, no runtime check (i.e. no
* {@link #matches(java.lang.reflect.Method, Class, Object[])} call)
* will be made.
* @param method the candidate method
* @param targetClass the target class
* @return whether or not this method matches statically
*/
boolean matches(Method method, Class<?> targetClass);
/**
* Is this MethodMatcher dynamic, that is, must a final call be made on the
* {@link #matches(java.lang.reflect.Method, Class, Object[])} method at
* runtime even if the 2-arg matches method returns {@code true}?
* <p>Can be invoked when an AOP proxy is created, and need not be invoked
* again before each method invocation,
* @return whether or not a runtime match via the 3-arg
* {@link #matches(java.lang.reflect.Method, Class, Object[])} method
* is required if static matching passed
*/
boolean isRuntime();
/**
* Check whether there a runtime (dynamic) match for this method,
* which must have matched statically.
* <p>This method is invoked only if the 2-arg matches method returns
* {@code true} for the given method and target class, and if the
* {@link #isRuntime()} method returns {@code true}. Invoked
* immediately before potential running of the advice, after any
* advice earlier in the advice chain has run.
* @param method the candidate method
* @param targetClass the target class
* @param args arguments to the method
* @return whether there's a runtime match
* @see MethodMatcher#matches(Method, Class)
*/
boolean matches(Method method, Class<?> targetClass, Object... args);
/**
* Canonical instance that matches all methods.
*/
MethodMatcher TRUE = TrueMethodMatcher.INSTANCE;
}
PointCut的一部分,用來判斷方法是否需要進行增強。ClassFilter過濾需要生成代理的類。而這個類里,不是所有的方法都需要增強的,所以要通過MethodMatcher接口匹配出要增強的方法來。
MethodMatcher分為靜態(tài)匹配和動態(tài)匹配。靜態(tài)匹配是根據(jù)方法名匹配。動態(tài)匹配是根據(jù)參數(shù)進行匹配(不知道這么理解對不對)
MethodMatcher的實現(xiàn)類中,如果isRuntime()方法返回false,則使用靜態(tài)匹配,無論參數(shù)是什么,只要方法名匹配,則都會進行增強。而且這個接口中帶有3個參數(shù)的matches方法,即matches(java.lang.reflect.Method, Class, Object[])就永遠不會執(zhí)行。
實現(xiàn)類中,如果兩個參數(shù)的matches方法返回true,且isRuntime()也返回true。那么在執(zhí)行增強之前,會執(zhí)行三個參數(shù)的matches方法,來判斷這個增強是否要執(zhí)行。
下面來看接口三個方法的注釋:
boolean matches(Method method, Class<?> targetClass);
靜態(tài)核對給定的方法是否需要增強。如果返回false。則不再會執(zhí)行三個參數(shù)的matches方法。
boolean isRuntime();
當兩個參數(shù)的matches方法返回true時,是否要執(zhí)行三個參數(shù)的matches方法。該方法在AOP代理生成的時候執(zhí)行,而不是每次調(diào)用代理方法之前執(zhí)行。意思就是生成代理對象的時候,就已經(jīng)判斷好要不要執(zhí)行三個參數(shù)的matches方法了。
boolean matches(Method method, Class<?> targetClass, Object... args);
該方法執(zhí)行的時機是增強方法要執(zhí)行之前,判斷參數(shù)是否滿足要求,如果滿足,則執(zhí)行增強。注意isRuntime方法是創(chuàng)建代理對象時就決定好的,而是否執(zhí)行三個參數(shù)的matches方法是調(diào)用增強之前判斷的。
總結(jié)
從上面的源碼可以看出,PointCut就是起到過濾的作用,首先是過濾類,然后再過濾方法,篩選出需要加強的方法來。由接口可知,我們要將參數(shù)中的class或method進行比較,然后過濾,那么,和誰進行比較呢?要過濾的類和方法的規(guī)則存在哪里了呢?請看下回分解。
到此這篇關于Java Spring AOP之PointCut案例詳解的文章就介紹到這了,更多相關Java Spring AOP之PointCut內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Springboot通過配置WebMvcConfig處理Cors非同源訪問跨域問題
這篇文章主要介紹了Springboot通過配置WebMvcConfig處理Cors非同源訪問跨域問題,關于Cors跨域的問題,前端有代理和jsonp的常用方式解決這種非同源的訪問拒絕策略2023-04-04
knife4j+springboot3.4異常無法正確展示文檔
本文主要介紹了knife4j+springboot3.4異常無法正確展示文檔,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2025-01-01
Java concurrency之LockSupport_動力節(jié)點Java學院整理
這篇文章主要為大家詳細介紹了Java concurrency之LockSupport的相關資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-06-06

