zoukankan      html  css  js  c++  java
  • 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开头的所有方法

  • 相关阅读:
    POJ3693 Maximum repetition substring —— 后缀数组 重复次数最多的连续重复子串
    SPOJ
    POJ2774 Long Long Message —— 后缀数组 两字符串的最长公共子串
    POJ3261 Milk Patterns —— 后缀数组 出现k次且可重叠的最长子串
    POJ1743 Musical Theme —— 后缀数组 重复出现且不重叠的最长子串
    SPOJ
    AC自动机小结
    HDU3247 Resource Archiver —— AC自动机 + BFS最短路 + 状压DP
    POJ1625 Censored! —— AC自动机 + DP + 大数
    Herding
  • 原文地址:https://www.cnblogs.com/wangleBlogs/p/7443509.html
Copyright © 2011-2022 走看看