澳门新葡亰娱乐网站-www.142net-欢迎您

澳门新葡亰娱乐网站是因为你还没有找到一条正确的致富之路,www.142net是将所有的游戏都汇集在一起的官方平台,因为澳门新葡亰娱乐网站这个网站当中有着大量的游戏攻略,托IP定位技术,传达终端直接到达的精准传播方式。

Spring AOP详解

来源:http://www.bhtsgq.com 作者:计算机知识 人气:120 发布时间:2019-05-30
摘要:一.前言 Spring4 AOP详解 第一章Spring火速入门并从未对Spring四 的AOP做太多的讲述,是因为AOP切面编制程序概念不佳领悟。所以那章入眼从四个方面详解AOP:AOP简要介绍(领会),基于注脚

一.前言

Spring4 AOP详解

第一章Spring 火速入门并从未对Spring四 的 AOP 做太多的讲述,是因为AOP切面编制程序概念不佳领悟。所以那章入眼从四个方面详解AOP:AOP简要介绍(领会),基于注脚的AOP编制程序(器重)和依照xml的AOP编制程序。


Spring4 AOP详解

第一章Spring 急迅入门并不曾对Spring四 的 AOP 做太多的叙说,是因为AOP切面编程概念糟糕驾驭。所以那章器重从多个地点详解AOP:AOP简单介绍(通晓),基于注脚的AOP编制程序(注重)和基于xml的AOP编制程序。


    在原先的种类中,十分的少去关爱spring aop的切实落实与理论,只是简短明白了一下哪些是aop具体怎么用,看到了一篇博文写得还不易,就转载来读书一下,博文地址:

AOP简介

AOP简介

AOP

什么是AOP

AOP(Aspect Oriented Programming)面向切面编制程序,是对价值观的OOP(ObjectOriented Programming)面向对象编制程序的互补。

什么是AOP

AOP(Aspect Oriented Programming)面向切面编制程序,是对价值观的OOP(ObjectOriented Programming)面向对象编制程序的补给。

AOP(Aspect Oriented Programming),即面向切面编制程序,能够说是OOP(Object Oriented Programming,面向对象编制程序)的增补和周详。OOP引进封装、承袭、多态等概念来确立1种对象档次结构,用于模拟公共行为的三个成团。但是OOP允许开荒者定义纵向的涉及,但并不合乎定义横向的关联,举例日志效率。日志代码往往横向地布满在享有目的档案的次序中,而与它对应的目的的中坚职能毫毫无干系系对于任何项目的代码,如安全性、卓殊处理和透明的持续性也都以这么,这种散布在四面八方的非亲非故的代码被喻为横切(cross cutting),在OOP设计中,它导致了多量代码的重复,而不便利各种模块的重用。

AOP的作用

Spring AOP详解。举例A,B,C多少个方法都要在推行前做注解操作,施行后做日志打印操作。咋做?
图片 1

排版非常难看。。。。。。

AOP的作用

假设A,B,C多个艺术都要在实施前做表达操作,推行后做日志打印操作。咋办?
图片 2

排版非常丑。。。。。。

AOP本事恰恰相反,它选取壹种叫做"横切"的本领,剖解临汾装的对象内部,并将那么些影响了多少个类的国有行为封装到二个可选择模块,并将其取名称为"Aspect",即切面。所谓"切面",轻易说正是那么些与业务非亲非故,却为作业模块所联合调用的逻辑或权利封装起来,便于缩小系统的再次代码,降低模块之间的耦合度,并有利于今后的可操作性和可维护性。

AOP专门的学问术语

** 切面(Aspect) ** : A,B,C,方法实行前都要调用的辨证逻辑和试行后都要调用的日志逻辑,那两层业务逻辑正是切面。
** 通知(Advice) ** : 有各个公告,施行前,推行后,推行成功后,实行抛出极度后,环绕文告。正是切面施行的秘诀。
** 目标(Target) ** : 被通报的目标,这里正是A,B,C多少个格局。
** 连接点(Joinpoint) :连接点是多个应用实践进度中能够插入叁个断面包车型大巴点。 切点(pointcut) **:各类类都享有多个连接点,即连接点是程序类中客观存在的工作。AOP 通过切点定位到一定的连接点
打个比如:一天,二人侠客(被打招呼的靶子Target)来小编府上做客,被大门(切面Aspect)拦住,门前有多少个保证(负担通知的Advice),因为内部壹位侠客会降龙108掌(满意被打招呼的3个标准Joinpoint),在那之中1位保养告诉他:"你能够进来了"。此外三个侠客因为武艺(英文名:wǔ yì)超群(满意被打招呼的统壹规范poincut)也都跻身了。


AOP专门的职业术语

