Java Spring AOP用法

Spring AOP

Java web 环境搭建

Java web 项目搭建

Java Spring IOC用法

spring提供了两个核心功能,一个是IoC(控制反转),另外一个便是Aop(面向切面编程),IoC有助于应用对象之间的解耦,AOP则可以实现横切关注点(如日志、安全、缓存和事务管理)与他们所影响的对象之间的解耦。

1.简介

AOP主要包含了通知、切点和连接点等术语,介绍如下

  • 通知(Advice)

    通知定义了切面是什么以及何时调用,何时调用包含以下几种

    Before 在方法被调用之前调用通知

    After 在方法完成之后调用通知,无论方法执行是否成功

    After-returning 在方法成功执行之后调用通知

    After-throwing 在方法抛出异常后调用通知

    Around 通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为

  • 切点(PointCut)

    通知定义了切面的什么何时,切点定义了何处,切点的定义会匹配通知所要织入的一个或多个连接点,我们通常使用明确的类的方法名称来指定这些切点,或是利用正则表达式定义匹配的类和方法名称来指定这些切点。

    切点的格式如下

    execution(* com.ganji.demo.service.user.UserService.GetDemoUser (..) )

  • 连接点(JoinPoint)

    连接点是在应用执行过程中能够插入切面的一个点,这个点可以是调用方法时,抛出异常时,甚至是修改一个字段时,切面代码可以利用这些连接点插入到应用的正常流程中,并添加新的行为,如日志、安全、事务、缓存等。

现阶段的AOP框架

AOP框架除了Spring AOP之外,还包括AspectJJBoss AOP

上述框架的区别是Spring AOP只支持到方法连接点,另外两个还支持字段和构造器连接点。

2.用法

