【Spring开发】—— AOP之方法级拦截

简介:

前言:

前面介绍了Spring的核心模块以及相关的依赖注入等概念。这篇讲解一下spring的另一个重点,AOP面向切面编程。

  说道AOP不得不提到几个概念:

  切面:也就是我们自己的一些业务方法。

  通知:用于拦截时出发的操作。

  切点:具体拦截的某个业务点。

  这样说可能还是有点抽象,举个例子,下面是一个纸糊的多面体。

  每个面都是一个业务方法,我们通过刺穿每一个面,都可以进入到内部,这个面就是一个切面

  刺穿的时候会发出声响,这就是一种通知

  而具体从哪个面刺入,这就是一个切入点的选择了。

  这样说,应该能稍微了解一点。

 

  那么下面看一个简单的例子:

  为了便于理清关系,先放上一张相关的类图:

  首先定义个接口

1 public interface IService {
2  public void withAop();
3  public void withoutAop();
4 }

  有了接口,当然需要一个实现类

复制代码
 1 public class TestAOP implements IService {
 2  private String name;
 3  public void withAop() {
 4   System.out.println("with AOP name:"+name);
 5  }
 6  public void withoutAop() {
 7   System.out.println("without AOP name:"+name);
 8  }
 9  public String getName() {
10   return name;
11  }
12  public void setName(String name) {
13   this.name = name;
14  }
15 }
复制代码

  这个实现类实现了接口定义的两个方法,下面我们定义几种拦截方式,这些拦截方式通过拦截的位置或者时机不同而不同。

  通常有方法前拦截方法后拦截,以及异常拦截。通过在这些拦截中编写自己的业务处理,可以达到特定的需求。

  方法前拦截,需要实现MethodBeforeAdvice接口,并填写before方法。这样,当拦截到某个方法时,就会在方法执行前执行这个before()方法。

复制代码
1 public class BeforeAOPInterceptor implements MethodBeforeAdvice{
2  public void before(Method method, Object[] args, Object instance)
3    throws Throwable {
4   System.out.println("before()"+method.getName());
5  }
6 }
复制代码

  同理,方法后拦截,也是如此。需要实现AfterReturningAdvice接口。

复制代码
1 public class AfterAOPInterceptor implements AfterReturningAdvice{
2  public void afterReturning(Object value, Method method, Object[] args,
3    Object instance) throws Throwable {
4   System.out.println("after()"+method.getName());
5  }
6 }
复制代码

  以及异常拦截。

复制代码
1 public class ThrowsAOPInterceptor implements ThrowsAdvice{ 
2  public void afterThrowing(Method method,Object[] args,Object instance,AccountException ex) throws Throwable{
3   System.out.println("after()"+method.getName()+"throws exception:"+ex);
4  }
5  public void afterThrowing(NullPointerException ex) throws Throwable{
6   System.out.println("throws exception:"+ex);
7  }
8 }
复制代码

  接下来就需要配置一下spring的配置文件,把拦截器与切面方法关联起来。

  参考上面的图,可以看到配置文件中的层次关系。

复制代码
 1 <?xml version="1.0" encoding="UTF-8"?> 
 2 <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 3 xmlns="http://www.springframework.org/schema/beans" 
 4 xsi:schemaLocation="http://www.springframework.org/schema/beans 
 5 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> 
 6 <!-- 通过名字匹配 --> 
 7 <!-- 
 8   <bean id="before" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor"> 
 9     <property name="advice"> 
10       <bean class="com.test.pointcut.beforeAOP"></bean> 
11     </property> 
12     <property name="mappedName" value="withoutAop"></property> 
13   </bean> 
14 --> 
15 <!-- 通过正则表达式 匹配 --> 
16   <bean id="before" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> 
17     <property name="advice"> 
18       <bean class="com.test.pointcut.BeforeAOPInterceptor"></bean> 
19     </property> 
20   <property name="patterns"> 
21     <list> 
22       <value>.*out.*</value> 
23     </list> 
24   </property> 
25   </bean> 
26   <bean id="after" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> 
27     <property name="advice"> 
28       <bean class="com.test.pointcut.AfterAOPInterceptor"></bean> 
29     </property> 
30     <property name="patterns"> 
31       <list> 
32         <value>.*out.*</value> 
33       </list> 
34     </property> 
35   </bean> 
36   <bean id="exception" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> 
37     <property name="advice"> 
38       <bean class="com.test.pointcut.ThrowsAOPInterceptor"></bean> 
39     </property> 
40     <property name="patterns"> 
41       <list> 
42         <value>.*out.*</value> 
43       </list> 
44     </property> 
45   </bean> 
46 <!-- --> 
47   <bean id="aopService" class="org.springframework.aop.framework.ProxyFactoryBean"> 
48     <property name="interceptorNames"> 
49       <list> 
50         <value>before</value> 
51         <value>after</value> 
52         <value>exception</value> 
53       </list> 
54     </property> 
55     <property name="target"> 
56       <bean class="com.test.pointcut.TestAOP"> 
57         <property name="name" value="Hello"></property> 
58       </bean> 
59     </property> 
60   </bean> 
61 </beans>
复制代码

  ProxyFactoryBean下有两个属性,一个想要拦截的目标类,一个是拦截器。而拦截器又包括两种,主要是因为定位方法的不同而分类。分别是:

  RegexpMethodPointcutAdvisor 通过正则表达式来定位业务方法。

  NameMatchMethodPointcutAdvisor 通过名字来定位业务方法。

  定位到了业务方法,还需要添加响应的拦截器,拦截器就是上面的三种。

  最后看一下测试的方法:

