spring aop代码的增强
这篇博客,主要会分析spring aop是如何实现代码增强的。
从上一篇博客 我们大概知道,spring能在不改变代码的前提下,往一个方法的之前和之后添加代码。
想下,java中有哪种技术可以帮我们实现动态修改代码呢?就是jdk的动态代理。关于动态代理可以看下这篇博客jdk动态代理与cglib动态代理实现原理
大体我们先知道,jdk动态代理和cglib的动态代理都可以在运行时修改源码。两者之间的基本区别之一是,jdk动态代理需要被代理的类实现接口,cglib不需要。
然后我们开始分析spring是如何使用动态代理的。
回到spring调用链的图,spring 对于aop的增强是在创建bean时,通过BeanPostProcessor机制来实现的。在spring初始化之后类后,会有一次对类增强的机会。就是在AbstractAutoProxyCreator里。
AbstractAutoProxyCreator.postProcessAfterInitialization
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (bean != null) {Object cacheKey = getCacheKey(bean.getClass(), beanName);if (!this.earlyProxyReferences.contains(cacheKey)) {return wrapIfNecessary(bean, beanName, cacheKey);}}return bean;
}
这里就是检查下该类是否已经暴露过了
(可能已经创建了,比如A依赖B时,创建A时候,就会先去创建B。当真正需要创建B时,就没必要再代理一次已经代理过的对象)
wrapIfNecessary
真正创建代理对象的地方就在wrapIfNecessary
依旧我们先来看最关键的一步,createProxy
protected Object createProxy(Class<?> beanClass, String beanName, 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()) {if (shouldProxyTargetClass(beanClass, beanName)) {proxyFactory.setProxyTargetClass(true);}else {evaluateProxyInterfaces(beanClass, proxyFactory);}}Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);for (Advisor advisor : advisors) {proxyFactory.addAdvisor(advisor);}proxyFactory.setTargetSource(targetSource);customizeProxyFactory(proxyFactory);proxyFactory.setFrozen(this.freezeProxy);if (advisorsPreFiltered()) {proxyFactory.setPreFiltered(true);}//获取代理对象return proxyFactory.getProxy(getProxyClassLoader());
}
createProxy也很长,依旧我们只关心最重要的也就是最后一行,proxyFactory.getProxy
整理了一个流程图
大概说明下:
1)代理对象的创建最终委托给AopProxy生成
2)AopProxy的创建交由AopProxyFactory工厂
3)AopProxyFactory的默认实现是DefaultAopProxyFactory
AopProxyFactory.createAopProxy
那么我们先来看看AopProxy究竟是如何创建的。
我们首先可以看出,最后生成的AopProxy底层实现要么是cglib的,要么是jdk。再然后,我们分析下,什么时候使用jdk动态代理,什么时候使用cglib的。
1)配置了optimize。由于 cglib的动态代理创建类比较慢,但是执行代码比较快,jdk动态代理相反,创建比较快,执行比较慢。如果配置了optimize=true,那么目标类实现了接口就使用jdk代理,否则就用cglib。默认是false。
2)proxyTargetClass 是否强制使用cglib实现代理。默认是false
3)没有可代理的接口
代理对象的生成
到了这里,我们继续分析AopProxy如何生成代理对象(这里以jdk动态代理来分析)
看到Proxy.newProxyInstance就非常熟悉了,jdk的动态代理。
总结及待续
这篇博客大致分析了下,spring是如何创建代理对象的。jdk及cglib代理方式的选择。以及大概看了下jdk代理对象的创建。
当然还是留了很多问题,首先就是wrapIfNecessary里的各种缓存究竟是干啥用的,再然后就是jdk代理里,非常核心的InvocationHandler.invoke方法是如何实现的。再然后,我们常说的,切面,通知这些概念在源码层究竟对应着啥。这些问题会再下一篇博客介绍。
spring aop代码的增强相关推荐
- Spring AOP代码实现:实例演示与注解全解
1 理解AOP 1.1 什么是AOP AOP(Aspect Oriented Programming),面向切面思想,是Spring的三大核心思想之一(两外两个:IOC-控制反转.DI-依赖注入). ...
- Spring : Spring AOP 中的增强(Advice)或者通知
1.美图 2.概述 概念参考:Spring :Spring AOP 中的一些术语 很多人将增强理解为通知,但是理解为增强会更加准确,因为它表示在连接点上执行的行为,这个行为是目标类类所没有的,是为目标 ...
- 在Intellij上面导入项目 AOP示例项目 AspectJ学习 Spring AoP学习
为了学习这篇文章里面下载的代码:http://www.cnblogs.com/charlesblc/p/6083687.html 需要用Intellij导入一个已有工程.源文件原始内容也可见:link ...
- 从AOP到Spring AOP
文章目录 一.前言 二.AOP基础知识 2.1 AOP 2.1.1 引子:AOP,AOP是什么? 2.1.2 使用对比的方式理解AOP--AOP与OOP 2.1.3 使用对比的方式理解AOP--静态A ...
- java after方法_spring AOP的After增强实现方法实例分析
本文实例讲述了spring AOP的After增强实现方法.分享给大家供大家参考,具体如下: 一 配置 xmlns:xsi="http://www.w3.org/2001/XMLSchema ...
- 哪些方法不能够实施Spring AOP事务
2019独角兽企业重金招聘Python工程师标准>>> 哪些方法不能够实施Spring AOP事务 由于Spring事务管理是基于接口代理或动态字节码技术.通过AOP实施事务增强. ...
- Spring AOP之HelloWorld与概念介绍(xml版)
Spring AOP之HelloWorld与概念介绍 什么是AOP Spring AOP代码实现 Spring AOP 基本概念介绍 目标类 连接点 切入点 切面 切面类 通知 通知类别 织入 什么是 ...
- 简单六步上手spring aop,通过各种类型通知,面向切面编程,实现代码解耦(超详细)
aop(面向切面编程)是一种重要的编程思想,是对面向对象编程的完善和补充.我们都很熟悉"高内聚,低耦合",这是评判代码是否优质的标准之一,而aop思想,就是对这一标准的具体实现. ...
- Spring AOP实现声明式事务代码分析
众所周知,Spring的声明式事务是利用AOP手段实现的,所谓"深入一点,你会更快乐",本文试图给出相关代码分析. AOP联盟为增强定义了org.aopalliance.aop.A ...
最新文章
- (五)Oracle学习笔记—— 视图
- MySQL工作笔记-建表时为Float型数据确定精度,查询时精度显示,多列之和查询
- Linux运维之道之ENGINEER1.3(配置SMB共享,配置NFS共享)
- dmol3给定关键字不在字典中_Materials Studio自学系列——软件安装常见问题及解决方法...
- Chrome 谷歌浏览器 google 复制网页上禁止复制的文本
- mysql 5.7.20免安装_Windows下MySQL 5.7.20 免安装版配置
- 接收邮件服务器(pop3,邮件接收(POP3或IMAP)服务器是什么
- 李煜 天涯 青砚1989
- L13过拟合欠拟合及其解决方案
- ESP8266 驱动1.3寸SH1106 OLED屏幕显示库
- 算法设计与分析基础 第一章谜题
- HDFS、Ceph文件系统以及Hbase、Cassendra、TiDB比较
- 移动端车牌识别:新能源车牌识别上线
- 【官方文档】Fluent Bit 概念
- 推荐12个优质技术公众号!
- 数学文化 卢卡斯数列和黄金分割
- 网络(十三)之ACL的高级应用
- Codeforces 545D - Queue
- 会计 复式记账 财务会计 系统设计 数据库建模(待翻译)
- Stm32的GPIO PB10 驱动固态继电器