同依赖注入一样,AOP在spring中有两种配置方式,一是xml配置的方式,二是自动注解的模式。

  • 2.1 xml中声明切面

    • 2.1.1 AOP配置元素

    在xml中,我们使用如下AOP配置元素声明切面

     AOP配置元素 | 描述
    ------------ | -------------
    `<aop:advisor>` | 定义AOP通知器
    `<aop:after>`  | 定义AOP后置通知(不管该方法是否执行成功)
    `<aop:after-returning>` | 在方法成功执行后调用通知
    `<aop:after-throwing>` | 在方法抛出异常后调用通知
    `<aop:around>` | 定义AOP环绕通知
    `<aop:aspect>` | 定义切面
    `<aop:aspect-autoproxy>` | 定义`@AspectJ`注解驱动的切面
    `<aop:before>` | 定义AOP前置通知
    `<aop:config>` | 顶层的AOP配置元素,大多数的<aop:*>包含在<aop:config>元素内
    `<aop:declare-parent>` | 为被通知的对象引入额外的接口,并透明的实现
    `<aop:pointcut>` | 定义切点
    • 2.1.2 定义切面

    我们在service层添加com.ganji.demo.service.aspect.XmlAopDemoUserLog类,里面实现了拦截方法,具体如下

    
    package com.ganji.demo.service.aspect;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    
    /**
     * Created by admin on 2015/9/2.
     */
    public class XmlAopDemoUserLog {
    //    方法执行前通知
        public void beforeLog() {
            System.out.println("开始执行前置通知  日志记录");
        }
    //    方法执行完后通知
        public void afterLog() {
            System.out.println("开始执行后置通知 日志记录");
        }
    //    执行成功后通知
        public void afterReturningLog() {
            System.out.println("方法成功执行后通知 日志记录");
        }
    //    抛出异常后通知
        public void afterThrowingLog() {
            System.out.println("方法抛出异常后执行通知 日志记录");
        }
    
    //    环绕通知
        public Object aroundLog(ProceedingJoinPoint joinpoint) {
            Object result = null;
            try {
                System.out.println("环绕通知开始 日志记录");
                long start = System.currentTimeMillis();
    
                //有返回参数 则需返回值
                result =  joinpoint.proceed();
    
                long end = System.currentTimeMillis();
                System.out.println("总共执行时长" + (end - start) + " 毫秒");
                System.out.println("环绕通知结束 日志记录");
            } catch (Throwable t) {
                System.out.println("出现错误");
            }
            return result;
        }
    }
    
    • 2.1.3 xml声明切面并调用

    我们在web层,web-inf/dispatcher-servlet.xml中定义切面,具体如下

    
    <!--定义切面 指定拦截方法时 做什么-->
    <bean id="xmlAopDemoUserLog" class="com.ganji.demo.service.aspect.XmlAopDemoUserLog"></bean>
    <aop:config>
        <aop:aspect ref="xmlAopDemoUserLog"> <!--指定切面-->
            <!--定义切点-->
            <aop:pointcut id="logpoint" expression="execution(* com.ganji.demo.service.user.UserService.GetDemoUser(..))"></aop:pointcut>
            <!--定义连接点-->
            <aop:before pointcut-ref="logpoint" method="beforeLog"></aop:before>
            <aop:after pointcut-ref="logpoint" method="afterLog"></aop:after>
            <aop:after-returning pointcut-ref="logpoint" method="afterReturningLog"></aop:after-returning>
            <aop:after-throwing pointcut-ref="logpoint" method="afterThrowingLog"></aop:after-throwing>
        </aop:aspect>
    </aop:config>

    在controller下调用,调用具体如下

    DemoUserEntity demoUser=userService.GetDemoUser(1);

    这是运行起来 我们将看到打印出如下日志

    开始执行前置通知 日志记录

    开始执行后置通知 日志记录

    方法成功执行后通知 日志记录

    • 2.1.4 小结

    如果通过xml配置,我们还可以实现环绕通知,环绕通知的目的是把前置通知和后置通知的信息共享起来。同时还可以为通知传递方法的参数,在切面拦截中验证参数的有效性。

  • 2.2 自动注解AOP

    在上述2.1中我们通过xml配置的形式 实现了AOP编程,现在我们通过不配置xml,配置注解的形式实现AOP。

    • 2.2.1 配置自动代理

    使用配置注解,首先我们要将切面在spring上下文中声明成自动代理bean,我们需要在web层的web-inf/dispatcher-servlet.xml文件中配置如下一句话即可

    <aop:aspectj-autoproxy />

    当然我们需要在xml的根目录beans下引用aop的命名空间和xsi

    
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="
      http://www.springframework.org/schema/aop
      http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
    • 2.2.2 使用@Aspect注解

    声明一个切面,只需要在类名上添加@Aspect属性即可,具体的连接点,我们用@Pointcut@Before@After等标注。具体如下

    在声明前 我们需要依赖配置pom

    
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjrt</artifactId>
        <version>1.6.11</version>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.6.11</version>
    </dependency>

    声明切面类,包含了注解@Aspect以及何时(如@Before)执行通知

    
    package com.ganji.demo.service.aspect;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.*;
    import org.springframework.stereotype.Service;
    
    /**
     * Created by admin on 2015/9/2.
     */
    @Aspect
    @Service
    public class XmlAopDemoUserLog {
    
    // 配置切点 及要传的参数
        @Pointcut("execution(* com.ganji.demo.service.user.UserService.GetDemoUser(..)) && args(id)")
        public void pointCut(int id)
        {
    
        }
    
    // 配置连接点 方法开始执行时通知
        @Before("pointCut(id)")
        public void beforeLog(int id) {
            System.out.println("开始执行前置通知  日志记录:"+id);
        }
    //    方法执行完后通知
        @After("pointCut(id)")
        public void afterLog(int id) {
            System.out.println("开始执行后置通知 日志记录:"+id);
        }
    //    执行成功后通知
        @AfterReturning("pointCut(id)")
        public void afterReturningLog(int id) {
            System.out.println("方法成功执行后通知 日志记录:"+id);
        }
    //    抛出异常后通知
        @AfterThrowing("pointCut(id)")
        public void afterThrowingLog(int id) {
            System.out.println("方法抛出异常后执行通知 日志记录"+id);
        }
    
    //    环绕通知
        @Around("pointCut(id)")
        public Object aroundLog(ProceedingJoinPoint joinpoint,int id) {
            Object result = null;
            try {
                System.out.println("环绕通知开始 日志记录"+id);
                long start = System.currentTimeMillis();
    
                //有返回参数 则需返回值
                result =  joinpoint.proceed();
    
                long end = System.currentTimeMillis();
                System.out.println("总共执行时长" + (end - start) + " 毫秒");
                System.out.println("环绕通知结束 日志记录");
            } catch (Throwable t) {
                System.out.println("出现错误");
            }
            return result;
        }
    }
    
    • 2.2.3 总结

    按照上述两个步骤,使用注解实现Aop即可,这里依赖了IOC。

原创文章

原文地址:https://www.cnblogs.com/yanduanduan/p/8397472.html

时间: 2024-10-06 03:05:46

Java Spring AOP用法的相关文章

Spring AOP用法详解

