作为spring核心思想之一的AOP,网络上关于此的博客数不胜数,大多都是通过源码流程解析,源码分析本篇就不再提起,直接生动形象的说说我的通俗易懂理解。
- AOP就是面向切面编程,目的是让你的业务逻辑去关注自己本身的业务,而不去想一些其他的事情,这些其他的事情包括:安全,事物,日志等。
- Spring AOP 就是负责实施切面的框架,它将切面所定义的横切逻辑编织到切面所指定的连接点中。
- 实现 AOP 的技术主要为代理模式
- 静态代理:通过aop的接口实现,编译阶段就可生成 AOP 代理类,因此也称为编译时增强。
- 动态代理:通过反射在运行时在内存中“临时”生成 AOP 动态代理类,因此也被称为运行时增强。
- spring AOP使用的是动态代理,有两种:JDK动态代理 和 CGLIB
- JDK 动态代理
- 通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口。JDK动态代理的核心是 java.lang.reflect.Proxy类。
- 通俗理解:实现和目标类相同的接口,伪装成了和目标类一样的类(实现了同一接口,咱是兄弟了),也就逃过了类型检查,到java运行期的时候,利用多态的后期绑定(所以spring采用运行时),伪装类(代理类)就变成了接口的真正实现,代理类后来还是会把业务具体方法让目标类实现,只不过在这之前自己就处理好了其他事情(写日志,安全检查,事务等)。
- CGLIB动态代理
- 如果目标类没有实现接口,那么 Spring AOP 会选择使用 CGLIB 来动态代理目标类。
- CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成某个类的子类,注意,CGLIB 是通过继承的方式做的动态代理,因此如果某个类被标记为 final ,那么它是无法使用 CGLIB 做动态代理的。
- 通俗理解:如果目标类就没实现某一接口呢,那jdk代理还怎么伪装!我就压根没有机会让你搞出这个长的一样的兄弟,那么就用第2种代理方式,创建一个目标类的子类,生个儿子,让儿子伪装我。spring使用CGLIB库生成目标类的一个子类,spring织入通知,并且把对这个子类的调用委托到目标类,在这之前子类还会实现目标类不关心的方法(写日志,安全检查,事务等)。而final就像目标类的孤独,拒绝生后代,此时自然不能使用CGLIB了。
- JDK 动态代理