1.配置通知器
其實如何配置攔截器的問題誊酌,可以轉(zhuǎn)化為攔截器元素是從哪來的部凑,又在哪邊配置的問題”套牵看過上章Aop攔截器調(diào)用解析的博文的朋友肯定有印象存在著一行代碼
// 獲得該方法定義好的連接器鏈.
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
這里的advised是AdvisedSupport對象涂邀,我們來看一下它的具體實現(xiàn)
//這里運用緩存,存入了Map<MethodCacheKey, List<Object>>
//key:Method ; value: advisor chain List
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class<?> targetClass) {
MethodCacheKey cacheKey = new MethodCacheKey(method);
List<Object> cached = this.methodCache.get(cacheKey);
if (cached == null) {
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this, method, targetClass);
this.methodCache.put(cacheKey, cached);
}
return cached;
}
DefaultAdvisorChainFactory的getInterceptorsAndDynamicInterceptionAdvice方法
//獲取通知
@Override
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, Class<?> targetClass) {
//根據(jù)AOP中配置創(chuàng)建通知器鏈的集合.
List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
//獲取目標(biāo)類的class對象
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
//判斷Advisors是否符合配置要求
boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
//獲取AdvisorAdapterRegistry對象
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
//遍歷advisors
for (Advisor advisor : config.getAdvisors()) {
//PointcutAdvisor
if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
//AOP配置對通知已經(jīng)過濾或者當(dāng)前切入點的類過濾器匹配目標(biāo)類
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
//獲取advisor中的方法攔截器列表
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
//獲取advisor切點的方法匹配器
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
//目標(biāo)類方法匹配切點
if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
//方法匹配器是運行時動態(tài)匹配的
if (mm.isRuntime()) {
//將方法攔截器和方法匹配器封裝后添加到返回的通知器集合中.
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
//將方法攔截器添加到返回的通知器集合中
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
//引入通知器
else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
//其他通知器
else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
private static boolean hasMatchingIntroductions(Advised config, Class<?> actualClass) {
for (int i = 0; i < config.getAdvisors().length; i++) {
Advisor advisor = config.getAdvisors()[i];
//通知器是引入通知器
if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
//是否匹配目標(biāo)類
if (ia.getClassFilter().matches(actualClass)) {
return true;
}
}
}
return false;
}
在ProxyFactoryBean的getObject方法中對advisor進行初始化時箱锐,從XML配置中獲取了Advisor通知器比勉。在初始化Advisor中,可以看到對IOC容器的一個getBean回調(diào)來得到配置好的Advisor通知器驹止。那么ProxyFactoryBean是如何獲得IOC容器浩聋,然后通過回調(diào)來獲得Advisor的呢?對于IOC容器的使用幢哨,如果需要回調(diào)容器赡勘,前提是當(dāng)前的Bean實現(xiàn)BeanFactoryAware接口嫂便,并實現(xiàn)setBeanFactory方法捞镰,同時設(shè)置一個屬性來持有IOC容器,就可以在Bean中取得IOC容器并進行回調(diào)了,而ProxyFactoryBean就實現(xiàn)了這個接口岸售。ProxyFactoryBean給出通知器的名字(這些名字在XML中interceptorNames的list中)践樱,在IOC對FactoryBean進行依賴注入的時候,會直接注入到FactoryBean的interceptorNames的屬性中凸丸。完成這個過程以后拷邢,ProxyFactoryBean就獲得了配置的通知器。
2.Advice的通知實現(xiàn)
首先我們來看下如何獲取通知器的通知屎慢,我們在解析如何獲取配置通知器的時候出現(xiàn)過如下這行代碼
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
因為AdvisorAdapterRegistry是一個接口瞭稼,我們來看一下它的默認實現(xiàn)類DefaultAdvisorAdapterRegistry
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {
//通知器適配器集合
private final List<AdvisorAdapter> adapters = new ArrayList<AdvisorAdapter>(3);
/**
* 構(gòu)造方法,只有3種通知器適配器.
*/
public DefaultAdvisorAdapterRegistry() {
registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
registerAdvisorAdapter(new AfterReturningAdviceAdapter());
registerAdvisorAdapter(new ThrowsAdviceAdapter());
}
//將通知封裝為通知器
@Override
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
if (adviceObject instanceof Advisor) {
return (Advisor) adviceObject;
}
if (!(adviceObject instanceof Advice)) {
throw new UnknownAdviceTypeException(adviceObject);
}
Advice advice = (Advice) adviceObject;
if (advice instanceof MethodInterceptor) {
return new DefaultPointcutAdvisor(advice);
}
for (AdvisorAdapter adapter : this.adapters) {
//檢查符合的advice.
if (adapter.supportsAdvice(advice)) {
return new DefaultPointcutAdvisor(advice);
}
}
throw new UnknownAdviceTypeException(advice);
}
//獲得通知器的通知
@Override
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(3);
//獲取advice通知
Advice advice = advisor.getAdvice();
//如果通知是MethodInterceptor類型,則加入interceptors
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
//對通知進行適配腻惠,從適配器(MethodBeforeAdviceAdapter环肘,AfterReturningAdviceAdapter,ThrowsAdviceAdapter)中取出封裝好AOP編織功能的攔截器
for (AdvisorAdapter adapter : this.adapters) {
if (adapter.supportsAdvice(advice)) {
interceptors.add(adapter.getInterceptor(advisor));
}
}
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
}
return interceptors.toArray(new MethodInterceptor[interceptors.size()]);
}
//注冊通知適配器
@Override
public void registerAdvisorAdapter(AdvisorAdapter adapter) {
this.adapters.add(adapter);
}
}
我們以MethodBeforeAdviceAdapter為例集灌,看一下MethodBeforeAdviceAdapter的具體實現(xiàn)
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {
@Override
public boolean supportsAdvice(Advice advice) {
return (advice instanceof MethodBeforeAdvice);
}
@Override
public MethodInterceptor getInterceptor(Advisor advisor) {
MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
return new MethodBeforeAdviceInterceptor(advice);
}
}
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {
private MethodBeforeAdvice advice;
/**
* Create a new MethodBeforeAdviceInterceptor for the given advice.
* @param advice the MethodBeforeAdvice to wrap
*/
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
return mi.proceed();
}
}
如代碼所示悔雹,MethodBeforeAdviceInterceptor 完成的是對MethodBeforeAdvice 通知的封裝,可以在MethodBeforeAdviceInterceptor 設(shè)計的invoke回調(diào)方法中欣喧,看到首先觸發(fā)了advice的before方法腌零,然后才是MethodInvocation的proceed方法調(diào)用。而proceed方法已經(jīng)在第十一章中分析完畢唆阿。以上則是Spring AOP的所有內(nèi)容益涧。