zoukankan      html  css  js  c++  java
  • Spring的AOP特性

    一、AOP简介

       AOP是Aspect-Oriented Programming的缩写,即面向切面编程。利用oop思想,可以很好的处理业务流程,但是不能把系统中某些特定的重复性行为封装到模块中。例如,在很多业务中都需要记录操作日志,结果我们不得不在业务流程中嵌入大量的日志记录代码。无论是对业务代码还是对日志记录代码来说,维护都是相当复杂的。由于系统中嵌入了这种大量的与业务无关的其他重复性代码,系统的复杂性、代码的重复性增加了。维护起来会更加复杂。

       AOP可以很好解决这个问题,AOP关注的是系统的“截面”,在适当的时候“拦截”程序的执行流程,把程序的预处理和后期处理交给某个拦截器来完成。比如,访问数据库时需要记录日志,如果使用AOP的编程思想,那么在处理业务流程时不必在去考虑记录日志,而是把它交给一个专门的例子记录模块去完成。这样,程序员就可以集中精力去处理业务流程,而不是在实现业务代码时嵌入日志记录代码,实现业务代码与非业务代码的分别维护。在AOP术语中,这称为关注点分离。AOP的常见应用有日志拦截、授权认证、数据库的事务拦截和数据审计等。

    二、AOP优点

      当一个方法,对不同的用户的功能要求不满足时,那么需要在此方法的地方就可以出现变化;在这个变化点进行封转,留下一个可扩展的接口,便于后期的维护;

    三、AOP专业名词

    (1)通知(增强)Advice

      通知定义了切面是什么以及何时使用,应该应用在某个方法被调用之前?之后?还是抛出异常时?等等。

    (2)连接点 Join point

      连接点是在应用执行过程中能够插入切面的一个点。这个点可以是调用方法时,抛出异常时,甚至修改一个字段时。切面代码可以利用这些点插入到应用的正常流程中,并添加新的行为。

    (3)切点 Pointcut

      切点有助于缩小切面所通知的连接点的范围。如果说通知定义了切面的“什么”和“何时”的话,那么切点就定义了“何处”,切点会匹配通知所要织入的一个或多个连接点,一般常用正则表达式定义所匹配的类和方法名称来指定这些切点。

    (4)切面 Aspect

      切面是通知和切点的结合。通知和切点定义了切面的全部内容——它是什么,在何时何处完成其功能。

    (5)引入 Introduction

      引入允许我们向现有的类添加新方法或属性,从而无需修改这些现有类的情况下,让他们具有新的行为和状态。

    (6)织入 Weaving

      在过去我常常把织入与引入的概念混淆,我是这样来辨别的,“引入”我把它看做是一个定义,也就是一个名词,而“织入”我把它看做是一个动作,一个动词,也就是切面在指定的连接点被织入到目标对象中。

    四、注解方式实现AOP

      1、C包下在resources文件夹中创建application2.xml文件,具体内容如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:p="http://www.springframework.org/schema/p"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:jee="http://www.springframework.org/schema/jee"
    
           xsi:schemaLocation="
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
            http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.0.xsd
           ">
    <context:component-scan base-package="com.zxc.C">
        <context:include-filter type="annotation" expression="org.aspectj.lang.annotation.Aspect"/>
    </context:component-scan>
        <aop:aspectj-autoproxy/>
    </beans>
    <context:component-scan base-package="com.zxc.C">用来自动扫描com.zxc.C包中带有@component注解的bean类,然后将其加载到内存中。
    <context:include-filter type="annotation" expression="org.aspectj.lang.annotation.Aspect"/>  这是aspect切面包的位置。
    <aop:aspectj-autoproxy/>用来启用Spring对@Aspect切面配置的支持。

      2、在java类下创建Chinese类,如下:

      这个就是测试用的业务代码,@Componet代表这是个javabean,有xml配置后,自动扫描装载。

    package com.zxc.C;
    import org.springframework.stereotype.Component;
    @Component
    public class Chinese{
        public String say(String name){
            //int a=1/0;用来测试异常增强的
            System.out.println("主方法");
            System.out.println(name);
            return "返回值";
        }
    }

      3、在java类下创建Test类,用来测试代码:

    package com.zxc.C;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    public class Test {
        public static void main(String[] args) {
            ApplicationContext ctx=new ClassPathXmlApplicationContext("application2.xml");
            Chinese chinese=(Chinese)ctx.getBean("chinese");
            chinese.say("环绕增强测试");
        }
    }

    Application用来生成IoC容器,装载application2.xml配置文件,之后通过getBean方法来反射创建一个chinese的对象,在调用其核心业务方法say,say的内容是随意写的。

      4、在java类下创建切面类MyAspect类

      

    package com.zxc.C;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.*;
    @Aspect
    public class MyAspect {
        @Before("execution(* com.zxc.C.*.say*(..))")
        public void ok(){
            System.out.println("前置增强");
        }
    
        @After("execution(* com.zxc.C.*.say*(..))")
        public void ok1(){
            System.out.println("后置增强");
        }
    
        @AfterReturning(pointcut = "execution(* com.zxc.C.*.say*(..))",returning ="myreturn" )
        public void ok2(Object myreturn){
            System.out.println(myreturn+"返回增强");
        }
    
    //    @AfterThrowing(pointcut ="execution(* com.zxc.C.*.say*(..))",throwing = "myerror")
    //    public void ok3(Throwable myerror){
    //        System.out.println(myerror+"返回增强");
    //    }
    
        @Around("execution(* com.zxc.C.*.say*(..))")
        public void ok4(ProceedingJoinPoint pjp){
            try {
                System.out.println("环绕点前");
                Object[] objects=pjp.getArgs();
                objects[0]=objects[0]+"环绕增强方法";
                System.out.println(pjp.proceed(objects));
                System.out.println("环绕点后");
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }
        }
    
    }  

      a、增强类型有:前置增强Before、后置增强After、环绕增强Around、异常后增强AfterThrowing、返回增强AfterReturning:用在关注点方法前

        优先级:(可以加上@order(num)来标注优先级,数越小优先级越高,1最小)环绕前增强>前置增强>异常增强>返回增强>环绕后增强>后置增强

      b、其中环绕增强需要在方法形参上加上形参:ProceedingJoinPoint pjp表示可在切面分钟执行的连接点,在关注点方法中,加入pjp.proceed()方法,可以运行业务方法。

        而在异常增强中需要加上形参Throwable error,用来将业务代码中的错误传到关注点方法中。

      c、切点的书写规则:(在异常后增强和返回增强中都要加上pointcut)

    AspectJ切点指示器

       d、在切面类上要记得加注解@Abstrct,表示这是个切面。

       e、jointpoint中的几个常用方法

  • 相关阅读:
    https://www.cnblogs.com/marost/p/4668664.html
    UEFI 坑 Ubuntu
    Spring《六》管理Bean
    Spring《五》集合的注入方式
    Spring《四-一》解决自动装配的问题
    spring《四》自动装配
    Spring《三》ref 引用其他bean
    Spring《二》 Bean的生命周期
    Spring《一》
    Fragment间相互调用并传值
  • 原文地址:https://www.cnblogs.com/television/p/8724507.html
Copyright © 2011-2022 走看看