复制代码
public class TestMain {
 public static void main(String[] args) {
  XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("applicationContextAOP.xml"));
  IService hello = (IService)factory.getBean("aopService");
  hello.withAop();
  hello.withoutAop();
 }
}
复制代码

  我们上面通过正则表达式定位到所有包含out的方法,其实就是withoutAOP方法。这样当执行withoutAop方法时,会触发拦截器的操作。

  执行结果:

复制代码
2014-12-4 16:46:58 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [applicationContextAOP.xml]
with AOP name:Hello
before()withoutAop
without AOP name:Hello
after()withoutAop
复制代码

  总结:

  这是通过定义切入点的方式来实现AOP,通过这种编程方式,可以针对业务方法进行包装或者监控

  举个例子,比如有个业务方法想要进行数据的查询,那么可以再这个查询前面获取JDBC连接池的连接,这样就对用户屏蔽掉了复杂的申请过程。而销毁就可以放在方法后拦截函数里。

  再比如,想要监控某个业务方法呗执行了多少次,那么就可以通过这样一种拦截方式,进行信息的统计,计数或者计时!

  妙处多多,还待完善!

  参考:《java web王者归来》《spring实战》《spring权威指南》

本文转自博客园xingoo的博客,原文链接:【Spring开发】—— AOP之方法级拦截,如需转载请自行联系原博主。
相关文章
|
7天前
|
设计模式 Java 测试技术
spring复习04,静态代理动态代理,AOP
这篇文章讲解了Java代理模式的相关知识,包括静态代理和动态代理(JDK动态代理和CGLIB),以及AOP(面向切面编程)的概念和在Spring框架中的应用。文章还提供了详细的示例代码,演示了如何使用Spring AOP进行方法增强和代理对象的创建。
spring复习04,静态代理动态代理,AOP
|
9天前
|
Java 应用服务中间件 Spring
IDEA 工具 启动 spring boot 的 main 方法报错。已解决
IDEA 工具 启动 spring boot 的 main 方法报错。已解决
|
8天前
|
前端开发 Java Spring
关于spring mvc 的 addPathPatterns 拦截配置常见问题
关于spring mvc 的 addPathPatterns 拦截配置常见问题
|
21天前
|
Java 数据库连接 数据库
Spring基础3——AOP,事务管理
AOP简介、入门案例、工作流程、切入点表达式、环绕通知、通知获取参数或返回值或异常、事务管理
Spring基础3——AOP,事务管理
|
2月前
|
缓存 Java 开发者
Spring高手之路22——AOP切面类的封装与解析
本篇文章深入解析了Spring AOP的工作机制,包括Advisor和TargetSource的构建与作用。通过详尽的源码分析和实际案例,帮助开发者全面理解AOP的核心技术,提升在实际项目中的应用能力。
23 0
Spring高手之路22——AOP切面类的封装与解析
|
2月前
|
安全 Java 应用服务中间件
如何在 Spring Boot 3.3 中实现请求 IP 白名单拦截功能
【8月更文挑战第30天】在构建Web应用时,确保应用的安全性是至关重要的。其中,对访问者的IP地址进行限制是一种常见的安全措施,特别是通过实施IP白名单策略,可以只允许特定的IP地址或IP段访问应用,从而有效防止未授权的访问。在Spring Boot 3.3中,我们可以通过多种方式实现这一功能,下面将详细介绍几种实用的方法。
87 1
|
2月前
|
Java Spring XML
掌握面向切面编程的秘密武器:Spring AOP 让你的代码优雅转身,横切关注点再也不是难题!
【8月更文挑战第31天】面向切面编程(AOP)通过切面封装横切关注点,如日志记录、事务管理等,使业务逻辑更清晰。Spring AOP提供强大工具,无需在业务代码中硬编码这些功能。本文将深入探讨Spring AOP的概念、工作原理及实际应用,展示如何通过基于注解的配置创建切面,优化代码结构并提高可维护性。通过示例说明如何定义切面类、通知方法及其应用时机,实现方法调用前后的日志记录,展示AOP在分离关注点和添加新功能方面的优势。
38 0
|
2月前
|
缓存 安全 Java
Spring AOP 中两种代理类型的限制
【8月更文挑战第22天】
16 0
|
7天前
|
SQL 监控 druid
springboot-druid数据源的配置方式及配置后台监控-自定义和导入stater(推荐-简单方便使用)两种方式配置druid数据源
这篇文章介绍了如何在Spring Boot项目中配置和监控Druid数据源,包括自定义配置和使用Spring Boot Starter两种方法。
|
2月前
|
缓存 Java Maven
Java本地高性能缓存实践问题之SpringBoot中引入Caffeine作为缓存库的问题如何解决
Java本地高性能缓存实践问题之SpringBoot中引入Caffeine作为缓存库的问题如何解决
下一篇
无影云桌面