面向切面编程,有效的降低了代码之间的耦合性,易于维护;例如:我们习惯在代码中加上一些日志信息,在程序出错时方便快速查找找到问题,通常做法是在请求进入方法的时候打印日志,退出前打印日志,还有在出错时打印日志,那么问题就来了,每个方法中都需要打印日志,这些相同的部分就可以当做一个切面,通过配置切点来触发所需要的功能,比如,我需要在请求进入方法的时候打印,即可使用aop当中的前置通知来做到,这样就不需要每个方法中都去写一遍,配置好之后引用即可。

  简单的记录一下spring aop的一个示例

  基于两种配置方式:

      1:基于xml配置

      2:基于注解配置

  这个例子是模拟对数据库的更改操作添加事物

  其实并没有添加,只是简单的输出了一下记录

  首先看下整个例子的目录图

  

全部代码就不贴了,数目有点多,不过很简单,看一部分就能够明白

第一种配置方式

  基于xml方式配置

  首先将service,dao注册到spring容器

  

  配置一下扫描包还是很方便的

  接下来看下service 

package com.yangxin.core.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import com.yangxin.core.dao.UserDao;
import com.yangxin.core.pojo.User;
import com.yangxin.core.service.UserService; @Service
public class UserServiceImpl implements UserService { @Autowired
private UserDao userDao; @Override
public void addUser(User user) {
userDao.insertUser(user);
System.out.println("添加成功");
} @Override
public void deleteUser(String name) {
userDao.deteleUser(name);
System.out.println("删除成功");
} }

要做的事情很简单,插入一条数据,删除一条数据

接下来看下切面代码

package com.yangxin.core.transaction;

import org.aspectj.lang.ProceedingJoinPoint;

import com.yangxin.core.pojo.User;

public class TransactionDemo {

    //前置通知
public void startTransaction(){
System.out.println("begin transaction ");
} //后置通知
public void commitTransaction(){
System.out.println("commit transaction ");
} //环绕通知
public void around(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("begin transaction");
//调用process()方法才会真正的执行实际被代理的方法
joinPoint.proceed(); System.out.println("commit transaction");
} }

然后看下这个切面在applicationContext.xml中是如何配置的

<aop:config>
  <aop:pointcut expression="execution(* com.yangxin.core.service.*.*.*(..))" id="p1" /> <!--切点-->
  <aop:aspect ref = "transactionDemo"> <!--切面 -->
    <aop:before method="startTransaction" pointcut-ref="p1" /> <!--前置通知-->
    <aop:after-returning method="commitTransaction" pointcut-ref="p1"/> <!--后置通知-->
  </aop:aspect>
</aop:config>

这里没有演示环绕通知

好了,运行测试代码

测试代码如下

@Test
public void test1(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring/applicationContext.xml"); UserService userService = applicationContext.getBean(UserService.class); User user = new User(); user.setAge(19);
user.setName("yangxin"); userService.addUser(user);
userService.deteleUser("yangxin"); }

控制台输出如下

  begin transaction

  添加成功

  commit transaction

  begin transaction

  删除成功

  commit transaction

现在来测试一下环绕通知

修改一下applicationContext.xml中的配置切面那一部分

修改后的代码

<aop:config>
  <aop:pointcut expression="execution(* com.yangxin.core.service.*.*.*(..))" id="p1" />
  <aop:aspect ref = "transactionDemo">
    <aop:around method="around" pointcut-ref="p1"/>
  </aop:aspect>
</aop:config>

运行测试代码

输出如下

begin transaction
添加成功
commit transaction
begin transaction
删除成功
commit transaction

好了,现在贴下如何用注解的方法

贴下基于注解的切面的代码

package com.yangxin.core.transaction;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut; @Aspect
public class TransactionDemo2 { @Pointcut(value="execution(* com.yangxin.core.service.*.*.*(..))")
public void point(){ } @Before(value="point()")
public void before(){
System.out.println("transaction begin");
} @AfterReturning(value = "point()")
public void after(){
System.out.println("transaction commit");
} @Around("point()")
public void around(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("transaction begin");
joinPoint.proceed();
System.out.println("transaction commit"); }
}

在applicationContext.xml中配置

<bean id = "transactionDemo2" class = "com.yangxin.core.transaction.TransactionDemo2" />
<aop:aspectj-autoproxy />

测试步骤和以上一致,这里就不贴了

结合例子我们来看看这些核心的概念:

  2.1、切面(Aspect):是一个类,里面定义了通知与切点。

  2.2、切点(PointCut):表达式。就是告诉程序要在执行哪些核心业务的时候,执行非核心的业务。

  2.3、通知(advice):五种通知方式:

    • @Before:前置通知,在调用目标方法之前执行通知定义的任务
    • @After:后置通知,在目标方法执行结束后,无论执行结果如何都执行通知定义的任务
    • @After-returning:后置通知,在目标方法执行结束后,如果执行成功,则执行通知定义的任务
    • @After-throwing:异常通知,如果目标方法执行过程中抛出异常,则执行通知定义的任务
    • @Around:环绕通知,在目标方法执行前和执行后,都需要执行通知定义的任务。

