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

本文内容纲要:

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

-   总结:

前言:

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

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

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

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

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

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

Image

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

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

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

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

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

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

Image

  首先定义个接口

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的配置文件,把拦截器与切面方法关联起来。

Image

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

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权威指南》

本文内容总结:  那么下面看一个简单的例子:,  总结:,

原文链接:https://www.cnblogs.com/xing901022/p/4143696.html

以上是 【Spring开发】—— AOP之方法级拦截 的全部内容, 来源链接: utcz.com/z/295977.html

回到顶部