美文网首页
4 AOP操作

4 AOP操作

作者: ca8519be679b | 来源:发表于2020-06-15 17:33 被阅读0次

    概念

    面向切面编程。

    可以使业务的各个部分相互隔离,耦合度降低,提高程序可重用性,同时提高开发效率

    1

    视频里老师用一个业务来说明,如上图,比如我们做一个登陆功能,用户输入账号密码,表单提交,数据库查询来判断能否登陆。如果我们想在登陆功能基础上加上权限控制,我们先将权限功能做一个模块,然后将这个模块配置到登陆成功后,这就是AOP

    底层原理

    AOP底层使用的是动态代理,其使用情况分为有接口和没有接口2种情况

    有接口,使用jdk的动态代理

    没有接口,使用CGLIB的动态代理

    2

    有接口情况如上图,我们做了个接口UserDao,实现类UserDaoImpl,有登陆函数,使用JDK动态代理,创建了接口实现类的代理对象来扩展功能

    3

    没有接口情况如实,比如我们定义了一个类User,想要扩展add方法,可能会使用子类继承,然后添加功能,而CGLIB是创建当前类的子类的代理对象

    代码实现动态代理

    使用jdk动态代理,有接口情况,我们需要使用jdk的lang包下的Proxy类的静态方法newProxyInstance

    4

    其3个参数,第一个是类加载器,第二个是传递的接口(字节码数组),可以写多个接口,第三个是创建接口InvocationHandler实现类对象,用于写我们代码功能增强的部分

    了解后,我们来编写代码

    5 6

     首先创建接口和实现类

    7

    然后就是带main接口的使用类,这里我们定义main方法,使用Proxy的刚才讲过的方法,返回代理实例,这里类加载器使用当前类.class.getClassLoader()获取,然后接口数组使用外部定义,对于InvocationHandler实例参数,由于其是接口,我们需要写实现类,其要复写的方法是invoke方法,默认是返回null的,这里Method是当前执行的方法,args是方法执行的参数,我们可以在前后打印内容,但是我们需要调用实现类对象,所以我们定义属性和有参构造,在main方法里将实现类对象传递进来,

    8

    如上,可以看到功能增加了,这里我们只是了解下如何使用jdk增强功能,实际spring是已经给我们封装好了,到时候我们配置就行。当然如果我们执行的是update方法呢,我们可以通过method对象getName来if判断,根据不同参数来做不同的功能增强

    AOP相关术语

    Aop有很多术语,我们着重如下4个:连接点,切入点,通知(增强),切面

    9

    连接点:可以被增强的方法,成为连接点

    切入点:连接点中被增强的部分

    通知:就是增强的代码逻辑,分5种,在前面是前置,后面后置,都有环绕,catch捕获,finally最终执行

    切面:把通知应用到切入点的过程


    AOP操作准备工作

    spring框架中一般基于AspectJ实现AOP操作

    AspectJ是独立于Spring的AOP框架

    基于AspectJ实现AOP操作有2种方式:xml配置,注解,后者经常使用

    导入依赖包

    10

    我们之前的IOC案例,使用的如上的包,已经包含了AOP,这里还需要aspect包

    11

    这个包在spring下面

    12

    还有视频资源的3个aspect依赖包,然后idea设置导入

    切入表达式

    配置前需要学习切入表达式

    作用:知道什么类什么方法被增强

    语法结构:execution([权限修饰符如public等][返回类型][类全路径][方法名称](参数列表) )

    13

    例子如上图,我们对指定类,指定方法增强,我们表达式如上,权限修饰符我们可以写public,这里使用*替代,返回类型可以省略,我们的类名写上,然后方法名之间有.连接,参数列表直接使用..,注意*和后面有空格

    14

    然后还有上面2个例子,如上,我们增强只要是所有即可用*替代

    使用Aspect注解完成AOP操作

    15

    首先,创建被增强类,我们使用注解创建对象

    16

    虽然是使用注解,但是aop还是需要xml配置,这里就还算是加上组件扫描完成注解,使用context:标签,然后记得使用context名称空间配置修改,同样的配置xmlns:aop和网址,配置后使用aop的自动代理标签

    17

    创建增强代理类,由于要生成对象类需要使用@Component注解完成,同时加上@Aspect,实现将我们之前的配置aop增强识别,我们定义方法before,这里要给其加上@Before注解(注意是使用Aspect包下的),里面value就是我们之前说的切入表达式

    18

    最后编写测试文件,由于使用的是bean.xml配置了注解,还是使用ClassPathXmlApplicationContext,可以看到执行效果,如上

    19

    所以聪明的你也想到了在后面加是使用@After(切入表达式),效果如上

    20

    当然除了这2个注解,我们还有3个注解,@AfterReturning  @AfterThrowing @Around,其中,环绕写法是前后增强的,需要使用切入点对象ProceedingJoinPoint类实例,其有proceed()方法,实现控制add此时执行,此方法还要抛出异常。

    21

    执行测试方法,可以看到环绕方法在Before前,after前,但是没有出现异常通知,因为我们没有出现异常

    22

    我们人为制造异常,可以看到运行结果,after被执行了,AfterThrowing也执行,但是没有执行AfterReturning和环绕后,所以@After也叫最终执行

    切入点共性提取

    我们之前定义了那么多通知来增强功能,实际他们都是对一个切入点进行增强,里面都要写比较长的切入表达式(而且还是一样的),其实这是可以共性抽取的

    23

    我们在代理类里建立一个函数,使用注解@Pointcut就是创建切面,这里我们就把之前的切入点表达式添加进去,然后之前的所有时序的注解value值就可以写成双引号内部函数运行结果,如上。运行效果和之前一样

    多增强类增强同一方法设置优先级

    24 25

    我们删掉多余方法只留@Before,复制一份起名UserProxy2,方法执行时设置打印区别

    26

    按默认顺序是先UserProxy再UserProxy2,现在我们想让后者在前怎么办,使用@Order给增强类添加注释,value值越小优先级越高

    27 28

    如上,我们给2设置优先级1,之前的设置2,结果2先运行

    AspectJ使用配置文件实现AOP(仅了解)

    我们之前使用的是通过注解实现aop,这将是大多数情况(推荐),不过配置文件实现增强也是可以的。

    步骤:创建类和增强类,xml创建Bean创建对象,xml配置切入点

    29 30

    首先创建类和增强类如上

    31

    xml文件里还是得有aop名称空间,然后创建2个bean,创建aop配置标签,使用pointcut创建切入点,我们设置id为point,属性expression如上就是切入表达式

    32

    aop配置切入点后,就要配置切面。就是增强函数插入位置,我们idea给出很多提示,相信到这里你已经明白啦

    33

    最后我们设置属性method为函数命名,pointcut-ref为我们的切入点id,运行结果实现before增强

    最终完全注解AOP

    我们之前使用注解AOP操作,其实还是用了xml文件,如图16,里面使用context标签开启扫描,aop设置自动代理对象创建,

    其实是可以只使用注解,一点都不使用aop的

    34

    我们还是文件层级关系,创建配置类,里面@Configuration注解和自动扫描注解

    35

    原始类使用@Component创建实例

    36

    增强类。使用@Aspect创建前面,@Component创建对象@EnableAspectAutoProxy设置自动代理,在这里要给目标类设置true,默认为false

    37

    测试类和结果如上,这里使用的是AnnotationConfig开头的上下文,传入的是配置类的字节码

    相关文章

      网友评论

          本文标题:4 AOP操作

          本文链接:https://www.haomeiwen.com/subject/lsrmtktx.html