Spring aop 实例(转)的更多相关文章

  1. Spring Aop实例@Aspect、@Before、@AfterReturning@Around 注解方式配置

    用过spring框架进行开发的人,多多少少会使用过它的AOP功能,都知道有@Before.@Around和@After等advice.最近,为了实现项目中的输出日志和权限控制这两个需求,我也使用到了A ...

  2. Spring AOP实例——异常处理和记录程序执行时间

    实例简介: 这个实例主要用于在一个系统的所有方法执行过程中出线异常时,把异常信息都记录下来,另外记录每个方法的执行时间. 用两个业务逻辑来说明上述功能,这两个业务逻辑首先使用Spring AOP的自动 ...

  3. Spring学习十四----------Spring AOP实例

    © 版权声明:本文为博主原创文章,转载请注明出处 实例 1.项目结构 2.pom.xml <project xmlns="http://maven.apache.org/POM/4.0 ...

  4. Spring Aop实例

    一.XML方式 1. TestAspect:切面类 package com.spring.aop; import org.aspectj.lang.JoinPoint; import org.aspe ...

  5. Spring学习(十六)----- Spring AOP实例(Pointcut(切点),Advisor)

    在上一个Spring AOP通知的例子,一个类的整个方法被自动拦截.但在大多数情况下,可能只需要一种方式来拦截一个或两个方法,这就是为什么引入'切入点'的原因.它允许你通过它的方法名来拦截方法.另外, ...

  6. Spring Aop实例@Aspect、@Before、@AfterReturning@Around 注解方式配置(转)

    用过spring框架进行开发的人,多多少少会使用过它的AOP功能,都知道有@Before.@Around和@After等advice.最近,为了实现项目中的输出日志和权限控制这两个需求,我也使用到了A ...

  7. Spring Aop实例之xml配置

    AOP的配置方式有2种方式:xml配置和AspectJ注解方式.今天我们就来实践一下xml配置方式. 我采用的jdk代理,所以首先将接口和实现类代码附上 package com.tgb.aop; pu ...

  8. Spring学习笔记IOC与AOP实例

    Spring框架核心由两部分组成: 第一部分是反向控制(IOC),也叫依赖注入(DI); 控制反转(依赖注入)的主要内容是指:只描述程序中对象的被创建方式但不显示的创建对象.在以XML语言描述的配置文 ...

  9. Spring AOP 系列总括

    Spring有两大核心,IOC和AOP.IOC在Java Web项目中无时无刻不在使用,然而AOP用的比较少,尤其是对一些初级程序员,在架构师搭好的框架上开发应用代码,AOP几乎是透明的.然而,项目中 ...

随机推荐

  1. mysql jdbcTemplate访问

    String sql = "select * from xxx_photo_info where user_id in (:userIds)"; userIds从dao传过来时必须 ...

  2. php如何实现大文件断点续传-php文件

    总结一下大文件分片上传和断点续传的问题.因为文件过大(比如1G以上),必须要考虑上传过程网络中断的情况.http的网络请求中本身就已经具备了分片上传功能,当传输的文件比较大时,http协议自动会将文件 ...

  3. Anaconda安装PyTorch

    Anaconda是一个Python语言管理器,支持安装基于Python的开发包,例如tensorflow.Pytorch等,以及各种基于Python的IDE. https://www.jb51.net ...

  4. 【转】jqprint打印时自定义页眉页脚

    需求:自定义页眉,实现打印时分页时每页页眉都显示相同的信息 打印所用插件jqprint 解决方法: <div class="divHeader"> <span s ...

  5. Redis缓存雪崩和缓存穿透等问题

    穿透 缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,造成缓存穿透. 解决办法:①用一个bitma ...

  6. JAVA 第十一周学习总结

    20175308 2018-2019-2 <Java程序设计>第十一周学习总结 教材学习内容总结 13.1 URL类: URL类是java.net包中的一个类,用URL创建的对象可以获取U ...

  7. 关于Qt 构建套件(Kit) 编译器 自动识别不正确 不能修改的问题

    当系统内有多个Qt的版本的时候,QtCreater会自动识别出 编译器,Qt版本,和构建套件(Kit),但是有时候会发现,识别出来的路径不对,而且不能修改. 当出现这是问题的时候,可以到 qtcrea ...

  8. Android Studio 安装 Flutter

    1 下载sdk https://flutter.dev/docs/get-started/install/windows   2 解压到自定义文件夹,并配置bin路径到环境变量path中 path添加 ...

  9. 四十、python中的生成器和迭代器

    A.生成器(包含yield的就是生成器) def func(): print(11) yield 1 print(22) yield 2 print(33) yield 3 print(44) yie ...

  10. 中国MOOC_零基础学Java语言_第3周 循环_2数字特征值

    2 数字特征值(5分) 题目内容: 对数字求特征值是常用的编码算法,奇偶特征是一种简单的特征值.对于一个整数,从个位开始对每一位数字编号,个位是1号,十位是2号,以此类推.这个整数在第n位上的数字记作 ...