zoukankan      html  css  js  c++  java
  • Spring学习之第一个AOP程序

     IOC和AOP是Spring的两大基石,AOP(面向方面编程),也可称为面向切面编程,是一种编程范式,提供从另一个角度来考虑程序结构从而完善面向对象编程(OOP)。

      在进行 OOP 开发时,都是基于对组件(比如类)进行开发,然后对组件进行组合,OOP 最大问题就是无法解耦组件进行开发,比如我们上边举例,而 AOP 就是为了克服这个问题而出现的,它来进行这种耦合的分离。AOP 为开发者提供一种进行横切关注点(比如日志关注点)分离并织入的机制,把横切关注点分离,然后通过某种技术织入到系统中,从而无耦合的完成了我们的功能。

    1、AOP基本概念

    • 连接点( Jointpoint) : 表示需要在程序中插入横切关注点的扩展点,连接点可能是类初始化、方法执行、 方法调用、字段调用或处理异常等等, Spring 只支持方法执行连接点, 在 AOP 中表示为“在哪里干” ;
    • 切入点( Pointcut) : 选择一组相关连接点的模式, 即可以认为连接点的集合,Spring 支持 perl5 正则表达式和 AspectJ 切入点模式, Spring 默认使用 AspectJ 语法, 在 AOP 中表示为“在哪里干的集合” ;
    • 通知( Advice) : 在连接点上执行的行为, 通知提供了在 AOP 中需要在切入点所选择的连接点处进行扩展现有行为的手段; 包括前置通知( before advice)、后置通知(after advice)、环绕通知( around advice), 在 Spring 中通过代理模式实现AOP,并通过拦截器模式以环绕连接点的拦截器链织入通知; 在 AOP 中表示为“干什么”;
    • 方面/切面( Aspect): 横切关注点的模块化,可以认为是通知、引入和切入点的组合; 在 Spring 中可以使用 Schema 和@AspectJ 方式进行组织实现; 在 AOP 中表示为“在哪干和干什么集合” ;
    • 引入( inter-type declaration) : 也称为内部类型声明, 为已有的类添加额外新的字段或方法, Spring 允许引入新的接口(必须对应一个实现)到所有被代理对象(目标对象) , 在 AOP 中表示为“干什么(引入什么) ” ;
    • 目标对象( Target Object) : 需要被织入横切关注点的对象,即该对象是切入点选择的对象,需要被通知的对象,从而也可称为“被通知对象”;由于 Spring AOP通过代理模式实现,从而这个对象永远是被代理对象, 在 AOP 中表示为“对谁干” ;
    • AOP 代理( AOP Proxy) : AOP 框架使用代理模式创建的对象,从而实现在连接点处插入通知(即应用切面) ,就是通过代理来对目标对象应用切面。在 Spring中, AOP 代理可以用 JDK 动态代理或 CGLIB 代理实现,而通过拦截器模型应用切面。
    • 织入( Weaving) : 织入是一个过程,是将切面应用到目标对象从而创建出 AOP代理对象的过程, 织入可以在编译期、类装载期、运行期进行。

     Spring有哪些通知类型呢?

    • 前置通知( Before Advice) :在切入点选择的连接点处的方法之前执行的通知,该通知不影响正常程序执行流程(除非该通知抛出异常,该异常将中断当前方法链的执行而返回)。
    • 后置通知( After Advice) : 在切入点选择的连接点处的方法之后执行的通知,包括如下类型的后置通知:
      • 后置返回通知( After returning Advice) :在切入点选择的连接点处的方法正常执行完毕时执行的通知, 必须是连接点处的方法没抛出任何异常正常返回时才调用后置通知。
      • 后置异常通知( After throwing Advice) : 在切入点选择的连接点处的方法抛出异常返回时执行的通知, 必须是连接点处的方法抛出任何异常返回时才调用异常通知。
      • 后置最终通知( After finally Advice) : 在切入点选择的连接点处的方法返回时执行的通知,不管抛没抛出异常都执行,类似于 Java 中的 finally 块。
    • 环绕通知( Around Advices): 环绕着在切入点选择的连接点处的方法所执行的通知,环绕通知可以在方法调用之前和之后自定义任何行为,并且可以决定是否执行连接点处的方法、替换返回值、抛出异常等等。

      在 AOP 中,通过切入点选择目标对象的连接点,然后在目标对象的相应连接点处织入通知,而切入点和通知就是切面(横切关注点),而在目标对象连接点处应用切面的实现方式是通过 AOP 代理对象,如图所示。

     2、AOP的HelloWorld程序

      AOP代理就是 AOP框架通过代理模式创建的对象,Spring使用 JDK动态代理或 CGLIB代理来实现, Spring 缺省使用 JDK 动态代理来实现,从而任何接口都可被代理,如果被代理的对象实现不是接口将默认使用 CGLIB 代理,不过 CGLIB 代理当然也可应用到接口。AOP 代理的目的就是将切面织入到目标对象。

      新建工程,导入Spring中对应的包,最后引入的jar包如下所示(有些包spring的lib下没有,需要另外下载):

    (1)定义目标接口

    package com.log;
    
    public interface IHelloWorldService {
        public void sayHello();
    }

    (2)定义目标接口实现类

    复制代码
    package com.log;
    
    public class HelloWorldService implements IHelloWorldService {
        @Override
        public void sayHello() {
            System.out.println("---hello world---");
        }
    }
    复制代码

    (3)定义切面支持类

    复制代码
    package com.log;
    
    public class HelloWorldAspect {
        public void beforeAdvice() {
            System.out.println("---before advice---");
        }
        
        public void afterAdvice() {
            System.out.println("---after advice---");
        }
    }
    复制代码

    (4)在XML中进行配置

    复制代码
    <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-2.0.xsd
                http://www.springframework.org/schema/aop
                http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
    
        <!-- 配置目标类 -->
        <bean id="helloWorldService" class="com.log.HelloWorldService"/>
        <!-- 配置切面 -->
        <bean id="aspect" class="com.log.HelloWorldAspect"/>
        <aop:config>
            <aop:pointcut id="pointcut" expression="execution(* com.log..*.*(..))"/>
            <!-- aop:aspect的ref引用切面支持类的方法 -->
            <aop:aspect ref="aspect">
                <aop:before pointcut-ref="pointcut"
                    method="beforeAdvice"/>
                <aop:after pointcut-ref="pointcut"
                    method="afterAdvice"/>
            </aop:aspect>
        </aop:config>
    </beans>
    复制代码

      切入点使用<aop:config>标签下的<aop:pointcut>配置, expression属性用于定义切入点模式,默认是AspectJ语法,“ execution(* cn.javass..*.*(..))”表示匹配cn.javass包及子包下的任何方法执行。关于expression属性如何配置请点击:expression配置

      切面使用<aop:config>标签下的<aop:aspect>标签配置,其中“ ref”用来引用切面支持类的方法。
      前置通知使用<aop:aspect>标签下的<aop:before>标签来定义, pointcut-ref属性用于引用切入点Bean, 而method用来引用切面通知实现类中的方法,该方法就是通知实现,即在目标类方法执行之前调用的方法。
      最终通知使用<aop:aspect>标签下的<aop:after >标签来定义,切入点除了使用pointcut-ref属性来引用已经存在的切入点,也可以使用pointcut属性来定义,如pointcut="execution(* cn.javass..*.*(..))", method属性同样是指定通知实现,即在目标类方法执行之后调用的方法。

    (5)测试运行

    复制代码
    package com.log;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class AopTest {
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("aopBean.xml");
            IHelloWorldService hello = context.getBean("helloWorldService", IHelloWorldService.class);
            hello.sayHello();
            
            HelloWorldAspect advice = context.getBean("aspect", HelloWorldAspect.class);
            advice.beforeAdvice();
        }
    }
    复制代码

    (6)输出结果

     

  • 相关阅读:
    飞入飞出效果
    【JSOI 2008】星球大战 Starwar
    POJ 1094 Sorting It All Out
    POJ 2728 Desert King
    【ZJOI 2008】树的统计 Count
    【SCOI 2009】生日快乐
    POJ 3580 SuperMemo
    POJ 1639 Picnic Planning
    POJ 2976 Dropping Tests
    SPOJ QTREE
  • 原文地址:https://www.cnblogs.com/zhengxingpeng/p/6664484.html
Copyright © 2011-2022 走看看