栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

AOP的源码走读

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

AOP的源码走读

aop源码

又撸了一边AOP的源码 ,做一下整理 (可能比较乱 就自己能看懂)我是通过注解的形式打断点来看的 像配置类开启AOP 打注解@EnableAspectJAutoProxy 切入的的类 @Aspect 和@Pointcut @Before 这些我就不表述了

我主要记住一下源码的关键步骤 以及思路
一:解析切面
二:创建动态代理
三:调用

------关于 AOP 到解析的开始的调用过程 start-------------------------

1.org.springframework.context.support.AbstractApplicationContext#refresh -----启动IOC
2.org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization ---- 实例化我们剩余的单实例bean.
finishBeanFactoryInitialization 方法中的 {
//实例化剩余的单实例bean
beanFactory.preInstantiateSingletons();

3.org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons
4.org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)
5.org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
doGetBean 方法中的 {
//进入创建bean的逻辑
return createBean(beanName, mbd, args);
}
6.org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])
createBean方法中的{

Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}

  1. org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessBeforeInstantiation – 解析当前Bean的切面
    ------关于 AOP 到解析的开始的调用过程 end-------------------------

org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator#shouldSkip
org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors
org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors
List advisors = super.findCandidateAdvisors(); ---- 是以前接口的方式 注解的方式 集合返回的是0
@Override
protected List findCandidateAdvisors() {
// 找出xml配置的Advisor和原生接口的AOP的Advisor 找出事务相关的advisor
List advisors = super.findCandidateAdvisors();
//找出Aspect相关的信息之后封装为一个advisor
if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
//返回我们所有的通知
return advisors;
}

postProcessBeforeInstantiation 方法把 advisors 放到缓存中

------关于 生成aop代理过程 Start-------------------------


@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
if (bean != null) {
//获取缓存key
Object cacheKey = getCacheKey(bean.getClass(), beanName);
// 之前循环依赖创建的动态代理 如果是现在的bean 就不再创建,,并且移除
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
// 该方法将会返回动态代理实例
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}

wrapIfNecessary方法的
// 根据当前bean找到匹配的advisor
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#getAdvicesAndAdvisorsForBean


org.springframework.aop.support.AopUtils#canApply(org.springframework.aop.Advisor, java.lang.Class, boolean)
//找到真正能用的增强器
return canApply(pca.getPointcut(), targetClass, hasIntroductions);

org.springframework.aop.support.AopUtils#canApply(org.springframework.aop.Pointcut, java.lang.Class, boolean) – 进行粗筛
// 进行类级别过滤(通过AspectJ) --粗筛
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}

org.springframework.aop.aspectj.AspectJexpressionPointcut#matches(java.lang.Class) 上面代码的类

org.springframework.aop.aspectj.AspectJexpressionPointcut#obtainPointcutexpression

org.springframework.aop.aspectj.AspectJexpressionPointcut#initializePointcutParser – 得到切点解析器 得到一个 Pointcutexpression

org.aspectj.weaver.tools.Pointcutexpression#couldMatchJoinPointsInType — 调用这个方法 进行粗筛

//循环所有的class对象
for (Class clazz : classes) {
//通过class获取到所有的方法
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
//循环我们的方法
for (Method method : methods) {
//通过methodMatcher.matches来匹配我们的方法
if (introductionAwareMethodMatcher != null ?
// 通过切点表达式进行匹配 AspectJ方式 调用这个方法进行精筛
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
// 通过方法匹配器进行匹配 内置aop接口方式
methodMatcher.matches(method, targetClass)) {
// 只要有1个方法匹配上了就创建代理
return true;
}
}
}

org.springframework.aop.IntroductionAwareMethodMatcher#matches – 调用这个方法进行精筛 只要有一个匹配上了 就返回true 返回到
org.springframework.aop.support.AopUtils#findAdvisorsThatCanApply 方法下的 CanApply方法 Advisor 加入到 eligibleAdvisors 集合中

if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}

eligibleAdvisors 回到 org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findEligibleAdvisors 方法中会进行加上一个 内置的 ExportInvocation 的Advisor List 索引是0
protected List findEligibleAdvisors(Class beanClass, String beanName) {
// 拿到接口方式的AOP (这次是从缓存中拿了)
List candidateAdvisors = findCandidateAdvisors();
//判断我们的通知能不能作用到当前的类上(切点是否命中当前Bean)
List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors); ---- - 这里加入了一个和 内置的 ExportInvocation 的Advisor
//对我们的advisor进行排序
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}

再进行排序 索引大的放在前面 ( 多个切面就根据实现了 order注解的数字 小的在前面)

最后根据 eligibleAdvisors 这个集合 的数量 大于 0 则证明可以创建动态代理

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createProxy — 创建动态代理 (createProxy 是wrapIfNecessary方法内的)
org.springframework.aop.framework.DefaultAopProxyFactory#createAopProxy 在这个方法中会判断是用 JDK动态代理 还是 cglib动态代理

设置了ProxyTargetClass就会用cglib动态代理
如果没有设置,并且有实现接口就会用JDK动态代理
通过代理工厂得到动态代理 放到一级缓存当中

------关于 生成aop代理过程 End-------------------------

------关于 调用动态代理过程 Start-------------------------
以JDK动态代理为例子:
调用的时候 从bean里面拿到的就是一个动态代理的实现, 在调用方法的时候 就会进入到 org.springframework.aop.framework.JdkDynamicAopProxy#invoke
JdkDynamicAopProxy 的 invoke方法中
会进行一些判断:
//若执行代理对象的equals方法不需要代理
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
return equals(args[0]);
}
//若执行的是hashCode方法 不需要代理
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
return hashCode();
}
//若执行的class对象是DecoratingProxy 则不会对其应用切面进行方法的增强。返回源目标类型
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.
return AopProxyUtils.ultimateTargetClass(this.advised);
}
// 如果目标对象实现的Advised接口,则不会对其应用切面进行方法的增强。 直接执行方法
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// Service invocations on ProxyConfig with the proxy config…
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}

如: 是否是执行对象的equals方法 、 是否执行的是hashCode方法 、执行的class对象是DecoratingProxy对象 、是否实现了目标对象实现的Advised接口

再判断一下 exposeProxy = true

接着 把我们的aop的advisor 全部转化为interceptorList, 通过责任链模式 依此调用
//把我们的aop的advisor 全部转化为拦截器, 通过责任链模式 依此调用
List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

责任链 调用调用org.springframework.aop.framework.ReflectiveMethodInvocation#proceed
proceed 这个方法

------关于 调用动态代理过程 End-------------------------

最后提出几个问题
问题一:Aop解析是在第一个bean的后置处理器进行解析的 那是哪个一个bean?
答:
是 AnnotationAwareAspectJAutoProxyCreator 这个bean 的后置处理器进行解析切面
把带有AspectJ这个注解的类
下面对应的@before @afrer等这些注解的方法 解析成一条条的 Advisor (Advisor中带有 Advice Pointcut )
Advice — 通知
Pointcut 有表达式 回去匹配 匹配到了 就回去创建动态代理

问题二: aop 在哪个方法创建动态代理?

正常的bean 在初始化之后
循环依赖的在getSingleton的时候 (循环依赖会设置一个smarInstantiationAwareBeanPostProcesor.getEarlyBeanrRefence)

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/328165.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号