Spring是如何实现AOP的
识别需要增强的 Bean。查找匹配的增强器。创建代理对象(JDK 或 CGLIB)。执行增强器链。这一机制使得 Spring 能够灵活地为 Bean 提供切面功能,而开发者无需关注底层的代理实现细节。🪁🍁 希望本文能够给您带来一定的帮助🌸文章粗浅,敬请批评指正!🍁🐥如对本文内容有任何疑问、建议或意见,请联系作者,作者将尽力回复并改进📓;(联系微信:Solitudemind )点击下方名
Spring是如何实现AOP的
博主 默语带您 Go to New World.
✍ 个人主页—— 默语 的博客👦🏻 优秀内容
《java 面试题大全》
《java 专栏》
《idea技术专区》
《spring boot 技术专区》
《MyBatis从入门到精通》
《23种设计模式》
《经典算法学习》
《spring 学习》
《MYSQL从入门到精通》数据库是开发者必会基础之一~
🍩惟余辈才疏学浅,临摹之作或有不妥之处,还请读者海涵指正。☕🍭
🪁 吾期望此文有资助于尔,即使粗浅难及深广,亦备添少许微薄之助。苟未尽善尽美,敬请批评指正,以资改进。!💻⌨
默语是谁?
大家好,我是 默语,别名默语博主,擅长的技术领域包括Java、运维和人工智能。我的技术背景扎实,涵盖了从后端开发到前端框架的各个方面,特别是在Java 性能优化、多线程编程、算法优化等领域有深厚造诣。
目前,我活跃在CSDN、掘金、阿里云和 51CTO等平台,全网拥有超过10万的粉丝,总阅读量超过1400 万。统一 IP 名称为 默语 或者 默语博主。我是 CSDN 博客专家、阿里云专家博主和掘金博客专家,曾获博客专家、优秀社区主理人等多项荣誉,并在 2023 年度博客之星评选中名列前 50。我还是 Java 高级工程师、自媒体博主,北京城市开发者社区的主理人,拥有丰富的项目开发经验和产品设计能力。希望通过我的分享,帮助大家更好地了解和使用各类技术产品,在不断的学习过程中,可以帮助到更多的人,结交更多的朋友.
我的博客内容涵盖广泛,主要分享技术教程、Bug解决方案、开发工具使用、前沿科技资讯、产品评测与使用体验。我特别关注云服务产品评测、AI 产品对比、开发板性能测试以及技术报告,同时也会提供产品优缺点分析、横向对比,并分享技术沙龙与行业大会的参会体验。我的目标是为读者提供有深度、有实用价值的技术洞察与分析。
AOP:面向切面编程原理简述
在面向切面编程(AOP)中,Spring 通过动态代理机制为目标对象提供增强功能。本文以 AbstractAutoProxyCreator
为核心,简要分析 AOP 的原理和关键实现步骤。
AOP 的入口
AbstractAutoProxyCreator
包含两个关键方法:
- 提前暴露 Bean 的引用地址(用于解决循环依赖):
getEarlyBeanReference
- Bean 初始化后的后置处理:
postProcessAfterInitialization
两者都会调用 AOP 的核心方法 wrapIfNecessary
,这是 AOP 代理逻辑的入口。
// 提前暴露 Bean 的引用
public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
this.earlyProxyReferences.put(cacheKey, bean); // 缓存
return this.wrapIfNecessary(bean, beanName, cacheKey); // 包装
}
// 初始化后的后置处理
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return this.wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
wrapIfNecessary
方法的作用是为需要增强的 Bean 创建代理对象:
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 跳过无需代理的 Bean
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey)) ||
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) {
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;
}
如何识别需要增强的 Bean
wrapIfNecessary
方法调用 getAdvicesAndAdvisorsForBean
确定 Bean 是否需要增强:
@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
return advisors.isEmpty() ? DO_NOT_PROXY : advisors.toArray();
}
// 筛选合适的增强器
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
List<Advisor> candidateAdvisors = findCandidateAdvisors(); // 获取所有增强器
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); // 筛选匹配的增强器
extendAdvisors(eligibleAdvisors); // 扩展点,允许开发者自定义
return eligibleAdvisors.isEmpty() ? eligibleAdvisors : sortAdvisors(eligibleAdvisors); // 排序
}
Spring 通过以下两步完成增强器的匹配:
-
获取增强器候选列表:从 IOC 容器中查找所有
Advisor
的实现类。advisors.add(this.beanFactory.getBean(name, Advisor.class));
-
筛选匹配的增强器:根据目标类和方法进行匹配。
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) { List<Advisor> eligibleAdvisors = new ArrayList<>(); for (Advisor candidate : candidateAdvisors) { if (canApply(candidate, clazz)) { eligibleAdvisors.add(candidate); } } return eligibleAdvisors; }
匹配逻辑中涉及两种增强器:
- IntroductionAdvisor:类级别增强(如为类添加新功能)。
- PointcutAdvisor:方法级别增强(如方法执行前后插入逻辑)。
代理对象的创建
一旦识别到需要增强的 Bean,Spring 开始创建代理对象。
protected Object createProxy(Class<?> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource) {
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass() && shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true); // 使用 CGLIB
} else {
evaluateProxyInterfaces(beanClass, proxyFactory); // 使用 JDK 动态代理
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
return proxyFactory.getProxy(getProxyClassLoader());
}
代理方式的选择:
- JDK 动态代理:针对接口生成代理类。
- CGLIB 动态代理:针对类生成子类代理。
拦截器链的执行
代理对象拦截方法调用后,执行增强器链(Interceptor Chain):
- JDK 代理:通过
invoke
方法实现。 - CGLIB 代理:通过
intercept
方法实现。
以 JDK 动态代理为例:
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
if (chain.isEmpty()) {
return method.invoke(target, args); // 无增强器,直接调用
} else {
MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
return invocation.proceed(); // 调用增强器链
}
}
总结
Spring 的 AOP 实现通过以下步骤完成:
- 识别需要增强的 Bean。
- 查找匹配的增强器。
- 创建代理对象(JDK 或 CGLIB)。
- 执行增强器链。
这一机制使得 Spring 能够灵活地为 Bean 提供切面功能,而开发者无需关注底层的代理实现细节。
🪁🍁 希望本文能够给您带来一定的帮助🌸文章粗浅,敬请批评指正!🍁🐥
如对本文内容有任何疑问、建议或意见,请联系作者,作者将尽力回复并改进📓;(联系微信:Solitudemind )
点击下方名片,加入IT技术核心学习团队。一起探索科技的未来,共同成长。
更多推荐
所有评论(0)