1.配置通知器
其实如何配置拦截器的问题,可以转化为拦截器元素是从哪来的,又在哪边配置的问题。看过上章Aop拦截器调用解析的博文的朋友肯定有印象存在着一行代码
// 获得该方法定义好的连接器链.
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
这里的advised是AdvisedSupport对象,我们来看一下它的具体实现
//这里运用缓存,存入了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) {
//根据AOP中配置创建通知器链的集合.
List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
//获取目标类的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配置对通知已经过滤或者当前切入点的类过滤器匹配目标类
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
//获取advisor中的方法拦截器列表
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
//获取advisor切点的方法匹配器
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
//目标类方法匹配切点
if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
//方法匹配器是运行时动态匹配的
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;
//是否匹配目标类
if (ia.getClassFilter().matches(actualClass)) {
return true;
}
}
}
return false;
}
在ProxyFactoryBean的getObject方法中对advisor进行初始化时,从XML配置中获取了Advisor通知器。在初始化Advisor中,可以看到对IOC容器的一个getBean回调来得到配置好的Advisor通知器。那么ProxyFactoryBean是如何获得IOC容器,然后通过回调来获得Advisor的呢?对于IOC容器的使用,如果需要回调容器,前提是当前的Bean实现BeanFactoryAware接口,并实现setBeanFactory方法,同时设置一个属性来持有IOC容器,就可以在Bean中取得IOC容器并进行回调了,而ProxyFactoryBean就实现了这个接口。ProxyFactoryBean给出通知器的名字(这些名字在XML中interceptorNames的list中),在IOC对FactoryBean进行依赖注入的时候,会直接注入到FactoryBean的interceptorNames的属性中。完成这个过程以后,ProxyFactoryBean就获得了配置的通知器。
2.Advice的通知实现
首先我们来看下如何获取通知器的通知,我们在解析如何获取配置通知器的时候出现过如下这行代码
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
因为AdvisorAdapterRegistry是一个接口,我们来看一下它的默认实现类DefaultAdvisorAdapterRegistry
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {
//通知器适配器集合
private final List<AdvisorAdapter> adapters = new ArrayList<AdvisorAdapter>(3);
/**
* 构造方法,只有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的具体实现
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 设计的invoke回调方法中,看到首先触发了advice的before方法,然后才是MethodInvocation的proceed方法调用。而proceed方法已经在第十一章中分析完毕。以上则是Spring AOP的所有内容。