• Spring 学习(三)AOP


    (1)AOP概述

      - AOP:面向切面编程,扩展功能不修改源代码实现

      - AOP采取横向抽取机制,取代了传统的纵向继承体系重复性代码

    (2)AOP底层原理

      原始方法-------》纵向继承体系

          

      横向机制:

    JDK代理机制:jdk动态代理是由Java内部的反射机制来实现的.jdk动态代理的应用前提,必须是目标类基于统一的接口。如果没有上述前提,jdk动态代理不能应用。

    CGlib代理机制:Cglib的原理是对指定的目标类动态生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类和final方法进行代理。

           

     

    (3)AOP操作相关术语(重点切入点、增强、切面)

    spring的AOP操作(基于aspectj的XML方式)

    Joinpoint   连接点:类里面可以被增强的方法,这些方法称为连接点

    Pointcut     切入点:在类里面可以有很多的方法被增强,但是在实际的操作中值只是增强了add()和update(),则这两个实际增强的方法称为切入点

    Advice      通知/增强:实际增强的逻辑,称为增强,例如扩展日志的功能,这个日志功能称为增强

          分为:

                      (1)前置通知:在方法之前执行

           (2)后置通知:在方法之后执行

           (3)异常通知:方法出现异常

           (4)最终通知:在后置之后执行

           (5)环绕通知:在方法之前和方法之后都执行,例如获取执行时间

     Aspect      切面:把我们的Advice增强应用到具体的Pointcut切入点方法上面,这个过程称为切面

    Introduction  引介 :是一种特殊的增强,它为类添加一些属性和方法。这样,即使一个业务类原本没有实现某个接口,通过AOP的引介功能,我们可以动态地为该业务类添加接口的实现逻辑,让业务类成为这个接口的实现类。

    Target        目标对象增强逻辑的织入目标类。如果没有AOP,目标业务类需要自己实现所有逻辑,而在AOP的帮助下,目标业务类只实现那些非横切逻辑的程序逻辑,而性能监视和事务管理等这些横切逻辑则可以使用AOP动态织入到特定的连接点上。
    Weaving   织入织入是将Advice增强添加对target目标类具体连接点上的过程。AOP像一台织布机,将目标类、增强或引介通过AOP这台织布机天衣无缝地编织到一起。根据不同的实现技术,AOP有三种织入的方式:
        a、编译期织入,这要求使用特殊的Java编译器。
        b、类装载期织入,这要求使用特殊的类装载器。
        c、动态代理织入,在运行期为目标类添加增强生成子类的方式。
        Spring采用动态代理织入,而AspectJ采用编译期织入和类装载期织入。

    proxy        代理:一个类被AOP织入增强后,就产出了一个结果类,它是融合了原类和增强逻辑的代理类。根据不同的代理方式,代理类既可能是和原类具有相同接口的类,也可能就是原类的子类,所以我们可以采用调用原类相同的方式调用代理类。

    (4)Spring的AOP操作

    1、在spring里面进行AOP操作,使用 AspecJ  实现

      AspectJ:面向切面的框架,它扩展了JAVA语言,是一个基于JAVA语言的AOP框架

      - (1)aspectj不是spring的一部分,和spring一起使用进行AOP操作

      - (2)Spring2.0之后新增加了对 aspectj 支持

    2、使用AspectJ 方式实现AOP操作有两种方式

      - (1)基于AspectJ 的xml配置

    Book类:

    package cn.itcast.aop;
    
    public class Book {
        public void add(){
            System.out.println("add book......");
        }
        
    }

    MyBook类:增强类对象

    package cn.itcast.aop;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    
    //增强类
    public class MyBook {
         public void befoer1(){
             System.out.println("前置before1......");
         }
         public void after1(){
             System.out.println("后置after1......");
         }
         //环绕通知
         public void around1(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
             //在方法之前执行
             System.out.println("方法之前执行.....");
             
             //执行被增强的方法
             proceedingJoinPoint.proceed();
             
             //在方法之后执行
             System.out.println("方法之后执行....");
         }
    }

    AspectJ 的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:aop="http://www.springframework.org/schema/aop"
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- bean definitions here -->
    
        <!--1、 配置对象 -->
        <bean id="book" class="cn.itcast.aop.Book"></bean>
        <bean id="myBook" class="cn.itcast.aop.MyBook"></bean>
        <!-- 2、配置AOP操作 -->
        <aop:config>
            <!-- 2.1 配置切入点 -->
            <aop:pointcut expression="execution(* cn.itcast.aop.Book.add(..))" id="pointcut1"/>
            <!-- 2.2配置切面 :把增强用到方法上面 -->
            <aop:aspect ref="myBook">
                <!-- 配置增强类型 :method:增强的类里面,使用哪个方法作为前置增强-->
                <aop:before method="befoer1" pointcut-ref="pointcut1"/>
                <aop:after-returning method="after1" pointcut-ref="pointcut1"/>
                <aop:around method="around1" pointcut-ref="pointcut1"/>
                
            </aop:aspect>
        </aop:config>
    </beans>

    测试代码:

        public static void main(String[] args) {
            ApplicationContext context=new ClassPathXmlApplicationContext("aopbeans.xml");
            Book book=(Book)context.getBean("book");
            book.add();
        }

    结果:

    前置before1......
    方法之前执行.....
    add book......
    方法之后执行....
    后置after1......

     - (2)基于aspectj 的注解方式

        - 第一步:在配置文件中设置对象

    <bean id="book" class="cn.sdust.aop.Book"></bean>
    <bean id="myBook" class="cn.sdust.aop.MyBook"></bean>

        - 第二步:开启aop操作

        <!-- 开启aop操作 -->
        <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

        - 第三步:在增强类上面使用注解完成AOP操作

    Book类

    package cn.sdust.aop;
    
    public class Book {
    
        public void add(){
            System.out.println("add book.....");
        }
    }

    MyBook类

    package cn.sdust.aop;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    
    @Aspect
    public class MyBook {
        //在方法上面使用注解完成增强配置
        @Before(value="execution(* cn.sdust.aop.Book.*(..))")
        public void before(){
            System.out.println("before......");
        }
        @AfterReturning(value="execution(* cn.sdust.aop.Book.*(..))")
        public void after(){
            System.out.println("after......");
        }
        @Around(value="execution(* cn.sdust.aop.Book.*(..))")
        public void round(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
            System.out.println("round--before....");
            proceedingJoinPoint.proceed();
            System.out.println("round--after....");
        }
    }

    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:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- bean definitions here -->
        
        <!-- 开启aop操作 -->
        <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
        <!-- 创建对象 -->
        <bean id="book" class="cn.sdust.aop.Book"></bean>
        <bean id="myBook" class="cn.sdust.aop.MyBook"></bean>
    </beans>

     测试代码 

        @Test
        public void testaop(){
            ApplicationContext context=new ClassPathXmlApplicationContext("aop.xml");
            Book book=(Book) context.getBean("book");
            book.add();
        }

     运行结果

    round--before....
    before......
    add book.....
    round--after....
    after......

    AOP 操作准备:

    1、jar包

      - 基本jar包

      

      - aspectj 的jar 包

      

     2、xml中的约束有beans、context、aop

    <?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:aop="http://www.springframework.org/schema/aop"
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- bean definitions here -->
    
    </beans>

    使用表达式配置切入点

      1、切入点:实际增强的方法

      2、常用表达式

      execution (<访问修饰符>?<返回类型><方法名>(<参数>)<异常>)

      (1)execution (* com.skd.aop.Book.add(..))//其中的(1)*表示修饰符(2)..表示如果有参数,也包括

      (2)execution (* com.skd.aop.Book.*(..)) //Book/类的所有方法

      (3)execution (* *.*(..))//所有类的所有方法

      (4)execution (* save*(..)) //匹配save开头的所有方法

  • 相关阅读:
    用数据泵技术实现逻辑备份Oracle 11g R2 数据泵技术详解(expdp impdp)
    用mysql实现类似于oracle dblink的功能
    统计1的个数
    转置字符串,其中单词内的字符需要正常
    经典排序之归并排序
    公共子序列与公共子串问题
    placement new (转)
    数组排序组合最小数字
    实现两个数相加不用四则运算
    操作系统中作业、线程、进程、内存管理、垃圾回收以及缓存等概念
  • 原文地址:https://www.cnblogs.com/wangleBlogs/p/7443509.html
Copyright © 2020-2023  润新知