** 切面(Aspect) ** : A,B,C,方法实践前都要调用的认证逻辑和实行后都要调用的日记逻辑,那两层业务逻辑就是切面。
** 通知(Advice) ** : 有多样公告,推行前,实行后,试行成功后,推行抛出至极后,环绕公告。正是切面奉行的办法。
** 目标(Target) ** : 被通告的对象,这里便是A,B,C多个主意。
** 连接点(Joinpoint) :连接点是3个选择实施进度中可见插入1个断面包车型地铁点。 切点(pointcut) **:每一个类都抱有三个连接点,即连接点是先后类中型客车观存在的政工。AOP 通过切点定位到一定的连接点
打个假设:一天,三个人侠客(被通报的指标Target)来自身府上做客,被大门(切面Aspect)拦住,门前有多少个维护(担当通知的Advice),因为当中一位侠客会降龙10捌掌(满足被打招呼的多个原则Joinpoint),当中壹位珍爱告诉她:"你能够进入了"。其余三个侠客因为武艺(英文名:wǔ yì)超群(知足被通报的统一标准poincut)也都进入了。


运用"横切"技艺,AOP把软件系统一分配为八个部分:着力关切点横切关怀点。业务管理的最首要流程是基本关怀点,与之关系非常的小的壹对是横切关心点。横切关心点的一个表征是,他们有的时候发出在宗旨关怀点的多处,而随处基本相似,举个例子权限认证、日志、事物。AOP的功效在于分离系统中的种种关心点,将焦点关切点和横切关切点分离开来。

基于评释的AOP编程

依附表明的编制程序,要求重视AspectJ框架(java中最盛行的aop框架)。
首先步:导入AspectJ的jar包,该框架唯有Spring 二.0上述才支撑。

<dependency>  
    <groupId>org.springframework</groupId>  
    <artifactId>spring-aspects</artifactId>  
    <version>4.2.2.RELEASE</version>  
</dependency>

第二步:核心文件applicationContext.xml,里面需求布署活动扫描包(用于IOC注明)和铺排启用AspectJ表明

<?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"  
    xmlns:context="http://www.springframework.org/schema/context"  
    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-4.0.xsd  
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">  

    <!-- 自动扫描的包 -->  
    <context:component-scan base-package="com.itdragon.spring.*" ></context:component-scan>  

    <!-- 使 AspectJ 的注解起作用 -->  
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>  

</beans>  

其三步:切面类,该类有啥特色?首先它必须是IOC的bean,还要注脚它是AspectJ切面,最终还是可以够定义切面包车型地铁预先级Order(非必填)
通报有两种表明
** @Before ** :前置文告的表明,在对象措施实行前调用
** @After :前置文告的解说, 在对象措施实行后调用,尽管程序抛出十三分都会调用 @AfterReturning :再次回到文告的注脚, 在目的措施成功进行后调用,假如程序出错则不会调用 @AfterThrowing :异常公告的笺注, 在指标措施出现内定特别时调用 @Around **:环绕公告的笺注,很有力(相当于前多少个公告的结合),但用的非常的少,
再有为了简化开垦的选取切入点@Pointcut,以及抽象表明"*"

public interface Calculator {  

    public int add(int a, int b);  
    public int division(int a, int b);  

}  

import org.springframework.stereotype.Repository;  
@Repository("calculator")  
public class CalculatorImp implements Calculator {  

    @Override  
    public int add(int a, int b) {  
        System.out.println("add 方法执行了 ----> "   (a   b));  
        return (a   b);  
    }  

    @Override  
    public int division(int a, int b) {  
        System.out.println("division 方法执行了 ----> "   (a / b));  
        return (a / b);  
    }  

}  

import java.util.Arrays;  
import java.util.List;  
import org.aspectj.lang.JoinPoint;  
import org.aspectj.lang.annotation.After;  
import org.aspectj.lang.annotation.AfterReturning;  
import org.aspectj.lang.annotation.AfterThrowing;  
import org.aspectj.lang.annotation.Aspect;  
import org.aspectj.lang.annotation.Before;  
import org.aspectj.lang.annotation.Pointcut;  
import org.springframework.core.annotation.Order;  
import org.springframework.stereotype.Component;  

/** 
 * @Order(n) : 切面的优先级,n越小,级别越高 
 * @Aspect:声明该类是一个切面 
 * @Component:切面必须是 IOC 中的 bean 
 */  
@Order(2)  
@Aspect  
@Component  
public class LoggerAspect {  

    /** 
     * 前置通知的注解,在目标方法执行前调用 
     * execution最基础的表达式语法。 
     * 注意点: 
     * 1. 方法里面不能有行参,及add(int a, int b) 这是会报错的。 
     * 2. int(方法的返回值),add(方法名) 可以用 * 抽象化。甚至可以将类名抽象,指定该包下的类。 
     * 3. (int, int) 可以用(..)代替,表示匹配任意数量的参数 
     * 4. 被通知的对象(Target),建议加上包的路径 
     */  
    @Before("execution(int com.atguigu.spring.my.aop.CalculatorImp.add(int , int))")  
    public void beforeAdvice(JoinPoint joinPoint) {  
        /** 
         * 连接点 joinPoint:add方法就是连接点 
         * getName获取的是方法名,是英文的,可以通过国际化转换对应的中文比较好。 
         */  
        String methodName = joinPoint.getSignature().getName();   
        List<Object> args = Arrays.asList(joinPoint.getArgs());  
        System.out.println("@Before 前置通知 : 方法名 【 "   methodName   " 】and args are "   args);  
    }  

