酷站(www.ku0.com)-致力于为互联网从业者提供动力!

热门关键词:  企业  as  baidu  c4rp3nt3r  美女
【ECS精选特惠】新用户上云低至1折起
百度资源

Spring中基于xml的AOP的方法介绍

来源:互联网搜集 作者:秩名 人气: 发布时间:2020-06-20
本篇文章主要介绍了Spring中基于xml的AOP的方法介绍,对大家的学习或者工作具有一定的参考学习价值,感兴趣的小伙伴们可以参考一下,也感谢大家对酷站(ku0.com)的支持。

1、Aop 全程是Aspect Oriented Programming 即面向切面编程,通过预编译方式和运行期动态代理实现程序功能的同一维护的一种技术。Aop是oop的延续,是软件开发中的 一个热点,也是Spring框架中一个重要的内容。是函数式编程的一个衍生范例,利用Aop可以对业务逻辑各个部分进行分割,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用行,提高了开发效率。简单的说就是把我们程序中的重复代码抽取出来,在需要执行的时候,使用动态代理的技术,在不修改源码的基础上已有的方法进行增强,(使用动态代理的方式实现)

相关术语

JoinPoint:链接点 那些被拦截到的点,在spring中,这些点指的是方法,因为spring只支持方法类型的连接点

Pointcut:切入点 是指我们要对哪些JoinPont进行拦截的定义

Advice:通知/增强 拦截到Joinpoint之后所要做的事情就是通知

通知类型:前置通知、后置通知、异常通知、最终通知、环绕通知

Introduction:引介 是一种特殊的通知,在不修改类代码的前提下,Introduction可以在运行期为类动态的添加一些方法或field

Target:目标对象,代理的目标对象

Weaving织入 是指把增强应用到目标对象来创建新的代理对象的过程,spring采用动态代理织入,而AspectJ采用编译期织入和类装载期织入

Proxy:代理,一类类被Aop织入增强后,就产生一个结果代理类

Aspect:切面 是切入点和通知(引介)的结合

在 spring 中,框架会根据目标类是否实现了接口来决定采用哪种动态代理的方式。

基于XMl的AOP步骤

1、创建Maven项目引入spring坐标

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>com.mingqi</groupId>
 <artifactId>SpringIOC</artifactId>
 <packaging>pom</packaging>
 <version>1.0-SNAPSHOT</version>
 <dependencies>
 <dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>5.0.2.RELEASE</version>
 </dependency>
 <dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjweaver</artifactId>
  <version>1.8.7</version>
 </dependency>
 <dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.12</version>
  <scope>test</scope>
 </dependency>
 </dependencies>
</project>
 

2、创建业务层接口:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.mingqi.services;
public interface IAccountService {
 /**
 * 模拟登陆账户
 */
 void saveAccount();
 
 /**
 * 模拟更新账户
 * @param id
 */
 void updateAccount(int id);
 
 /**
 * 模拟删除账户
 * @return
 */
 int deleteAccount();
 
}
 

3.创建业务层实现类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.mingqi.services.impl;
import com.mingqi.services.IAccountService;
public class AccountServicesImpl implements IAccountService {
 public void saveAccount() {
 System.out.println("执行了保存");
 }
 
 public void updateAccount(int id) {
 System.out.println("执行了更新"+id);
 }
 
 public int deleteAccount() {
 System.out.println("执行了删除");
 return 0;
 }
}
 

4、创建工具类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package com.mingqi.utils;
import org.aspectj.lang.ProceedingJoinPoint;
/**
 * 用户记录日志的工具类,里面提供公共的代码
 */
public class Logger {
 /**
 * 用于打印日志:计划让其在切入点方法执行前执行(切入点方法就是业务层方法)
 */
 public void beforePrintLog(){
 System.out.println("Logger类中的pringLog方法开始记录日志了。。。");
 }
 public void afterReturningPrintLog()
 {
 System.out.println("后置通知Logger类中的beforePrintLog方法开始记录日志了。。。");
 }
 /**
 * 异常通知
 */
 public void afterThrowingPrintLog()
 {
 System.out.println("异常通知Logger类中的afterThrowingPrintLog方法开始记录日志了。。。");
 
 }
 /**
 * 最终通知
 */
 public void afterPrintLog()
 {
 System.out.println("最终通知Logger类中的afterPrintLog方法开始记录日志了。。。");
 }
 
