1. 整体
2. 重点
2.1 重要概念
- 切点
- 通知
- 代理
- 拦截
- 增强
2.2 动态代理原理
记住一点,AOP的核心技术就是动态代理
AOP用的是代理,管理代理。java有自带的代理机制,还有Cglb代理机制。这两种机制Aop都在应用,Java代理主要运用于接口,而Cglb主要是类。
很重要的一段话
了解一下ProxyCreatorSupport
AOP的具体实现就是在这个类中。
都是从DefaultAopProxyFactory中的createAopProxy()开始下面操作的。
- 生成代理对象
- 执行拦截器。
JdkDynamicAopProxy拦截器
从JdkDynamicAopProxy的invoke()方法,到ReflectiveMethodInvocation的process()
CglibAopProxy拦截器
intercept()方法,拦截器不是凭空来的,需要进行拦截器注册才能保存到拦截器链中,在拦截器注册之间有一个:从拦截器注册器中进行适配,确定哪些拦截器是该代理目标的拦截器的。
ReflectiveMethodInvocation反射
这里通过反射调用目标方法。 process()方法中实现,这里也是执行matches()的地方。
2.3 invoke()方法逻辑分析
代理中最主要的方法就是invoke()方法了,那就介绍一下该方法的逻辑。
- 获取目标源TargetSource
- 赋值代理目标对象Target
- 获取代理对象类
- 获取代理对象参数,用数组来存放
- 通过反射调用目标方法
- 获取目标方法执行后返回信息
2.4 关于切点
知道切点都是到,就是增强的目标方法,一般是方法。但是Aop怎么知道对那些方法进行操作,这就要在配置的时候告诉Aop需要操作哪些方法。
先看一下Pointcut的整体架构:
这里每一个实现类都要实现一个方法matchs(),至于不同的切点匹配规则不一样。通常用到的
- 方法名
- 注解
- 正则表达式
2.4 Advisor通知器
将增强设计,也就是Advice和切点(Pointcut)结合起来。 也就是哪个切点上使用哪个通知。
2.4.1 DefaultPointcutAdvisor默认切点通知器
也就是当通知器为空的时候,就是用默认的。 默认就是对任何方法的匹配都成功。
TrueMethodMatcher这个方法的匹配对任何方法的匹配都会成功
总结
-
关于Spring AOP的介绍
AOP是基于代理对象的,,通过ProxyCreateSuport来设置创建代理对象的通用操作,在这个类中主要就是获取代理目标对象的SourceTarget,获取代理对象的信息。
-
再通过DefaultAopProxyFactory确定AopProxy代理对象的生成策略,生成策略的配置主要实在createAopProxy()方法中,其实也就是确定是有Java Proxy还是CGLIB第三来生成AopProxy代理对象。
在确定了生成策略之后,真正的Proxy实在ObjenesisCglibAopProxy和JdkDynamicAopProxy类中生成的。
- 代理对象生成之后,在ObjenesisCglibAopProxy-(intercept)和JdkDynamicAopProxy-(invoke)都有自己的回调函数,回调函数的作用就是对代理的方法进行各种增强操作。
- 回调函数的作用是,获取目标对象(包括目标方法,方法参数),拦截器链,创建ReflectiveMethodInvocation的process()方法来完成Aop的各种增强处理。这里的拦截器链其实就是通过遍历连接器链,用一个一个的拦截器来执行拦截增强。
-
这里有一个问题,当拦截器为空的时候,直接使用反射来调用目标方法,不需要创建ReflectiveMethodInvocation。这也是我之前运用AOP的一个例子,没有用到拦截器,获取了代理的目标对象方法之后,通过目标对象方法调用invoke(target, args)来执行方法。
这里记住一点这些操作是在ObjenesisCglibAopProxy-(intercept)和JdkDynamicAopProxy-(invoke)完成的,执行的方法是括号的方法。
- 拦截器分类两种JdkDynamicAopProxy拦截器和CglibAopProxy拦截器,其实不难理解,既然是对AopProxy代理对象的拦截,针对AopProxy两种生成策略,肯定也有两种拦截器。上面已经讲过了,当拦截器链不为空的时候,这两种连接器都是通过ReflectiveMethodInvocation的process()方法进行代理目标函数的增强的。
- 所以接下来的重心就是ReflectiveMethodInvocation的process()方法,该方法中中实现了具体的增强逻辑。贴一个代码吧。代码的核心是从interceptorsAndDynamicMethodMatchers集合中获取拦截器或者拦截通知,然后执行增强操作。这里的interceptorsAndDynamicMethodMatchers连接器接口是从前面提到的方法中传过来的,那就返回获取看看。
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;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
if (dm.methodMatcher.matches(this.method, 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);
}
}
-
关于通知或者拦截器来源我们在JdkDynamicAopProxy的invoke方法中看到了下面这段代码,跟进去发现是在AdvisedSupport获取的。代码如第二段代码,该类中用了一个Map来缓存所有代理方法的拦截器,
Map定义:
从代码中可以看到,真正获取拦截器的方法是:private transient Map<MethodCacheKey, List<Object>> methodCache;
this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice( this, method, targetClass);
方法。跟进去看看。
这里有一个问题,通过advisorChainFactory工程来获取拦截器,advisorChainFactory是该类的一个属性,看代码发现,该属性的具体实例被配置成DefaultAdvisorChainFactory类
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable 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中。这里算是找到了获取拦截器链的源头了。this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice( this, method, targetClass);
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass) {
// This is somewhat tricky... We have to process introductions first,
// but we need to preserve order in the ultimate list.
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
Advisor[] advisors = config.getAdvisors();
List<Object> interceptorList = new ArrayList<>(advisors.length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
Boolean hasIntroductions = null;
for (Advisor advisor : advisors) {
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
boolean match;
if (mm instanceof IntroductionAwareMethodMatcher) {
if (hasIntroductions == null) {
hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
}
match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
}
else {
match = mm.matches(method, actualClass);
}
if (match) {
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
if (mm.isRuntime()) {
// Creating a new object instance in the getInterceptors() method
// isn't a problem as we normally cache created chains.
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;
}
- 接下来就来看看这个方法的逻辑,该方法就是用一个单例类来注册通知-拦截器。首先通过获取所有的advisors,然后遍历获得所有advisiors,在匹配代理目标方法切点是否有该拦截器,如果有,就将该拦截器注册,保存到一个List拦截器集合中。 这里基本是理解了,但是有个问题,advisior是怎么读入系统的呢? 这将是整个Aop的最后一个环节了。
- advisior真正注册的地方就是在ProxyFacrotyBean中的initializeAdvisorChain()。之前在代码中有这一行代码。
,那个时候我就在这里的Advisor[] 从哪里来的,经过一番查看,就是从ProxyFacrotyBean中的initializeAdvisorChain()配置的。 这样这个Aop的逻辑就很清晰了。Advisor[] advisors = config.getAdvisors();
AopProxy代理类的获取,Advisior的注册,执行增强操作。 这一套都能联系起来。其实Aop的逻辑组件确实就这三个,理解深刻了就会化繁就简。