    /** 
     * 后置通知的注解, 在目标方法执行后调用,即使是程序出错都会调用 
     * 这里将 方法的返回值 和 CalculatorImp类下所有的方法,以及方法的形参 都抽象了 
     */  
    @After("execution(* com.atguigu.spring.my.aop.CalculatorImp.*(..))")  
    public void afterAdvice(JoinPoint joinPoint) {  
        String methodName = joinPoint.getSignature().getName();   
        List<Object> args = Arrays.asList(joinPoint.getArgs());  
        System.out.println("@After 后置通知 : 方法名 【 "   methodName   " 】and args are "   args);  
    }  

    /** 
     * 重用切入点定义:声明切入点表达式。该方法里面不建议添加其他代码 
     */  
    @Pointcut("execution(* com.atguigu.spring.my.aop.CalculatorImp.*(..))")  
    public void declareExecutionExpression(){}  

    /** 
     * 返回通知的注解, 在目标方法成功执行后调用,如果程序出错则不会调用 
     * returning="result" 和 形参 result 保持一致 
     */  
    @AfterReturning(value="declareExecutionExpression()", returning="result")  
    public void afterRunningAdvice(JoinPoint joinPoint, Object result) {  
        String methodName = joinPoint.getSignature().getName();   
        List<Object> args = Arrays.asList(joinPoint.getArgs());  
        System.out.println("@AfterReturning 返回通知 : 方法名 【 "   methodName   " 】and args are "   args   " , result is "   result);  
    }  

    /** 
     * 异常通知的注解, 在目标方法出现指定异常时调用 
     * throwing="exception" 和 形参 exception 保持一致 , 且目标方法出了Exception(可以是其他异常)异常才会调用。 
     */  
    @AfterThrowing(value="declareExecutionExpression()", throwing="exception")  
    public void afterThrowingAdvice(JoinPoint joinPoint, Exception exception) {  
        String methodName = joinPoint.getSignature().getName();   
        System.out.println("@AfterThrowing 异常通知 : 方法名 【 "   methodName   " 】and  exception is "   exception);  
    }  

} 

import java.util.Arrays;  
import java.util.List;  
import org.aspectj.lang.ProceedingJoinPoint;  
import org.aspectj.lang.annotation.Around;  
import org.aspectj.lang.annotation.Aspect;  
import org.springframework.core.annotation.Order;  
import org.springframework.stereotype.Component;  

@Order(1)  
@Aspect  
@Component  
public class AroundAspect {  

    /** 
     * 环绕通知,很强大,但用的不多。 用环绕通知测试Order的优先级看的不明显(这里是笔者的失误) 
     * 环绕通知需要用ProceedingJoinPoint 类型的参数 
     */  
    @Around("execution(* com.atguigu.spring.my.aop.CalculatorImp.*(..))")  
    public Object aroundAdvice(ProceedingJoinPoint joinPoint) {  
        Object result = null;  
        String methodName = joinPoint.getSignature().getName();   
        List<Object> args = Arrays.asList(joinPoint.getArgs());  
        try {  
            System.out.println("@Around 前置通知 : 方法名 【 "   methodName   " 】and args are "   args);  
            result = joinPoint.proceed();  
            System.out.println("@Around 返回通知 : 方法名 【 "   methodName   " 】and args are "   args   " , result is "   result);  
        } catch (Throwable e) {  
            e.printStackTrace();  
            System.out.println("@Around 异常通知 : 方法名 【 "   methodName   " 】and  exception is "   e);  
        }  
        System.out.println("@Around 后置通知 : 方法名 【 "   methodName   " 】and args are "   args);  

        return result;  
    }  

}  

import org.springframework.context.support.ClassPathXmlApplicationContext;  
public class Main {  

    public static void main(String[] args) {  

        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");  
        Calculator calculator = (Calculator) ctx.getBean("calculator");  

        calculator.add(11, 12);  
        calculator.division(21, 3); // 测试时,将被除数换成0,可以测试@AfterReturning , @After 和 @AfterThrowing  

        ctx.close();  
    }  

} 

第陆步:施行看结果。这里未有做环绕文告的打字与印刷。将被除数设置为零,能够测试 重回通知,前置文告 和 相当文告。

