Spring总结六:AOP(面向切面编程)

概述:

  AOP(Aspect-Oriented Programming,面向切面的编程),它是可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。它是一种新的方法论,它是对传统OOP编程的一种补充。AOP是希望能够将通用需求功能从不相关的类当中分离出来,能够使得很多类共享一个行为,一旦发生变化,不必修改很多类,而只需要修改这个行为即可。

  AOP就是将公用功能提取出来,如果以后公用功能的需求发生变化,只需要改动公用的模块的代码即可,多个调用的地方则不需要改动。所谓面向切面,就是只关注通用功能,而不关注业务逻辑。实现方式一般是通过拦截。一般应用在日志记录,权限验证,异常拦截等。

  1,Aspect(切面):通常是一个类,里面可以定义切入点和通知
  2,JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用
  3,Advice(通知):AOP在特定的切入点上执行的增强处理,有before,after,afterReturning,afterThrowing,around
  4,Pointcut(切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式
  5,AOP代理:AOP框架创建的对象,代理就是目标对象的加强。Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类,原理我们后面有时间再写一篇博客。

好了,我们先通过例子来了解一下基于xml配置的AOP:

简单的实现转账功能,刘德华给张学友转账10000元:

首先我们把pom.xml中需要包引进去(我是通过父工程管理的jar包版本,所以没有写版本信息):

<dependencies>
    <!--spring需要的包-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
    </dependency>
    <!--junit-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
    </dependency>
</dependencies>

我们的dao和service代码:

public class AccountDao {
    /**
     * 转入方法
     */
    public void shiftto(){
        System.out.println("张学友的账户转入了 10000...");
    }

    /**
     * 转出方法
     */
    public void rollout(){
        System.out.println("刘德华的账户转出了 10000...");
    }
}

public class AccountService {

    private AccountDao accountDao;

    /**
     * 基于xml配置 提供一个set方法
     */
    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }

    /**
     * 转账方法
     */
    public String transfer() {
        //转出
        accountDao.rollout();
        //转入
        accountDao.shiftto();
        return "我是AccountService类的transfer方法的返回值";
    }
}

然后配置spring配置文件中对应的bean:

    <!--目标类-->
    <bean id="accountDao" class="com.zy.dao.AccountDao"></bean>
    <bean id="accountService" class="com.zy.service.AccountService">
        <property name="accountDao" ref="accountDao"></property>
    </bean>

如果只有上面这些的话(不使用AOP的情况),我们可以通过测试代码:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class AccountServiceTest {
    @Value("#{accountService}")
    private AccountService service;

    @Test
    public void transfer() throws Exception {
        service.transfer();
    }

}

得出的结果如下:

那么如果现在我们要把转账的功能放在事务里的话,正常情况下需要在实现的service中加入事务的代码,但是使用AOP的话我们可以这样做:

新建自己的AsPect类:

public class MyAspect {
    /**
     * before 前置通知方法
     */
    public void before(JoinPoint joinPoint) {
        System.out.println("---------------由" + joinPoint.getTarget().getClass().getSimpleName() + "类开启事务");
    }

    /**
     * afterReturning 后置通知方法
     */
    public void afterReturning(JoinPoint joinPoint, Object returnVal) {
        System.out.println("---------------提交事务,返回值为:" + returnVal);
    }

    /**
     * after 最终通知方法
     */
    public void after(JoinPoint joinPoint) {
        System.out.println("---------------释放资源");
    }

    /**
     * afterThrowing 后置异常通知方法
     */
    public void afterThrowing(JoinPoint joinPoint, Throwable ex) {
        System.out.println("---------------事务回滚,程序异常信息:" + ex.getMessage());
    }
}

这个时候 我们需要在spring配置文件applicationContext.xml中这样配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       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 id="accountDao" class="com.zy.dao.AccountDao"></bean>
    <bean id="accountService" class="com.zy.service.AccountService">
        <property name="accountDao" ref="accountDao"></property>
    </bean>
    <!--切面类:里面可以有多个增强目标类的方法-->
    <bean id="myAspect" class="com.zy.aspect.MyAspect"></bean>

    <!--配置目标类和切面类的关系-->
    <aop:config proxy-target-class="false">
        <!--配置切面:指定增强方法的位置-->
        <aop:aspect ref="myAspect">
            <!--配置切入点-->
            <aop:pointcut id="myPointcut" expression="bean(*Service)"></aop:pointcut>
            <!--配置切入点和增强方法的联系-->
            <!--before 前置通知-->
            <aop:before method="before" pointcut-ref="myPointcut"></aop:before>
            <!--afterReturning 后置通知 可能有返回值 returnVal要和方法的形参名称一致-->
            <aop:after-returning method="afterReturning" pointcut-ref="myPointcut"
                                 returning="returnVal"></aop:after-returning>
            <!--after 最终通知-->
            <aop:after method="after" pointcut-ref="myPointcut"></aop:after>
            <!--后置异常通知-->
            <aop:after-throwing method="afterThrowing" pointcut-ref="myPointcut" throwing="ex"></aop:after-throwing>
        </aop:aspect>
    </aop:config>
</beans>

最后再运行我们的测试代码会得出以下结果:

这样我们就把事务加进去了,这样做最大的好处就是可以随时把事务去掉或者是修改其实现代码。

原文地址:https://www.cnblogs.com/Alex-zqzy/p/9310859.html

时间: 2024-08-08 02:50:09

Spring总结六:AOP(面向切面编程)的相关文章

