- [举个栗子给大家讲一下代理:](https://cloud.tencent.com/developer)
Spring框架自诞生之日就拯救我等程序员于水火之中,它有两大法宝,一个是IoC控制反转,另一个便是AOP面向切面编程。今日我们就来破一下它的AOP法宝,以便以后也能自由使出一手AOP大法。
AOP全名Aspect-oriented programming面向切面编程大法,它有很多兄弟,分别是经常见的面向对象编程,朴素的面向过程编程和神秘的函数式编程等。所谓AOP的具体解释,以及和OOP的区别不清楚的同学可以自行去了解。
我相信大家都知道明星吧。
大部分明星是都有经纪人的。
假如我们是一个大厂,现在想要找一个明星代理产品,那我们会直接找到明星吗?不。
现实中,你大部分找到的都是找到明星的代理人(经纪人)。经纪人通过和你约谈,了解产品,看自己的家明星,是否可以接下这个广告。觉得可以,就会和你商量签订合同、商谈活动日期、排练等等。 虽然商家知道自己并没有找到明星,但是他却知道这件事情已经成了。
1、在这个流程中,商家找了明星的经纪人。但是却完成了最初的任务。
2、明星经纪人 帮明星签订合同、订下活动日期等等。
3、明星专注于拍广告。
这个时候我们是不是就可以讲 明星经纪人增强了明星的功能勒?
那么你喜欢哪个明星勒。
与OOP对比,AOP是处理一些横切行问题。这些横切性问题不会影响到主逻辑的实现,但是会散落到代码的各个部分,难以维护。AOP就是把这些问题和主业务逻辑分开,达到与主业务逻辑解耦的目的。
AOP是一种面向切面的编程思想。这些横切性问题,把它们抽象为一个切面,关注点在切面的编程,这就是所谓的AOP。
AOP关注点是横切性问题:
@Aspect
注解注解的常规类 (@AspectJ 风格)实现的。切面是一个横切关注点的模块化,一个切面能够包含同一个类型的不同增强方法,比如说事务处理和日志处理可以理解为两个切面。切面由切入点和通知组成,它既包含了横切逻辑的定义,也包括了切入点的定义。 Spring AOP就是负责实施切面的框架,它将切面所定义的横切逻辑织入到切面所指定的连接点中。
可以简单地认为, 使用 @Aspect 注解的类就是切面
目标对象指将要被增强的对象,即包含主业务逻辑的类对象。或者说是被一个或者多个切面所通知的对象。
程序执行过程中明确的点,如方法的调用或特定的异常被抛出。连接点由两个信息确定:
简单来说,连接点就是被拦截到的程序执行点,因为Spring只支持方法类型的连接点,所以在Spring中连接点就是被拦截到的方法。
讲人话 就是spring允许你使用通知的地方
上面说的连接点的基础上,来定义切入点,你的一个类里,有15个方法,那就有几十个连接点了对把,但是你并不想在所有方法附近都使用通知(使用叫织入,以后再说),你只想让其中的几个,在调用这几个方法之前,之后或者抛出异常时干点什么,那么就用切点来定义这几个方法,让切点来筛选连接点,选中那几个你想要的方法。
@Pointcut("execution(* com.remcarpediem.test.aop.service..*(..))")
public void pointcut() {
}
上边切入点的匹配规则是com.remcarpediem.test.aop.service
包下的所有类的所有函数。
Spring AOP 包括以下类型的通知:
// @Before说明这是一个前置通知,log函数中是要前置执行的代码,JoinPoint是连接点,
@Before("pointcut()")
public void log(JoinPoint joinPoint) {
}
织入是将切面和业务逻辑对象连接起来, 并创建通知代理的过程。织入可以在编译时,类加载时和运行时完成。在编译时进行织入就是静态代理,而在运行时进行织入则是动态代理。
关键就是:切点定义了哪些连接点会得到通知
所谓静态代理就是AOP框架会在编译阶段生成AOP代理类,因此也称为编译时增强。ApsectJ是静态代理的实现之一,也是最为流行的。静态代理由于在编译时就生成了代理类,效率相比动态代理要高一些。AspectJ可以单独使用,也可以和Spring结合使用。
与静态代理不同,动态代理就是说AOP框架不会去修改编译时生成的字节码,而是在运行时在内存中生成一个AOP代理对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。
Spring AOP中的动态代理主要有两种方式:JDK动态代理和CGLIB动态代理。
JDK代理通过反射来处理被代理的类,并且要求被代理类必须实现一个接口。核心类是 InvocationHandler接口 和 Proxy类。
而当目标类没有实现接口时,Spring AOP框架会使用CGLIB来动态代理目标类。
CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成某个类的子类。CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。核心类是 MethodInterceptor 接口和Enhancer 类
又是一天。