@Before 前置通知 : 方法名 【 add 】and args are [11, 12]  
add 方法执行了 ----> 23  
@After 后置通知 : 方法名 【 add 】and args are [11, 12]  
@AfterReturning 返回通知 : 方法名 【 add 】and args are [11, 12] , result is 23  
division 方法执行了 ----> 7  
@After 后置通知 : 方法名 【 division 】and args are [21, 3]  
@AfterReturning 返回通知 : 方法名 【 division 】and args are [21, 3] , result is 7  

异常粗略对啊,用到的注脚其实并不是众多。
如上代码有二个不足之处,正是测试Order优先级的时候,效果不明明。AroundAspect的事先级高于LoggerAspect,从打字与印刷的日记中发觉,唯有AroundAspect的放置文告在LoggerAspect前边打字与印刷,其余公告均在前边。
因为博客和课堂差别,假诺把各种知识点都单身写出来,篇幅只怕太长。笔者尽或然将全部知识点都写在1块,学A知识的还要将B,C,D的文化一同学习。但难免会有部分不听话的知识点。所以请各位读者见谅。
图片 3


依据表明的AOP编制程序

典故注脚的编制程序,需求依赖AspectJ框架(java中最盛行的aop框架)。
先是步:导入AspectJ的jar包,该框架唯有Spring 贰.0上述才支撑。

<dependency>  
    <groupId>org.springframework</groupId>  
    <artifactId>spring-aspects</artifactId>  
    <version>4.2.2.RELEASE</version>  
</dependency>

其次步:焦点文件applicationContext.xml,里面必要配置活动扫描包(用于IOC表明)和布局启用AspectJ申明

<?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"  
    xmlns:context="http://www.springframework.org/schema/context"  
    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-4.0.xsd  
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">  

    <!-- 自动扫描的包 -->  
    <context:component-scan base-package="com.itdragon.spring.*" ></context:component-scan>  

    <!-- 使 AspectJ 的注解起作用 -->  
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>  

</beans>  

其三步:切面类,该类有如何特点?首先它必须是IOC的bean,还要注明它是AspectJ切面,最终还足以定义切面包车型客车优先级Order(非必填)
通知有多种声明
** @Before ** :前置文告的解说,在目的措施施行前调用
** @After :前置文告的讲解, 在指标措施实施后调用,就算程序抛出极度都会调用 @AfterReturning :再次回到公告的申明, 在对象措施成功实践后调用,借使程序出错则不会调用 @AfterThrowing :十分布告的申明, 在目的措施出现钦定非常时调用 @Around **:环绕通知的注解,很强劲(约等于前几个关照的重组),但用的相当少,
还只怕有为了简化开拓的选定切入点@Pointcut,以及抽象表达"*"

public interface Calculator {  

    public int add(int a, int b);  
    public int division(int a, int b);  

}  

import org.springframework.stereotype.Repository;  
@Repository("calculator")  
public class CalculatorImp implements Calculator {  

    @Override  
    public int add(int a, int b) {  
        System.out.println("add 方法执行了 ----> "   (a   b));  
        return (a   b);  
    }  

    @Override  
    public int division(int a, int b) {  
        System.out.println("division 方法执行了 ----> "   (a / b));  
        return (a / b);  
    }  

}  

import java.util.Arrays;  
import java.util.List;  
import org.aspectj.lang.JoinPoint;  
import org.aspectj.lang.annotation.After;  
import org.aspectj.lang.annotation.AfterReturning;  
import org.aspectj.lang.annotation.AfterThrowing;  
import org.aspectj.lang.annotation.Aspect;  
import org.aspectj.lang.annotation.Before;  
import org.aspectj.lang.annotation.Pointcut;  
import org.springframework.core.annotation.Order;  
import org.springframework.stereotype.Component;  

/** 
 * @Order(n) : 切面的优先级,n越小,级别越高 
 * @Aspect:声明该类是一个切面 
 * @Component:切面必须是 IOC 中的 bean 
 */  
@Order(2)  
@Aspect  
@Component  
public class LoggerAspect {  

    /** 
     * 前置通知的注解,在目标方法执行前调用 
     * execution最基础的表达式语法。 
     * 注意点: 
     * 1. 方法里面不能有行参,及add(int a, int b) 这是会报错的。 
     * 2. int(方法的返回值),add(方法名) 可以用 * 抽象化。甚至可以将类名抽象,指定该包下的类。 
     * 3. (int, int) 可以用(..)代替,表示匹配任意数量的参数 
     * 4. 被通知的对象(Target),建议加上包的路径 
     */  
    @Before("execution(int com.atguigu.spring.my.aop.CalculatorImp.add(int , int))")  
    public void beforeAdvice(JoinPoint joinPoint) {  
        /** 
         * 连接点 joinPoint:add方法就是连接点 
         * getName获取的是方法名,是英文的,可以通过国际化转换对应的中文比较好。 
         */  
        String methodName = joinPoint.getSignature().getName();   
        List<Object> args = Arrays.asList(joinPoint.getArgs());  
        System.out.println("@Before 前置通知 : 方法名 【 "   methodName   " 】and args are "   args);  
    }  

