【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之方法级拦截,如需转载请自行联系原博主。

时间: 2024-10-22 11:00:44

【Spring开发】—— AOP之方法级拦截的相关文章

eclipse + JBoss 5 + EJB3开发指南(15):拦截器方法和拦截器类

一.拦截器方法 EJB3可以通过拦截器对Bean方法进行拦截和覆盖.这有些象AOP中的around.通过AOP的around方法, 可以修改被拦截方法的返回值.参数值,甚至可以取消被拦截方法的执行.EJB3的拦截器可以用在无状态 Session Bean.有状态Session Bean和消息驱动Bean(MDB)的方法中.实现拦截器的最简单的方法是使 用拦截器方法.也就是说,只要在当前的Bean中使用@AroundInvoke对某个方法进行注释(关于拦截器的 类都在javax.intercept

spring mvc aop获取controller中的方法中的参数名称

问题描述 spring mvc aop获取controller中的方法中的参数名称 //配置切入点,该方法无方法体,主要为方便同类中其他方法使用此处配置的切入点 //"execution(* com.nong.aop.*.controller..*.*(..))" /*@Pointcut("execution(* com.nong.aop.*.controller.*(..))") public void aspect(){} // 配置前置通知,使用在方法aspe

利用Spring AOP记录方法的执行时间_java

一.前言 对于spring aop这个我就不多介绍了,网上一搜一大把,使用过spring的人都知道spring的ioc和aop.ioc我们常用,但在我们自己的系统中,aop的使用几乎为零,除了这个监控的小功能应用到了,其他的基本上没有使用到.下面小编就给大家整理下利用Spring AOP记录方法执行时间的解决方案,有需要的一起看看吧. 二.解决方案 1.传统方法 最简单.粗暴的方法是给各个需要统计的方法开始和结尾处加的时间戳,然后差值计算结果即可,代码如下: long startTime = S

【Spring开发】—— Spring Core

前言 最近由于一些工作的需要,还有自己知识的匮乏再次翻开spring.正好整理了一下相关的知识,弥补了之前对spring的一些错误认知.这一次学习,更加深入的理解了Ioc和AOP的思想,并对其架构模块有了更深一步的理解. 刚开始翻看spring技术内幕,虽然有了一点看源码的经验,但是直接看如此深的源码,还是很头疼.spring由于业务的扩展,以及用户群的增加,对于某些模块的类封装的很深!因此追溯源码是个很头疼的问题,而直接看这本书,也是压力山大. 于是回去复习一下spring的基本知识,先学会走

Spring AOP从入门到放弃之概念以及Spring Boot AOP demo

本文小福利 点我获取阿里云优惠券 AOP核心概念 1.横切关注点 对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点 2.切面(aspect)->(通知+切点) 类是对物体特征的抽象,切面就是对横切关注点的抽象. 通知+切点 意思就是所有要被应用到增强(advice)代码的地方.(包括方法的方位信息) 3.连接点(joinpoint)->(被拦截的方法) 被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截的方法,实际上连接点还可以是字段或

Spring中的AOP(二)——AOP基本概念和Spring对AOP的支持

AOP的基本概念     AOP从运行的角度考虑程序的流程,提取业务处理过程的切面.AOP面向的是程序运行中的各个步骤,希望以更好的方式来组合业务逻辑的各个步骤.AOP框架并不与特定的代码耦合,AOP框架能处理程序执行中特定切入点,而不与具体某个类耦合(即在不污染某个类的情况下,处理这个类相关的切点).下面是一些AOP的一些术语:     切面(Aspect):业务流程运行的某个特定步骤,也就是应用运行过程的关注点,关注点通常会横切多个对象,因此常被称为横切关注点     连接点(JoinPoi

Spring中AOP的原理?

问题描述 面试问Spring中AOP的原理?用到哪些技术?答:通过动态代理技术,然后简单说了些实现方式.这只是其中的一种,还有其他的吗?答:........求大哥们指点! 问题补充:suziwen 写道 解决方案 其实它的代理 :分为动态代理和静态代理解决方案二:spring 提供了多种不同的方案实现对 bean 的 aop proxy, 包括 ProxyFactoryBean, 便利的 TransactionProxyFactoryBean 以及 AutoProxyCreator 等, 下图是

Spring的AOP的annotation实现

记录一下使用注解实现spring AOP的小例子. 第一步,导入相关的jar包:aspectjweaver-1.6.8.jar(提供注解org.aspectj.lang.annotation.Aspect等).spring-aop-3.0.4.RELEASE.jar(提供自动代理创建器org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator).aopalliance-1.0.jar(提供拦截

javascript-我感觉Spring的Aop感觉和事件用法是一样的

问题描述 我感觉Spring的Aop感觉和事件用法是一样的 例如js里一些事件,当加载前执行,当加在后执行 你们觉得呢? 解决方案 事件是细粒度的,aop是粗粒度的,事件组织的是不同的方法,aop组织的是aspects,通常是beans 解决方案二: 我觉得你可以好好看看Aop的相关文档,为什么要用Aop?如果单纯的像你说的那样,那Aop这种编程模式就没有存在的必要了. 解决方案三: 参考一篇文章:http://blog.csdn.net/moreevan/article/details/119