 /**
 * 环绕通知
 * 问题 当我们配置了环绕通知以后,切入点方法没有执行,而通知方法执行了
 * 分析: 通过对比动态代理中的环绕通知代码,发现动态代理中的环绕通知有明确的切入点方法调用,而我们的代码中没有
 * 解决: Spring 框架为我们提供了一个接口:ProceedingJoinPoint。该接口有一个方法proceed(),此方法就相当于明确调用切入点的方法
 * 该接口可以作为环绕通知的参数方法,在程序执行时,spring框架会为我们提供该接口的实现类供我们使用
 * spring中的环绕通知
 * 他是spring框架为我们提供的一种可以在代码中手动控制增强方法何时会执行的方式
 * @param pjp
 * @return
 */
 public Object aroundPringLog(ProceedingJoinPoint pjp){
 Object rtValue = null;
 try{
  Object[] args = pjp.getArgs();//得到方法执行所需的参数
 
  System.out.println("Logger类中的aroundPringLog方法开始记录日志了。。。前置");
 
  rtValue = pjp.proceed(args);//明确调用业务层方法(切入点方法)
 
  System.out.println("Logger类中的aroundPringLog方法开始记录日志了。。。后置");
 
  return rtValue;
 }catch (Throwable t){
  System.out.println("Logger类中的aroundPringLog方法开始记录日志了。。。异常");
  throw new RuntimeException(t);
 }finally {
  System.out.println("Logger类中的aroundPringLog方法开始记录日志了。。。最终");
 }
 }
}
 

5、创建bean配置文件

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<?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">
 <!-- 配置spring的IOC,把service对象配置进来-->
 <bean id="accountSevice" class="com.mingqi.services.impl.AccountServicesImpl"></bean>
 <!-- spring 中基于xml的Aop配置步骤
  1、把通知Bean也交给spring来管理
  2、使用aop:config标签表名开始aop的配置
  3、使用aop:aspect标签表明配置切面
  id属性:是给切面提供一个唯一标识
  ref属性:是指定通知类的id
  4、在aop:aspect标签的内部使用对应的标签来配置通知的类型
  我们现在的示例是让printlog方法在切入点方法执行之前执行,所以是前置通知
  aop:before:标识前置通知
  method属性: 用于指定Logger类中的方法哪个是前置通知
  pointcut属性: 用于指定切入点表达式,该表达式的含义指的是对业务层中的哪些方法增强
  切入点表达式的写法:
   关键字:execution(表达式)
   表达式: 访问修饰符 返回值 包名.包名.包名....类名.方法名(参数列表)
   标准的写法: public void com.mingqi.service.impl.AccountServiceImpl.saveAccount()
   访问修饰符可以省略:void com.mingqi.service.impl.AccountServiceImpl.saveAccount()
   返回值可以使用通配符,标识任意返回值:* com.mingqi.service.impl.AccountServiceImpl.saveAccount()
   包名可以使用通配符,表示任意包,但是有几级包就需要写几个* *.*.*.*.*.AccountServiceImpl.saveAccount()
   包名可以使用..代表当前包及其子包:* *.AccountServiceImpl.saveAccount()
   类名和方法名都可以使用*来实现统配 * *..*.*();
   参数列表: 可以直接写数据类型:
     基本类型直接写名称:int
     引用类型写包名.类名的方式: java.lang.String
    可以使用通配符来标识任意类型,单必须有参数
    可以使用..标识有无参数均可,有参数可以是任意类型
 
   全通配写法:
   * *..*.*(..)
   实际开发中 切入点表达式的通常写法:
    切到业务层实现类的所有方法,* com.mingqi.service.impl.*.*(..);
  -->
 <!-- 配置Logger类-->
 <bean id="logger" class="com.mingqi.utils.Logger"></bean>
 <!--使用aop:config标签表名开始aop的配置-->
 <aop:config>
  <aop:pointcut id="pt1" expression="execution(* com.mingqi.services.impl.*.*(..))"></aop:pointcut>
  <!--使用aop:aspect标签表明配置切面-->
  <aop:aspect id="LogAdvice" ref="logger">
   <!-- 配置前置通知:在切入点方法执行之前执行
   <aop:before method="beforePrintLog" pointcut-ref="pt1"></aop:before>-->
 
   <!-- 配置后置通知:在切入点方法正常执行之后值。它和异常通知永远只能执行一个
    <aop:after-returning method="afterReturningPrintLog" pointcut-ref="pt1"></aop:after-returning>-->
   <!-- 配置异常通知:在切入点方法执行产生异常之后执行。它和后置通知永远只能执行一个
    <aop:after-throwing method="afterThrowingPrintLog" pointcut-ref="pt1"></aop:after-throwing>-->
   <!-- 配置最终通知:无论切入点方法是否正常执行它都会在其后面执行
   <aop:after method="afterPrintLog" pointcut-ref="pt1"></aop:after>-->
   <!-- 配置环绕通知 详细的注释请看Logger类中-->
   <aop:around method="aroundPringLog" pointcut-ref="pt1"></aop:around>
   </aop:aspect>
  </aop:config>
 </beans>
 