    /** 
     * 后置通知的注解, 在目标方法执行后调用,即使是程序出错都会调用 
     * 这里将 方法的返回值 和 CalculatorImp类下所有的方法,以及方法的形参 都抽象了 
     */  
    @After("execution(* com.atguigu.spring.my.aop.CalculatorImp.*(..))")  
    public void afterAdvice(JoinPoint joinPoint) {  
        String methodName = joinPoint.getSignature().getName();   
        List<Object> args = Arrays.asList(joinPoint.getArgs());  
        System.out.println("@After 后置通知 : 方法名 【 "   methodName   " 】and args are "   args);  
    }  

    /** 
     * 重用切入点定义:声明切入点表达式。该方法里面不建议添加其他代码 
     */  
    @Pointcut("execution(* com.atguigu.spring.my.aop.CalculatorImp.*(..))")  
    public void declareExecutionExpression(){}  

    /** 
     * 返回通知的注解, 在目标方法成功执行后调用,如果程序出错则不会调用 
     * returning="result" 和 形参 result 保持一致 
     */  
    @AfterReturning(value="declareExecutionExpression()", returning="result")  
    public void afterRunningAdvice(JoinPoint joinPoint, Object result) {  
        String methodName = joinPoint.getSignature().getName();   
        List<Object> args = Arrays.asList(joinPoint.getArgs());  
        System.out.println("@AfterReturning 返回通知 : 方法名 【 "   methodName   " 】and args are "   args   " , result is "   result);  
    }  

    /** 
     * 异常通知的注解, 在目标方法出现指定异常时调用 
     * throwing="exception" 和 形参 exception 保持一致 , 且目标方法出了Exception(可以是其他异常)异常才会调用。 
     */  
    @AfterThrowing(value="declareExecutionExpression()", throwing="exception")  
    public void afterThrowingAdvice(JoinPoint joinPoint, Exception exception) {  
        String methodName = joinPoint.getSignature().getName();   
        System.out.println("@AfterThrowing 异常通知 : 方法名 【 "   methodName   " 】and  exception is "   exception);  
    }  

} 

import java.util.Arrays;  
import java.util.List;  
import org.aspectj.lang.ProceedingJoinPoint;  
import org.aspectj.lang.annotation.Around;  
import org.aspectj.lang.annotation.Aspect;  
import org.springframework.core.annotation.Order;  
import org.springframework.stereotype.Component;  

@Order(1)  
@Aspect  
@Component  
public class AroundAspect {  

    /** 
     * 环绕通知,很强大,但用的不多。 用环绕通知测试Order的优先级看的不明显(这里是笔者的失误) 
     * 环绕通知需要用ProceedingJoinPoint 类型的参数 
     */  
    @Around("execution(* com.atguigu.spring.my.aop.CalculatorImp.*(..))")  
    public Object aroundAdvice(ProceedingJoinPoint joinPoint) {  
        Object result = null;  
        String methodName = joinPoint.getSignature().getName();   
        List<Object> args = Arrays.asList(joinPoint.getArgs());  
        try {  
            System.out.println("@Around 前置通知 : 方法名 【 "   methodName   " 】and args are "   args);  
            result = joinPoint.proceed();  
            System.out.println("@Around 返回通知 : 方法名 【 "   methodName   " 】and args are "   args   " , result is "   result);  
        } catch (Throwable e) {  
            e.printStackTrace();  
            System.out.println("@Around 异常通知 : 方法名 【 "   methodName   " 】and  exception is "   e);  
        }  
        System.out.println("@Around 后置通知 : 方法名 【 "   methodName   " 】and args are "   args);  

        return result;  
    }  

}  

import org.springframework.context.support.ClassPathXmlApplicationContext;  
public class Main {  

    public static void main(String[] args) {  

        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");  
        Calculator calculator = (Calculator) ctx.getBean("calculator");  

        calculator.add(11, 12);  
        calculator.division(21, 3); // 测试时,将被除数换成0,可以测试@AfterReturning , @After 和 @AfterThrowing  

        ctx.close();  
    }  

} 

第四步:实行看结果。这里未有做环绕通告的打字与印刷。将被除数设置为零,能够测试 重临通告,前置文告 和 卓殊通告。

@Before 前置通知 : 方法名 【 add 】and args are [11, 12]  
add 方法执行了 ----> 23  
@After 后置通知 : 方法名 【 add 】and args are [11, 12]  
@AfterReturning 返回通知 : 方法名 【 add 】and args are [11, 12] , result is 23  
division 方法执行了 ----> 7  
@After 后置通知 : 方法名 【 division 】and args are [21, 3]  
@AfterReturning 返回通知 : 方法名 【 division 】and args are [21, 3] , result is 7  