什么是AOP AOP:Aspect Oriented Programming,中文翻译为"面向切面编程".面向切面编程是一种编程范式,它作为OOP面向对象编程的一种补充,用于处理系统中分布于各个模块的横切关注点,比如事务管理.权限控制.缓存控制.日志打印等等.AOP采取横向抽取机制,取代了传统纵向继承体系的重复性代码 AOP把软件的功能模块分为两个部分:核心关注点和横切关注点.业务处理的主要功能为核心关注点,而非核心.需要拓展的功能为横切关注点.AOP的作用在于分离系统中的各种关注点,

[Java]Spring AOP基础知识-动态代理

Spring AOP使用动态代理技术在运行期织入增强的代码,为了揭示Spring AOP底层的工作机理,有必要对涉及到的Java知识进行学习.Spring AOP使用了两种代理机制:一种是基于JDK的动态代理:另一种是基于CGLib的动态代理.之所以需要两种代理机制,很大程度上是因为JDK本身只提供接口的代理,而不支持类的代理. 带有横切逻辑的实例 我们通过具体化代码实现上一节所介绍例子的性能监视横切逻辑,并通过动态代理技术对此进行改造.在调用每一个目标类方法时启动方法的性能监视,在目标类方法调

Java Spring AOP的两种配置方式

第一种:注解配置AOP java中注解配置AOP(使用 AspectJ 类库实现的),大致分为三步: 1. 使用注解@Aspect来定义一个切面,在切面中定义切入点(@Pointcut),通知类型(@Before, @AfterReturning,@After,@AfterThrowing,@Around).2. 开发需要被拦截的类.3. 将切面配置到xml中,当然,我们也可以使用自动扫描Bean的方式.这样的话,那就交由Spring AoP容器管理. 另外需要引用 aspectJ 的 jar

java spring 学习

Java Spring AOP用法 http://www.cnblogs.com/flowwind/p/4782606.html Java Spring IOC用法 http://www.cnblogs.com/flowwind/p/4772375.html 原文地址:https://www.cnblogs.com/lijiasnong/p/8393794.html

Spring AOP切点表达式用法总结

1. 简介 面向对象编程,也称为OOP(即Object Oriented Programming)最大的优点在于能够将业务模块进行封装,从而达到功能复用的目的.通过面向对象编程,不同的模板可以相互组装,从而实现更为复杂的业务模块,其结构形式可用下图表示: 面向对象编程解决了业务模块的封装复用的问题,但是对于某些模块,其本身并不独属于摸个业务模块,而是根据不同的情况,贯穿于某几个或全部的模块之间的.例如登录验证,其只开放几个可以不用登录的接口给用户使用(一般登录使用拦截器实现,但是其切面思想是一致

java框架篇---spring AOP 实现原理

什么是AOP AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善.OOP引入封装.继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合.当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力.也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系.例如日志功能.日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无

Java Spring的IoC和AOP的知识点速记

Spring简介 Spring解决的最核心的问题就是把对象之间的依赖关系转为用配置文件来管理,这个是通过Spring的依赖注入机制实现的. Spring Bean装配 1. IOC的概念以及在Spring容器中如何进行IOC的操作. IOC:Inversion of Control,控制反转.在Java开发中,IOC意味着将你设计好的类交给系统去控制,而不是在你的类内部控制,这称为控制反转,就是被调用类的实例由原先的调用类控制创建.销毁现在转变成由Spring的容器管理. 2. Spring容器

Java面试--Spring技术要点--Spring AOP(面向切面编程)

33  Spring AOP的概念 面向切面的编程,是一种编程技术,是OOP(面向对象编程)的补充和完善.OOP的执行是一种从上往下的流程,并没有从左到右的关系.因此在OOP编程中,会有大量的重复代码.而AOP则是将这些与业务无关的重复代码抽取出来,然后再嵌入到业务代码当中.常见的应用有:权限管理.日志.事务管理等. 实现AOP的技术,主要分为两大类:一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行:二是采用静态织入的方式,引入特定的语法创建"方面"

java框架篇---spring aop两种配置方式

第一种:注解配置AOP 注解配置AOP(使用 AspectJ 类库实现的),大致分为三步: 1. 使用注解@Aspect来定义一个切面,在切面中定义切入点(@Pointcut),通知类型(@Before, @AfterReturning,@After,@AfterThrowing,@Around). 2. 开发需要被拦截的类. 3. 将切面配置到xml中,当然,我们也可以使用自动扫描Bean的方式.这样的话,那就交由Spring AoP容器管理. 另外需要引用 aspectJ 的 jar 包: