大家好,我是被白菜拱的猪。
一个热爱学习废寝忘食头悬梁锥刺股,痴迷于girl的潇洒从容淡然coding handsome boy。
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
通俗的讲就是不改变源代码的方式,在主干功能中添加新的功能,比如我们在实现登录功能时想来一个权限判断,是管理员还是普通用户。
AOP底层采用的是动态代理,什么是代理,就是我们把要做的事情交给比人去做,比如我们要租房子,我们就是被代理对象,中介就是代理对象。
动态代理是利用反射机制创建代理对象,动态代理分为两种:
一种是有接口的情况,我们通过jdk代理方式创建接口实现类的代理对象,实现类的增强方法一种是没有接口的情况,我们通过CGLIB动态代理来创建子类的代理对象,实现类的增强方法。为什么要通过反射呢?因为我们是在运行期间创建代理类,静态代理是是编译时创建,不利于程序的扩展,而且每个代理类只能为一个借口服务,这样在程序开发的过程中就会产生很多个代理类,那么我们最好通过一个代理类实现全部的代理功能。这就是动态代理。
运行结果:
1、连接点 类中哪些方法可以增强,这些方法称为连接点 2、切入点 具体增强的方法称为切入点 3、通知 增强方法中的逻辑部分称为通知。
通知又分为如下几种: 前置通知、后置通知、环绕通知、异常通知、最终通知
4、切面 切面是一个动作,将通知应用于切入点的过程称为切面
AspectJ不是Spring的组成部分,他是一个独立的框架,一般把AspectJ和Spring一起使用来实现AOP的操作,假如不使用maven构建工程的话还要引入相关jar包。
除此之外,还要了解什么是切入点表达式,知道对哪个类里面的哪个类方法进行增强。
切入点表达式格式:execution([修饰符] 返回值类型 包名.类名.方法名(参数)), 修饰符默认为public可以不用写,返回值类型必须写*可以匹配所有的返回值类型。
示例一: 对com.coding.spring5中包中所有的类中的所有方法进行增强(…)是参数列表,不管一个参数还是多个参数
execution( * com.codingboy.spring5.*.*(..))(2)使用注解@Component创建对象(即增强类和要增强的类) (3)在增强类上加上@Aspect注解(注意选择的包是在aspectJ) (4)在Spring配置文件中开启生成代理对象,让@Aspect生效
<!--织入切面--> <aop:aspectj-autoproxy></aop:aspectj-autoproxy>3.在增强类中配置不同的通知,在方法上使用不同的注解,以及切入点表达式来表明对哪个方法进行增强
package com.codingboy.spring5.aopannotation; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; /** * @author: ljl * @date: 2020/9/4 16:35 * @description: book的增强类 */ @Aspect @Component public class BookProxy { //前置通知 @Before(value = "execution(* com.codingboy.spring5.aopannotation.Book.*(..)") public void before() { System.out.println("前置通知 before..."); } //后置通知(返回通知) @AfterReturning(value = "execution(* com.codingboy.spring5.aopannotation.Book.*(..)") public void afterReturning() { System.out.println("后置通知(返回通知) afterReturning"); } //环绕通知 @Around(value = "execution(* com.codingboy.spring5.aopannotation.Book.*(..)") public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { System.out.println("环绕通知前 around..."); //被增强方法执行 proceedingJoinPoint.proceed(); System.out.println("环绕通知后 around..."); } //最终通知 @After(value = "execution(* com.codingboy.spring5.aopannotation.Book.*(..)") public void after() { System.out.println("最终通知 after..."); } //异常通知 @AfterThrowing(value = "execution(* com.codingboy.spring5.aopannotation.Book.*(..)") public void afterThrowing() { System.out.println("异常通知 afterThrowing..."); } }这是一个方法只被一个类拦截时通知执行的顺序 正常执行: 出现异常:
这句话,下面是配置类的内容
@Configuration @ComponentScan(basePackages = {"com.codingboy.spring5"}) @EnableAspectJAutoProxy public class AopConfig { }使用配置文件的形式在实际开发过程中使用的不多,但是还是要有所了解的。这里不再对各个标签进行描述,直接上代码:
<!--创建对象--> <bean id="book" class="com.codingboy.spring5.aopannotation.Book"></bean> <bean id="bookProxy" class="com.codingboy.spring5.aopannotation.BookProxy"></bean> <!--配置aop--> <aop:config> <!--配置切点--> <aop:pointcut id="point" expression="execution(* com.codingboy.spring5.aopannotation.Book.*(..))"/> <!--配置切面 ref 指把哪个类当做切面--> <aop:aspect ref="bookProxy"> <!--配置通知,method指把哪个方法作为通知--> <aop:after method="before" pointcut-ref="point" ></aop:after> </aop:aspect> </aop:config>一天的内容,学了学aop,让我收获最多的是动态代理,看视频看了两遍才搞清楚,学习这条路任重而道远啊,要学的东西是在太多了。以上还仅仅是基础,学完这一篇还要在在了解了解源码,什么时候上SpringBoot这条船还不得而知。
长春的风太大,吹乱了我的秀发…一个人在风中前行,孤独又增添了几分。