6、创建测试类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.mingqi.test;
import com.mingqi.services.IAccountService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringIoc {
 @Test
 public void TestAccount()
 {
 ApplicationContext ac= new ClassPathXmlApplicationContext("beam.xml");
 IAccountService accountService=(IAccountService) ac.getBean("accountSevice");
 accountService.saveAccount();
 accountService.updateAccount(22);
 accountService.deleteAccount();
 }
}

版权声明:本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 959677720#qq.cn(#换@) 举报,一经查实,本站将立刻删除。
原文链接:https://www.cnblogs.com/mingqi-420/p/13167414.html

相关文章

  • java原生动态生成验证码的方法

    java原生动态生成验证码的方法

    需求描述: 为了防止脚本多次请求,很多时候在注册会用到验证码,我们用java实现 一个图片验证的二维码。 项目结构 只有 标记的这三个文件是用到的 CheckServlet核心代码 package lhw.wanlin.checkimg; import javax.imageio.ImageIO;imp......
    10-12
  • 详解java数组与以逗号分隔开的字符串的相互转换操作

    详解java数组与以逗号分隔开的字符串的相互转换操作

    数组转换成以逗号分隔开的字符串 ? 1 2 3 String[] strArray = {aaa,bbb,ccc}; String str= StringUtils.join(strArry,,); System.out.println(str); String[] strArray = {aaa,bbb,ccc};String str= StringUtils.join(strArry,,);Syst......
    09-23
  • java中throws与throw的区别介绍

    java中throws与throw的区别介绍

    Java中throws和throw的区别讲解 当然,你需要明白异常在Java中式以一个对象来看待。 并且所有系统定义的编译和运行异常都可以由系统自动抛出,称为标准异常,但是一般情况下Java 强烈地要求应用程序进行完整的异常处理,给用户友好的提示......
    07-18
  • JAVA观察者模式的讲解

    JAVA观察者模式的讲解

    当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。观察者模式属于行为型模式。 介绍 意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有......
    06-23
  • Junit写法及与spring整合过程的介绍

    Junit写法及与spring整合过程的介绍

    junit之前的写法: //在Before中注入service类private IUserService userService; @Beforepublic void setUp() throws Exception {//使用xml的方式 ApplicationContext applicationContext = new ClassPathXmlApplicationContext(applica......
    06-20
  • Spring中基于xml的AOP的方法介绍

    Spring中基于xml的AOP的方法介绍

    1、Aop 全程是Aspect Oriented Programming 即面向切面编程,通过预编译方式和运行期动态代理实现程序功能的同一维护的一种技术。Aop是oop的延续,是软件开发中的 一个热点,也是Spring框架中一个重要的内容。是函数式编程的一个衍生范例......
    06-20
  • 使用用java实现分页查询

    使用用java实现分页查询

    1.基本思路 我现阶段的分页查询的实现是基于sql语句的。 select * from user where id limit a, b 构造出相应的a和b就可以查询出想要的数据,在显示在页面上。重点是要构造出当前的页数,就要封装一个javaBean,存储有关分页的基本属性。......
    06-11
  • Java二维数组查找功能的实现代码

    Java二维数组查找功能的实现代码

    题目描述: 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。 题目分析: 根据......
    06-11
  • Java规则引擎Easy Rules的使用

    Java规则引擎Easy Rules的使用

    1. Easy Rules 概述 规则引擎就是提供一种可选的计算模型。与通常的命令式模型(由带有条件和循环的命令依次组成)不同,规则引擎基于生产规则系统。这是一组生产规则,每条规则都有一个条件(condition)和一个动作(action) 简单地说......
    06-11
  • Spring Security实现短信验证码登录功能的教程

    Spring Security实现短信验证码登录功能的教程

    开发短信验证码接口 获取验证码 短信验证码的发送获取逻辑和图片验证码类似,这里直接贴出代码。 ? 1 2 3 4 5 6 7 8 9 10 @GetMapping ( /code/sms ) public void createSmsCode(HttpServletRequest request, HttpServletResponse respon......
    05-20

最新更新