面向切面编程
咱们大家都知道透析吧,血液从身体里面流出来,经过一个罐子,罐子里面摆着一层层的透析薄膜,血液流过透析薄膜,废物被透析薄膜拦截,干净的血流流回我们的身体。我们JAVA中的AOP思想就像这一个透析罐子,AOP中的切面就像是罐子里面一层层的透析薄膜,流经里面的血液就像是切点。
就我暂时所遇到的编程来说:它们都有一个共同点,那就是它们一直在尽量减少重复的代码。线程池的责任是这样,NIO中的多路复用器是这样,数据库连接池是这样,AOP是这样,IOC还是这样。
AOP, Spring AOP,AspectJ这三者关系
AOP是一种思想,Spring AOP 和 AspectJ 是对这种思想的一个具体实现,Spring AOP 是基于 Spring Bean 做的实现,而 AspectJ 则是可以针对Java字节码进行修改。
@Pointcut() 注解的匹配方式: 通常 “.” 代表一个包名,”..” 代表包及其子包,方法参数任意匹配使用两个点 “..”。
梗概
AOP:面向切面编程 解决了什么问题:在不改变原有逻辑的情况下,增强代码,从根本上解决代码重复问题。
面向切面编程支持两种方式:JDK动态代理和CGLIB动态代理。
JDK动态代理面向接口
- 声明一个类继承InvocationHandler这个接口,实现invoker方法。
- 在invoke方法中实现我们的代理逻辑
- 通过Proxy.newProxyInstance传入代理接口的ClassLoader、Hello.class、InvocationHandler。生成一个代理类,强转为接口。
CGlib动态代理面向子类 cglib可以在运行期扩展Java类的实现。 cglib封装了asm,可以在运行期动态生成新的class(子类)
五种增强:
- 前置增强:在目标方法执行前
- 后置增强:在目标方法执行后
- 环绕增强:在目标方法执行前后都进行
- 异常抛出增强:抛出异常后执行
- 引介增强:为目标类增加新的方法和属性
如何实现一个切面
- 在配置类配置@EnableAspectJAutoProxy
- 使用@Aspect注解那个AOP类
- @Pointcut(“execution(* Concert.Performance.perform(..))”) 修饰一个方法用于确定切面
- @Around(“performance()”) 确定环绕方式和织入对象
深入源码
DefaultAdvisorAutoProxyCreator 将这个类注入为Bean可以将所有的 Advicor 生效。
Spring 5.3.6
DefaultAdvisorAutoProxyCreator 这个类继承了BeanPostProcessor,实现了 postProcessAfterInitialization() 方法,在类完成初始化之后会对类进行动态代理,然后返回代理之后的对象。具体见:AbstractAutowireCapableBeanFactory.class 437行
// AbstractAutoProxyCreator.class 286
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
// 获取bean的唯一标识
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
首先通过bean的Class对象或者beanName获取它的唯一标识
接着调用 wrapIfNecessary 方法,如果需要增加就先增强然后返回代理类。
// AbstractAutoProxyCreator.class 325
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// 这个bean不需要增强就直接返回
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
// 如果bean是一个增强、切点等等则不会被代理。第二种情况是IOC的一个特性,以.ORIGINAL作为class路径结尾的也不会被代理。
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// 获取这个类的增强
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
// 将bean的代理标记设置为true
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;
}
wrapIfNecessary 就是Spring AOP的核心方法了
首先判断这个bean是否需要增强,不需要增强的话直接返回原始的bean。
接着判断这个bean是不是本身就是一个AOP相关的类:Advice,Pointcut,Advisor,AopInfrastructureBean 这种情况也不需要增强。
或者这个bean的class以.ORIGINAL结尾,这种情况也不会增强。这是IOC的一种特性,具体不清楚
然后获取这个类的增强列表
将这个bean在advisedBeans设置为已代理
将增强列表加入到代理类中
返回代理类。
从上面的逻辑看,核心的方法就是获取bean对应的增强,然后将增强加入到代理类中。下文将按照这两个部分分别分析
获取bean对应的增强
getAdvicesAndAdvisorsForBean 获取bean对应的增强
它的实现类是 AbstractAdvisorAutoProxyCreator
// AbstractAdvisorAutoProxyCreator.class 75
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
// 获取这个bean的增强列表
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
// AbstractAdvisorAutoProxyCreator.class 95
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 获取候选的增强列表
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 从候选增强列表挑选出当前bean可以使用的
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
// 钩子方法,留给子类使用。
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
上面方法的逻辑先拿到候选的增强列表
然后从候选的增强列表选出当前bean可以使用的返回。
钩子方法,留给子类使用
将增强排序后返回
那么它是如何获取到候选的增强列表的呢?
// AbstractAdvisorAutoProxyCreator.class 109
protected List<Advisor> findCandidateAdvisors() {
Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
// 获取增强列表。增强也是以bean的方式被Spring管理
return this.advisorRetrievalHelper.findAdvisorBeans();
}
// BeanFactoryAdvisorRetrievalHelper.class 67
public List<Advisor> findAdvisorBeans() {
String[] advisorNames = this.cachedAdvisorBeanNames;
// 如果增强的beanName列表是空的,那就进行初始化
if (advisorNames == null) {
// 获取当前beanFactory中的属于增强类的beanName。并且允许获取singleton类型之外的bean。
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
this.cachedAdvisorBeanNames = advisorNames;
}
if (advisorNames.length == 0) {
return new ArrayList<>();
}
List<Advisor> advisors = new ArrayList<>();
// 遍历增强beanName列表
for (String name : advisorNames) {
if (isEligibleBean(name)) {
// beanName正在创建中则跳过
if (this.beanFactory.isCurrentlyInCreation(name)) {
if (logger.isTraceEnabled()) {
logger.trace("Skipping currently created advisor '" + name + "'");
}
}
else {
try {
// 初始化beanName
advisors.add(this.beanFactory.getBean(name, Advisor.class));
}
catch (BeanCreationException ex) {
Throwable rootCause = ex.getMostSpecificCause();
if (rootCause instanceof BeanCurrentlyInCreationException) {
BeanCreationException bce = (BeanCreationException) rootCause;
String bceBeanName = bce.getBeanName();
if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {
if (logger.isTraceEnabled()) {
logger.trace("Skipping advisor '" + name +
"' with dependency on currently created bean: " + ex.getMessage());
}
// Ignore: indicates a reference back to the bean we're trying to advise.
// We want to find advisors other than the currently created bean itself.
continue;
}
}
throw ex;
}
}
}
}
return advisors;
}
上面的逻辑就是先获取当前beanFactory所有的增强类的beanName,然后逐个调用getBean方法初始化。
上面方法中获取增强类beanName的逻辑就不深入了。
回到主线逻辑,我们拿到了所有的候选增强之后,接下来就是从中选中出当前beanName可以使用的增强,然后进行增强操作。
那么它是如何从候选的增强列表挑选出当前bean可以使用的呢?
// AbstractAdvisorAutoProxyCreator.class 95
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 获取候选的增强列表
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 从候选增强列表挑选出当前bean可以使用的
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
// 钩子方法,留给子类使用。
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
// AbstractAdvisorAutoProxyCreator.class 109
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
// 将beanName标记为正在进行代理
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
// 返回当前bean可用的增强
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
// 取消标记
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
// AopUtils.class 305
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new ArrayList<>();
for (Advisor candidate : candidateAdvisors) {
// IntroductionAdvisor 不太清楚,我们常用的是PointcutAdvisor,在下面应用
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
// 遍历所有增强,如果某个增强可以应用clazz的任何一个方法则将该增强加入到eligibleAdvisors中。
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
// PointcutAdvisor 在这里被应用
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
IntroductionAdvisor和PointcutAdvisor有什么不同? PointcutAdvisor切点的粒度是方法,它是在某一个方法执行的前后加上我们的增强。 而IntroductionAdvisor切点的粒度是类
// AopUtils.class 283
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
// 常用的是这个
else if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
// It doesn't have a pointcut so we assume it applies.
return true;
}
}
// AopUtils.class 224
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();
if (methodMatcher == MethodMatcher.TRUE) {
// No need to iterate the methods if we're matching any method anyway...
return true;
}
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
Set<Class<?>> classes = new LinkedHashSet<>();
if (!Proxy.isProxyClass(targetClass)) {
classes.add(ClassUtils.getUserClass(targetClass));
}
// 获取这个类实现的所有接口
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
// 如果这个切点可以匹配这个类中的任何一个方法则返回true,否则返回false。
for (Class<?> clazz : classes) {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
if (introductionAwareMethodMatcher != null ?
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
从所有候选增强中返回当前bean可用的增强列表,这个逻辑其实也比较直接。
遍历所有候选增强,遍历的时候判断这个增强是否可以匹配bean对应类的任何一个方法,如果可以则返回true将该增强加入到返回列表中。
总结
- 从当前beanFactory中获取所有Advisor.class类型的bean,这些就是候选增强
- 将上述的所有bean逐个调用getBean方法,进行初始化。
- 遍历所有增强
- 遍历的时候判断当前增强是否可以匹配目标class的任何一个方法,如果可以则返回true,表示当前增强可用于该class,接着将当前增强加入到可用增强列表。
下面需要将可用增强列表增强到目标类中。
生成代理
回到最开始的方法,getAdvicesAndAdvisorsForBean 这个方法已经分析完了,接下来看下createProxy方法。
// AbstractAutoProxyCreator.class 325
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// 这个bean不需要增强就直接返回
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
// 如果bean是一个增强、切点等等则不会被代理。第二种情况是IOC的一个特性,以.ORIGINAL作为class路径结尾的也不会被代理。
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// 获取这个类的增强
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
// 将bean的代理标记设置为true
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;
}
// AbstractAutoProxyCreator.class 433
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
// proxy-target-class="true" 如果有这个配置表示要求用CGLIB生成代理
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
// beanClass有接口的话把接口都添加到proxyFactory中;没有接口就setProxyTargetClass(true),表示使用CGLIB
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// 将入参的增强和公共的增强包装成Advisor数组,并返回
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// Use original ClassLoader if bean class not locally loaded in overriding class loader
ClassLoader classLoader = getProxyClassLoader();
if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {
classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();
}
// 代理
return proxyFactory.getProxy(classLoader);
}
生成代理工厂,根据配置使用CGLIB还是JDK动态代理,将入参的增强和公共的增强包装在一起返回一个增强数组,进行代理。
首先会通过代理工厂创建一个CGLIB或者JDK代理,然后调用他们实现的getProxy方法
// ProxyFactory.class 109
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
// ProxyCreatorSupport.class 101
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
// 创建AOP代理类
return getAopProxyFactory().createAopProxy(this);
}
// DefaultAopProxyFactory.class 53
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// 第一个参数不清楚,后面的参数是这些意思:是否要对代理进行优化 || proxy-target-class=true(使用CGLIB) || 代理对象没接口
if (!NativeDetector.inNativeImage() &&
(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() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
接下来就分别看CGLIB的getProxy方法和JDK动态代理的getProxy方法的实现了。
JDK动态代理
// JdkDynamicAopProxy.class 122
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
// 通过构造对象生成一个代理对象,入参this就是InvocationHandler,它具体实现了invoke方法
return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
}
通过构造对象生成代理对象,实际的操作得看 JdkDynamicAopProxy 的 invoke 方法
// JdkDynamicAopProxy.class 159
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
// 如果当前调用的方法是equals或者hashCode且这两个方法没有被代理,则直接调用。 另外两个分支不清楚
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {...}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {...}
else if (method.getDeclaringClass() == DecoratingProxy.class) {....}
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {...}
Object retVal;
// 通过线程本地变量解决代理类内部方法自调用问题。@EnableAspectJAutoProxy(exposeProxy = true)
// 详情见文章最后的学习文章列表
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// 获取这个方法的增强列表。
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// 如果增强列表为空,说明不需要增强,那我们不创建MethodInvocation,直接调用目标方法。
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// 创建一个MethodInvocation,它的构造方法只做了一些属性的赋值
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// 调用目标方法,肯定是先执行前置的方法,然后执行目标方法,接着执行后置方法。
retVal = invocation.proceed();
}
// Massage return value if necessary.
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// Special case: it returned "this" and the return type of the method
// is type-compatible. Note that we can't help if the target sets
// a reference to itself in another returned object.
retVal = proxy;
}
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
看一下它是怎么获取这个方法对于的增强的,解析一下 getInterceptorsAndDynamicInterceptionAdvice
// AdvisedSupport.class 466
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
AdvisedSupport.MethodCacheKey cacheKey = new AdvisedSupport.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.class 51
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass) {
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) {
// 最常用的就是Pointcut增强,它是针对方法的增强
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
// 是否经历过预处理(默认false),如果没经历过那么现在进行匹配操作。判断增强是否可以作用于当前类
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方法拦截器
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
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;
// IntroductionAdvisor的切点是类,只要类匹配成功就可以了
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;
}
接下来就是用递归的方式逐个调用列表中的拦截器,最后调用被代理的方法,然后返回递归方法,在返回递归的过程中实现后置增强。
// ReflectiveMethodInvocation.class 160
public Object proceed() throws Throwable {
// currentInterceptorIndex从-1开始,到size()-2结束,因此到size()-1就可以调用被代理的方法了。
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
// 获取拦截器
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
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 {
// 使用递归的方式去调用拦截器
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
看下 MethodInterceptor 的前置增强和后置增强的实现,还是挺简单的。
// 前置增强
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
private final MethodBeforeAdvice advice;
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}
@Override
@Nullable
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
return mi.proceed();
}
}
// 后置增强
public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {
private final AfterReturningAdvice advice;
public AfterReturningAdviceInterceptor(AfterReturningAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}
@Override
@Nullable
public Object invoke(MethodInvocation mi) throws Throwable {
Object retVal = mi.proceed();
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}
}
学习文章
https://www.javadoop.com/post/spring-aop-source 了解了 Spring AOP 的入口方法
https://blog.csdn.net/f641385712/article/details/89303088 IntroductionAvisor相关知识
https://blog.csdn.net/u013720069/article/details/112025020 了解了AOP动态代理exposeProxy参数的意义
https://cloud.tencent.com/developer/article/1497782 学习了PointcutAdvisor和IntroductionAdvisor的区别