zoukankan      html  css  js  c++  java
  • JavaEE——Spring4--(7)Spring AOP 面向切面编程

    切面(Aspect): 横切关注点(跨越应用程序多个模块的功能)被模块化的特殊对象
    通知(Advice): 切面必须要完成的工作
    目标(Target): 被通知的对象
    代理(Proxy): 向目标对象应用通知之后创建的对象
    连接点(Joinpoint):程序执行的某个特定位置:如类某个方法调用前、调用后、方法抛出异常后等。连接点由两个信息确定:方法表示的程序执行点相对点表示的方位。例如 ArithmethicCalculator#add() 方法执行前的连接点,执行点为 ArithmethicCalculator#add(); 方位为该方法执行前的位置
    切点(pointcut):每个类都拥有多个连接点:例如 ArithmethicCalculator 的所有方法实际上都是连接点,即连接点是程序类中客观存在的事务。AOP 通过切点定位到特定的连接点。类比:连接点相当于数据库中的记录,切点相当于查询条件。切点和连接点不是一对一的关系,一个切点匹配多个连接点,切点通过 org.springframework.aop.Pointcut 接口进行描述,它使用类和方法作为连接点的查询条件。

    编写SpringAOP  

    一、基于注解方式配置AOP

      基于 AspectJ 注解或基于 XML 配置的 AOP

    1.加入jar包

    2.在配置文件中加入AOP的命名空间

    3.基于注解的方式

    AspectJ 支持 5 种类型的通知注解:
    @Before: 前置通知, 在方法执行之前执行
    @After: 后置通知, 在方法执行之后执行  无论该方法是否异常
    @AfterRunning: 返回通知, 在方法返回结果之后执行
    @AfterThrowing: 异常通知, 在方法抛出异常之后
    @Around: 环绕通知, 围绕着方法执行

     i 声明一个方法

    ii   在方法前加入@Before注解

     ④访问当前连接点的细节

       可以在通知方法中声明一个类型为 JoinPoint 的参数. 然后就能访问链接细节. 如方法名称和参数值.

    //日志切面
    //把这个类声明为一个切面:需要把该类放入IOC容器中
    @Component
    //再声明为一个切面
    @Aspect
    public class LoggingAspect {
    
    
        //声明该方法是一个前置通知:在目标执行之前执行
        @Before("execution(public int aop.ArithmeticCalculator.*(int, int))")
        public void befordMethod(JoinPoint joinPoint){
            String methodName = joinPoint.getSignature().getName();
            List<Object> args = Arrays.asList(joinPoint.getArgs());
            System.out.println("The method " + methodName + " begins with: " + args);
        }
    
    }
    

      后置通知

    //后置通知:在方法执行之后执行,无论该方法是否出现异常
        @After("execution(public int aop.ArithmeticCalculator.*(int, int))")
        public void afterMethod(JoinPoint joinPoint){
            String methodName = joinPoint.getSignature().getName();
            System.out.println("The method " + methodName + " ends");
        }
    

      返回通知

    //在方法正常结束时执行的代码,返回通知是可以访问到返回值的
        @AfterReturning(value="execution(public int aop.ArithmeticCalculator.*(..))", returning="result")
        public void afterReturning(JoinPoint joinPoint, Object result){
            String methodName = joinPoint.getSignature().getName();
            System.out.println("The method " + methodName + " ends with " + result);
        }
    

      异常通知

        //目标方法出现异常时执行的代码,可以访问到异常对象,且可以指定在出现异常时再执行通知代码
        @AfterThrowing(value="execution(public int aop.ArithmeticCalculator.*(..))", throwing="ex")
        public void afterThrowing(JoinPoint joinPoint, Exception ex){
            String methodName = joinPoint.getSignature().getName();
            System.out.println("The method " + methodName + " occurs with: " + ex);
        }
    

      环绕通知

    /**
         * 环绕通知需携带ProceedingJoinPoint类型的参数
         * 环绕通知类似于动态代理的全过程:ProceedingJoinPoint类型的参数可以决定是否执行目标方法
         * 且环绕通知必须有返回值,返回值即为目标方法的返回值
         *
         */
        @Around("execution(public int aop.ArithmeticCalculator.*(..))")
        public Object aroundMethod(ProceedingJoinPoint proceedingJoinPoint){
            Object result = null;
            String methodName = proceedingJoinPoint.getSignature().getName();
            try {
                //前置通知
                System.out.println("---The method " + methodName + "begin with " + Arrays.asList(proceedingJoinPoint.getArgs()));
               //执行目标方法
                result = proceedingJoinPoint.proceed();
                //返回通知
                System.out.println("---The method ends with " + result);
    
            } catch (Throwable throwable) {
                throwable.printStackTrace();
                //异常通知
                System.out.println("The method occurs with exception " + throwable);
    
            }
    
            //后置通知
            System.out.println("---The method " + methodName + " ends");
    
            return result;
        }
    

      

     切面的优先级

     使用@Order注解指定切面的优先级,值越小 优先级越高

     重用切面表达式   @Pointcut

    /**
         * 定义一个方法,用于声明切入点表达式,一般,该方法不需要传入其他代码
         * 使用@Pointcut来声明一个切入点表达式
         * 后面的通知直接使用方法名来引用当前的切入点表达式 
         */
        @Pointcut("execution(public int aop.ArithmeticCalculator.*(..))")
        public void declareJoinPointExpression(){
    
        }
    
        //声明该方法是一个前置通知:在目标执行之前执行
        @Before("declareJoinPointExpression()")
        public void befordMethod(JoinPoint joinPoint){
            String methodName = joinPoint.getSignature().getName();
            List<Object> args = Arrays.asList(joinPoint.getArgs());
            System.out.println("The method " + methodName + " begins with: " + args);
        }
    

      

    二、基于XML配置文件配置AOP
    在文件中的注解全部去掉,直接在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-->
        <bean id="arithmeticCalculator" class="aop.ArithmeticCalculatorImp"></bean>
    
        <!--配置切面的bean-->
        <bean id="loggingAspect" class="aop.LoggingAspect"></bean>
    
        <bean id="validationAspect" class="aop.ValidationAspect"></bean>
    
        <!--配置AOP-->
        <aop:config>
            <!--配置切点表达式-->
            <aop:pointcut expression="execution(* aop.ArithmeticCalculator.*(..))" id="pointcut"/>
            <!--配置切面通知-->
            <aop:aspect ref="loggingAspect" order="2">
                <aop:before method="befordMethod" pointcut-ref="pointcut"/>
                <aop:after method="afterMethod" pointcut-ref="pointcut"/>
                <aop:after-throwing method="afterThrowing" pointcut-ref="pointcut" throwing="ex"/>
                <aop:after-returning method="afterReturning" pointcut-ref="pointcut" returning="result"/>
                <!--<aop:around method="aroundMethod" pointcut-ref="pointcut"/>-->
            </aop:aspect>
    
            <aop:aspect ref="validationAspect" order="1">
                <aop:before method="validate" pointcut-ref="pointcut"/>
            </aop:aspect>
        </aop:config>
    </beans>
    
    
    

      

     
  • 相关阅读:
    Ext JS学习第三天 我们所熟悉的javascript(二)
    Ext JS学习第二天 我们所熟悉的javascript(一)
    Ext JS学习第十七天 事件机制event(二)
    Ext JS学习第十六天 事件机制event(一)
    Ext JS学习第十五天 Ext基础之 Ext.DomQuery
    Ext JS学习第十四天 Ext基础之 Ext.DomHelper
    Ext JS学习第十三天 Ext基础之 Ext.Element
    Ext JS学习第十天 Ext基础之 扩展原生的javascript对象(二)
    针对错误 “服务器提交了协议冲突. Section=ResponseHeader Detail=CR 后面必须是 LF” 的原因分析
    C# 使用HttpWebRequest通过PHP接口 上传文件
  • 原文地址:https://www.cnblogs.com/SkyeAngel/p/8295940.html
Copyright © 2011-2022 走看看