很轻便对吧,用到的注明其实并不是多多益善。
上述代码有三个不足之处,就是测试Order优先级的时候,效果不明朗。AroundAspect的事先级高于LoggerAspect,从打字与印刷的日记中窥见,唯有AroundAspect的松开文告在LoggerAspect后边打字与印刷,别的布告均在前边。
因为博客和课堂不一样,假设把各类知识点都独立写出来,篇幅恐怕太长。作者尽只怕将富有知识点都写在壹块,学A知识的还要将B,C,D的文化一齐学学。但难免会有部分不听话的知识点。所以请各位读者见谅。
图片 4


 

基于xml的AOP编程

上壹篇小说讲到了依照xml的IOC设置bean,篇幅较长,内容较复杂。但配备AOP不一致,它大致了过多。
率先步:宗旨文件applicationContext.xml,
首先是布置三个bean,方正是多少个切面类,和多个方法类。
接下来配置AOP,
aop:config:注解起首安顿AOP了,
aop:pointcut:配置切点重用表明式,expression的值是切实可行的表明式,id 该aop:pointcut的举世无双标志,
aop:aspect:配置切面,ref的值引用相关怀面类的bean,order设置优先级(也足以不安装)。
多样布告的安插:aop:before,aop:after,aop:after-returning,aop:after-throwing,aop:around。method的值正是相应的章程,poincut-ref的值要引用 aop:pointcut 的id。当中有五个比较非常:aop:after-returning 要多配备四个returning,个中returning的值要和相应措施的形参保持壹致。同理aop:after-throwing 也要多安顿四个throwing,当中throwing的值也要和呼应措施的形参保持壹致。不然试行程序会报错。

<?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"  
    xmlns:context="http://www.springframework.org/schema/context"  
    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-4.0.xsd  
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">  

    <bean id="calculator" class="com.atguigu.spring.my.xml.CalculatorImp"></bean>  
    <bean id="loggerAspect" class="com.atguigu.spring.my.xml.LoggerAspect"></bean>  
    <bean id="aroundAspect" class="com.atguigu.spring.my.xml.AroundAspect"></bean>  

    <!-- AOP配置 -->  
    <aop:config>  
        <!-- 配置切点表达式 类似注解的重用表达式-->  
        <aop:pointcut expression="execution(* com.atguigu.spring.my.xml.CalculatorImp.*(..))"   
            id="pointcut"/>  
        <!-- 配置切面及通知  method的值就是 loggerAspect类中的值-->  
        <aop:aspect ref="loggerAspect" order="2">  
            <aop:before method="beforeAdvice" pointcut-ref="pointcut"/>  
            <aop:after method="afterAdvice" pointcut-ref="pointcut"/>  
            <aop:after-returning method="afterRunningAdvice" pointcut-ref="pointcut" returning="result"/>  
            <aop:after-throwing method="afterThrowingAdvice" pointcut-ref="pointcut" throwing="exception"/>  
        </aop:aspect>  
        <aop:aspect ref="aroundAspect" order="1">  
            <!-- <aop:around method="aroundAdvice" pointcut-ref="pointcut"/>  -->  
        </aop:aspect>  
    </aop:config>  

</beans>  

其次步:下边多少个类,正是脱去了富有申明的门面,采取通过配备的xml,完毕AOP编制程序。

public interface Calculator {  

    public int add(int a, int b);  
    public int division(int a, int b);  

}  

public class CalculatorImp implements Calculator {  

    @Override  
    public int add(int a, int b) {  
        System.out.println("add 方法执行了 ----> "   (a   b));  
        return (a   b);  
    }  

    @Override  
    public int division(int a, int b) {  
        System.out.println("division 方法执行了 ----> "   (a / b));  
        return (a / b);  
    }  

}  

import java.util.Arrays;  
import java.util.List;  
import org.aspectj.lang.JoinPoint;  

public class LoggerAspect {  

    public void beforeAdvice(JoinPoint joinPoint) {  
        String methodName = joinPoint.getSignature().getName();   
        List<Object> args = Arrays.asList(joinPoint.getArgs());  
        System.out.println("Before 前置通知 : 方法名 【 "   methodName   " 】and args are "   args);  
    }  

    public void afterAdvice(JoinPoint joinPoint) {  
        String methodName = joinPoint.getSignature().getName();   
        List<Object> args = Arrays.asList(joinPoint.getArgs());  
        System.out.println("After 后置通知 : 方法名 【 "   methodName   " 】and args are "   args);  
    }  

    public void afterRunningAdvice(JoinPoint joinPoint, Object result) {  
        String methodName = joinPoint.getSignature().getName();   
        List<Object> args = Arrays.asList(joinPoint.getArgs());  
        System.out.println("AfterReturning 返回通知 : 方法名 【 "   methodName   " 】and args are "   args   " , result is "   result);  
    }  