深入分析JavaWeb Item54 -- Spring中的AOP面向切面编程2

一.在Advice方法中获取目标方法的参数 1.获取目标方法的信息 访问目标方法最简单的做法是定义增强处理方法时,将第一个参数定义为JoinPoint类型,当该增强处理方法被调用时,该JoinPoint参数就代表了织入增强处理的连接点.JoinPoint里包含了如下几个常用的方法: Object[] getArgs:返回目标方法的参数 Signature getSignature:返回目标方法的签名 Object getTarget:返回被织入增强处理的目标对象 Object getThis:返

spring学习之aop(面向切面编程)

AOP术语学习: Aspect:切面,封装用于横向插入系统功能(事务,日志)的类 Joinpoint:连接点,在程序执行过程中的某个阶段点 Pointcut:切入点,切面与程序流程的交叉点,即那些需要处理的连接点. Advice:在定义好的切入点所要执行的程序代码,可以理解为切面类中的方法. Target Object:通知的对象,如果aop采用的是动态aop实现,该对象就是一个被代理对象. Proxy:代理,将通知应用到目标对象之后,被动态创建的对象. Weaving:织入,将切面代码插入到目

Spring AOP 面向切面编程

AOP 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型.利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率. 在Spring中提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例

sprint.net(2) AOP面向切面编程,spring.net的环绕通知;Spring.net的AOP通知的四种类型

AOP 有点类似于我们MVC里面的Filter过滤器,例如在MVC里面,如果给一个Action上打一个标签,就可以在这个Action执行之前或者之后,额外的执行一个方法,这个就相当于是面向切面编程. 无侵入式的. (也就是在不改变原来的代码的情况下,来跳转到一个其他的方法,执行完毕后回到主方法..),但是spring.net的AOP更牛叉,只需要在xml里面配置,就可以了,不需要在方法上面打特性的标签,也不需要继承什么类(例如MVC的过滤器是继承了ActionFilterAttribute) 主

深入探索spring技术内幕(七): 配置Spring AOP面向切面编程

一. AOP一些概念 Aspect( 切面 ): 指横切性关注点的抽象即为切面, 它与类相似, 只是两者的关注点不一样, 类是对物体特征的抽象, 而切面横切性关注点的抽象. joinpoint( 连接点 ): 指那些被拦截到的点. 在spring中, 这些点指的是方法, 因为spring只支持方法类型的连接点, 实际上joinpoint还可以是field或类构造器) Pointcut( 切入点 ): 指我们要对那些joinpoint进行拦截的定义. Advice( 通知 ): 指拦截到joinp

spring入门-AOP 面向切面编程

AOP 面向切面编程 在日常开发中最后将业务逻辑定义在一个专门的service包下,而实现定义在service包下的impl包中, 服务接口以IXXXService形式,而服务实现就是XXXService,这就是规约设计 步骤: 1.E:\Users\WorkSpaces\KmwalletApp\spring\aop\test\HelloWorldService.java 继承(implements)xx接口 2.E:\Users\WorkSpaces\KmwalletApp\spring\ao

浅谈Spring AOP 面向切面编程 最通俗易懂的画图理解AOP、AOP通知执行顺序~

简介 我们都知道,Spring 框架作为后端主流框架之一,最有特点的三部分就是IOC控制反转.依赖注入.以及AOP切面.当然AOP作为一个Spring 的重要组成模块,当然IOC是不依赖于Spring框架的,这就说明你有权选择是否要用AOP来完成一些业务. AOP面向切面编程,通过另一种思考的方式,来弥补面向对象编程OOP当中的不足,OOP当中最重要的单元是类,所以万物皆对象,万物皆是 对象类.而在AOP的模块单元中,最基础的单元是切面,切面对切点进行模块化的管理. 最后再提一句:Spring当

Spring:AOP, 面向切面编程

AOP概述 什么是AOP, 面向切面编程 AOP为Aspect Oriented Programming的缩写, 意为:面向切面编程, 通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术. AOP是OOP的延续, 是函数式编程的一种衍生范型. 利用AOP可以对业务逻辑的各个部分进行隔离, 从而使得业务逻辑各部分之间的耦合度降低, 提高程序的可重用性, 同时提高了开发的效率. - 传统开发模型: 纵向的编程.  面向切面编程: 纵横配合的编程. AOP的作用及优势 作用: 在程序运行期

Javascript aop(面向切面编程)之around(环绕)

Aop又叫面向切面编程,其中“通知”是切面的具体实现,分为before(前置通知).after(后置通知).around(环绕通知),用过spring的同学肯定对它非常熟悉,而在js中,AOP是一个被严重忽视的技术点.但是利用aop可以有效的改善js代码逻辑,比如前端框架dojo和yui3中AOP则被提升至自定义事件的一种内在机制,在源码中随处可见.得益于这种抽象使得dojo的自定义事件异常强大和灵活.dojo中aop的实现在dojo/aspect模块中,主要有三个方法:before.after

java aop面向切面编程

最近一直在学java的spring boot,一直没有弄明白aop面向切面编程是什么意思.看到一篇文章写得很清楚,终于弄明白了,原来跟python的装饰器一样的效果.http://www.cnblogs.com/yanbincn/archive/2012/06/01/2530377.html Aspect Oriented Programming  面向切面编程.解耦是程序员编码开发过程中一直追求的.AOP也是为了解耦所诞生. 具体思想是:定义一个切面,在切面的纵向定义处理方法,处理完成之后,回