    public void afterThrowingAdvice(JoinPoint joinPoint, Exception exception) {  
        String methodName = joinPoint.getSignature().getName();   
        System.out.println("AfterThrowing 异常通知 : 方法名 【 "   methodName   " 】and  exception is "   exception);  
    }  

}  

import java.util.Arrays;  
import java.util.List;  
import org.aspectj.lang.ProceedingJoinPoint;  

public class AroundAspect {  

    public Object aroundAdvice(ProceedingJoinPoint joinPoint) {  
        Object result = null;  
        String methodName = joinPoint.getSignature().getName();   
        List<Object> args = Arrays.asList(joinPoint.getArgs());  
        try {  
            System.out.println("@Around 前置通知 : 方法名 【 "   methodName   " 】and args are "   args);  
            result = joinPoint.proceed();  
            System.out.println("@Around 返回通知 : 方法名 【 "   methodName   " 】and args are "   args   " , result is "   result);  
        } catch (Throwable e) {  
            e.printStackTrace();  
            System.out.println("@Around 异常通知 : 方法名 【 "   methodName   " 】and  exception is "   e);  
        }  
        System.out.println("@Around 后置通知 : 方法名 【 "   methodName   " 】and args are "   args);  

        return result;  
    }  

}  

import org.springframework.context.support.ClassPathXmlApplicationContext;  

public class Main {  

    public static void main(String[] args) {  

        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");  
        Calculator calculator = (Calculator) ctx.getBean("calculator");  

        calculator.add(11, 12);  
        calculator.division(21, 3); // 测试时,将被除数换成0,可以测试AfterReturning ,After 和 AfterThrowing  

        ctx.close();  
    }  

}  

Before 前置通知 : 方法名 【 add 】and args are [11, 12]  
add 方法执行了 ----> 23  
After 后置通知 : 方法名 【 add 】and args are [11, 12]  
AfterReturning 返回通知 : 方法名 【 add 】and args are [11, 12] , result is 23  
Before 前置通知 : 方法名 【 division 】and args are [21, 3]  
division 方法执行了 ----> 7  
After 后置通知 : 方法名 【 division 】and args are [21, 3]  
AfterReturning 返回通知 : 方法名 【 division 】and args are [21, 3] , result is 7  

到这里,基于xml文件的AOP编制程序也讲完了。四不四很粗大略。

基于xml的AOP编程

上1篇作品讲到了遵照xml的IOC设置bean,篇幅较长,内容较复杂。但配备AOP差别,它大致了重重。
率先步:宗旨文件applicationContext.xml,
首先是安排八个bean,方就是五个切面类,和3个方法类。
接下来配置AOP,
aop:config:注脚初叶布置AOP了,
aop:pointcut:配置切点重用表明式,expression的值是现实性的表达式,id 该aop:pointcut的当世无双标志,
aop:aspect:配置切面,ref的值引用相关怀面类的bean,order设置优先级(也足以不设置)。
种种公告的布署:aop:before,aop:after,aop:after-returning,aop:after-throwing,aop:around。method的值正是相应的形式,poincut-ref的值要引用 aop:pointcut 的id。当中有两个对比新鲜:aop:after-returning 要多铺排二个returning,个中returning的值要和相应措施的形参保持1致。同理aop:after-throwing 也要多配备1个throwing,当中throwing的值也要和相应措施的形参保持壹致。不然试行程序会报错。

<?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"  
    xmlns:context="http://www.springframework.org/schema/context"  
    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-4.0.xsd  
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">  

    <bean id="calculator" class="com.atguigu.spring.my.xml.CalculatorImp"></bean>  
    <bean id="loggerAspect" class="com.atguigu.spring.my.xml.LoggerAspect"></bean>  
    <bean id="aroundAspect" class="com.atguigu.spring.my.xml.AroundAspect"></bean>  

    <!-- AOP配置 -->  
    <aop:config>  
        <!-- 配置切点表达式 类似注解的重用表达式-->  
        <aop:pointcut expression="execution(* com.atguigu.spring.my.xml.CalculatorImp.*(..))"   
            id="pointcut"/>  
        <!-- 配置切面及通知  method的值就是 loggerAspect类中的值-->  
        <aop:aspect ref="loggerAspect" order="2">  
            <aop:before method="beforeAdvice" pointcut-ref="pointcut"/>  
            <aop:after method="afterAdvice" pointcut-ref="pointcut"/>  
            <aop:after-returning method="afterRunningAdvice" pointcut-ref="pointcut" returning="result"/>  
            <aop:after-throwing method="afterThrowingAdvice" pointcut-ref="pointcut" throwing="exception"/>  
        </aop:aspect>  
        <aop:aspect ref="aroundAspect" order="1">  
            <!-- <aop:around method="aroundAdvice" pointcut-ref="pointcut"/>  -->  
        </aop:aspect>  
    </aop:config>  

</beans>  

第二步:上边多少个类,正是脱去了装有表明的糖衣,选取通过布署的xml,达成AOP编制程序。

public interface Calculator {  

    public int add(int a, int b);  
    public int division(int a, int b);  

}  

public class CalculatorImp implements Calculator {  

    @Override  
    public int add(int a, int b) {  
        System.out.println("add 方法执行了 ----> "   (a   b));  
        return (a   b);  
    }  

    @Override  
    public int division(int a, int b) {  
        System.out.println("division 方法执行了 ----> "   (a / b));  
        return (a / b);  
    }  

}  

import java.util.Arrays;  
import java.util.List;  
import org.aspectj.lang.JoinPoint;  

public class LoggerAspect {  

    public void beforeAdvice(JoinPoint joinPoint) {  
        String methodName = joinPoint.getSignature().getName();   
        List<Object> args = Arrays.asList(joinPoint.getArgs());  
        System.out.println("Before 前置通知 : 方法名 【 "   methodName   " 】and args are "   args);  
    }  

    public void afterAdvice(JoinPoint joinPoint) {  
        String methodName = joinPoint.getSignature().getName();   
        List<Object> args = Arrays.asList(joinPoint.getArgs());  
        System.out.println("After 后置通知 : 方法名 【 "   methodName   " 】and args are "   args);  
    }  

    public void afterRunningAdvice(JoinPoint joinPoint, Object result) {  
        String methodName = joinPoint.getSignature().getName();   
        List<Object> args = Arrays.asList(joinPoint.getArgs());  
        System.out.println("AfterReturning 返回通知 : 方法名 【 "   methodName   " 】and args are "   args   " , result is "   result);  
    }  

    public void afterThrowingAdvice(JoinPoint joinPoint, Exception exception) {  
        String methodName = joinPoint.getSignature().getName();   
        System.out.println("AfterThrowing 异常通知 : 方法名 【 "   methodName   " 】and  exception is "   exception);  
    }  

}  

import java.util.Arrays;  
import java.util.List;  
import org.aspectj.lang.ProceedingJoinPoint;  

public class AroundAspect {  

    public Object aroundAdvice(ProceedingJoinPoint joinPoint) {  
        Object result = null;  
        String methodName = joinPoint.getSignature().getName();   
        List<Object> args = Arrays.asList(joinPoint.getArgs());  
        try {  
            System.out.println("@Around 前置通知 : 方法名 【 "   methodName   " 】and args are "   args);  
            result = joinPoint.proceed();  
            System.out.println("@Around 返回通知 : 方法名 【 "   methodName   " 】and args are "   args   " , result is "   result);  
        } catch (Throwable e) {  
            e.printStackTrace();  
            System.out.println("@Around 异常通知 : 方法名 【 "   methodName   " 】and  exception is "   e);  
        }  
        System.out.println("@Around 后置通知 : 方法名 【 "   methodName   " 】and args are "   args);  

        return result;  
    }  

}  

import org.springframework.context.support.ClassPathXmlApplicationContext;  

public class Main {  

    public static void main(String[] args) {  

        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");  
        Calculator calculator = (Calculator) ctx.getBean("calculator");  

        calculator.add(11, 12);  
        calculator.division(21, 3); // 测试时,将被除数换成0,可以测试AfterReturning ,After 和 AfterThrowing  

        ctx.close();  
    }  

}  

Before 前置通知 : 方法名 【 add 】and args are [11, 12]  
add 方法执行了 ----> 23  
After 后置通知 : 方法名 【 add 】and args are [11, 12]  
AfterReturning 返回通知 : 方法名 【 add 】and args are [11, 12] , result is 23  
Before 前置通知 : 方法名 【 division 】and args are [21, 3]  
division 方法执行了 ----> 7  
After 后置通知 : 方法名 【 division 】and args are [21, 3]  
AfterReturning 返回通知 : 方法名 【 division 】and args are [21, 3] , result is 7  

到那边,基于xml文件的AOP编程也讲完了。四不四很简短。

AOP主旨概念

1、横切关心点

对怎么样措施开始展览阻挠,拦截后怎么管理,那么些关切点称之为横切关怀点

2、切面(aspect)

类是对实体特征的虚幻,切面正是对横切关怀点的虚幻

3、连接点(joinpoint)

被阻止到的点,因为Spring只帮衬措施类型的连接点,所以在Spring中连接点指的正是被阻碍到的方法,实际上连接点还足以是字段或许构造器

4、切入点(pointcut)

对连接点进行拦阻的定义

5、通知(advice)

所谓文告指的便是指拦截到连接点之后要进行的代码,文告分为前置、前置、非凡、最后、环绕文告伍类

陆、指标对象

代理的靶子对象

7、织入(weave)

将切面应用到对象对象并导致代理对象成立的进程

8、引入(introduction)

本文由澳门新葡亰发布于计算机知识,转载请注明出处:Spring AOP详解

关键词: spring 所有随笔 编程语言 aop

频道精选

最火资讯