Spring教程 - Spring AOP

2018-01-09 19:06 更新

Spring教程 - Spring AOP


除了依赖注入(DI),Spring Framework提供的另一个核心特性是面向方面的编程(AOP)。

除了依赖注入(DI),Spring Framework提供的另一个核心特性是面向方面的编程(AOP)。...

横切关注点指的是应用程序中的逻辑不能从其余的分解应用程序并可能导致代码重复和紧密耦合。

AOP是一个旨在提高模块性的编程范例通过允许分离交叉关注点。

AOP是一个旨在提高模块性的编程范例通过允许分离交叉关注点。...

Spring AOP框架在各方面模块化横切关注点。当在Spring IoC容器中执行一个方法时,Spring AOP可以劫持执行方法,并在方法执行之前或之后添加额外的功能。



AOP概念

AOP具有自己特定的概念和术语集。

以下是AOP的核心概念:

  • Joinpoints is a point during the execution of your application. Typical example of joinpoints is a call to a method. Joinpoints define the points in your application at which you can insert additional logic using AOP.
  • Advice is the code executed at a particular joinpoint. There are many types of advice, such as before , which executes before the joinpoint, and after , which executes after it.
  • Pointcut is a collection of joinpoints that is used to define when advice should be executed. By creating pointcuts, we control over how to apply advice to the Java Bean in the application.
  • Weaving is the process of inserting aspects into the application code at the appropriate point.
  • An object whose execution flow is modified by an AOP process is referred to as the target object or advised object.

Spring AOP有四种类型的建议。

  • Before advice - Run before the method execution
  • After returning advice - Run after the method returns a result
  • After throwing advice - Run after the method throws an exception
  • Around advice - Run around the method execution, combine all three advices above.

建议是在方法执行之前或之后采取的动作。



依赖

将以下新的依赖关系添加到POM.xml中进行AOP编码。

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>2.2.2</version>
</dependency>

Java Bean

以下代码定义了打印机服务的Java bean。

package com.www.w3cschool.cnmon;

public class PrinterService {
  private String name;
  private String url;
  public void setName(String name) {
    this.name = name;
  }
  public void setUrl(String url) {
    this.url = url;
  }
  public void printName() {
    System.out.println("Printer Name : " + this.name);
  }
  public void printURL() {
    System.out.println("Printer URL : " + this.url);
  }
  public void printThrowException() {
    throw new IllegalArgumentException();
  }
}

XML配置

这里是用于bean配置的Spring-Customer.xml文件。

<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
  <bean id="myService" class="com.www.w3cschool.cnmon.PrinterService">
    <property name="name" value="printerName" />
    <property name="url" value="http://www.www.w3cschool.cn" />
  </bean>
</beans>

以下是运行上面代码的主类。

package com.www.w3cschool.cnmon;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
  public static void main(String[] args) {
    ApplicationContext appContext = new ClassPathXmlApplicationContext(
        new String[] { "SpringBeans.xml" });
    PrinterService cust = (PrinterService) appContext.getBean("myService");
    cust.printName();
    cust.printURL();
    try {
      cust.printThrowException();
    } catch (Exception e) {
    }
  }
}

输出


Download Java2s_Spring_Pre_AOP.zip

XML配置...

下面的代码显示了如何添加Before通知。

A Before在方法执行之前执行。

首先,创建一个实现MethodBeforeAdvice接口的类。

package com.www.w3cschool.cnmon;

import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;

public class AOPBeforeMethod implements MethodBeforeAdvice
{
  @Override
  public void before(Method method, Object[] args, Object target)
    throws Throwable {
          System.out.println("AOPBeforeMethod : Before method call.");
  }
}

然后,我们在xml配置文件中创建AOPBeforeMethod bean。

<bean id="aopBeforeMethodBean" class="com.java2s.aop.AOPBeforeMethod" />

要使用 AOPBeforeMethod 类,我们必须使用安装它 org.springframework.aop.framework.ProxyFactoryBean ,如下所示。

  <bean id="myServiceProxy" 
                 class="org.springframework.aop.framework.ProxyFactoryBean">

    <property name="target" ref="myService" />

    <property name="interceptorNames">
      <list>
        <value>aopBeforeMethodBean</value>
      </list>
    </property>
  </bean>

完整的源代码

<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

  <bean id="myService" class="com.www.w3cschool.cnmon.PrinterService">
    <property name="name" value="printerName" />
    <property name="url" value="http://www.www.w3cschool.cn" />
  </bean>

  <bean id="aopBeforeMethodBean" class="com.www.w3cschool.cnmon.AOPBeforeMethod" />

  <bean id="myServiceProxy" 
                 class="org.springframework.aop.framework.ProxyFactoryBean">

    <property name="target" ref="myService" />

    <property name="interceptorNames">
      <list>
        <value>aopBeforeMethodBean</value>
      </list>
    </property>
  </bean>
</beans>

再次运行main函数。

从结果我们可以看到AOPBeforeMethod“的before()方法在每个myService的方法之前执行。

返回建议后

下面的代码显示了如何使用After返回通知。返回通知后,将在方法返回结果后执行。

首先,创建一个实现AfterReturningAdvice接口的类。

package com.www.w3cschool.cnmon;

import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;

public class AOPAfterMethod implements AfterReturningAdvice
{
  @Override
  public void afterReturning(Object returnValue, Method method,
    Object[] args, Object target) throws Throwable {
          System.out.println("AOPAfterMethod : After method call.");
  }
}

然后,在 AOPAfterMethod 类中安装Bean配置文件。

<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

  <bean id="myService" class="com.www.w3cschool.cnmon.PrinterService">
    <property name="name" value="printerName" />
    <property name="url" value="http://www.www.w3cschool.cn" />
  </bean>

  <bean id="aopAfterMethodBean" class="com.www.w3cschool.cnmon.AOPAfterMethod" />

  <bean id="myServiceProxy" 
                class="org.springframework.aop.framework.ProxyFactoryBean">

    <property name="target" ref="myService" />

    <property name="interceptorNames">
      <list>
        <value>aopAfterMethodBean</value>
      </list>
    </property>
  </bean>
</beans>

再次运行main函数。 这里是输出。

从结果我们可以看到AOPAfterMethod的“afterReturning()方法在每个myService的方法返回结果之后执行。

投掷后建议

下面的代码显示了如何使用After抛出的建议。抛出后抛出的通知会在方法抛出异常后执行。

第一,创建一个实现ThrowsAdvice接口的类,并创建一个afterThrowing方法来劫持IllegalArgumentException异常。

package com.www.w3cschool.cnmon;

import org.springframework.aop.ThrowsAdvice;

public class AOPThrowException implements ThrowsAdvice {
  public void afterThrowing(IllegalArgumentException e) throws Throwable {
    System.out.println("AOPThrowException : Throw exception call.");
  }
}

然后,在Bean配置文件中安装 AOPThrowException

<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

  <bean id="myService" class="com.www.w3cschool.cnmon.PrinterService">
    <property name="name" value="printerName" />
    <property name="url" value="http://www.www.w3cschool.cn" />
  </bean>

  <bean id="aopThrowExceptionBean" class="com.www.w3cschool.cnmon.AOPThrowException" />

  <bean id="myServiceProxy" 
                 class="org.springframework.aop.framework.ProxyFactoryBean">

    <property name="target" ref="myService" />

    <property name="interceptorNames">
      <list>
        <value>aopThrowExceptionBean</value>
      </list>
    </property>
  </bean>
</beans>

运行代码,这里是输出。

Printer Name : printerName
Printer URL : http://www.www.w3cschool.cn
AOPThrowException : Throw exception call.

从结果我们可以看到Spring IoC容器运行AOPThrowException的s afterThrowing()  方法,当myService的方法抛出异常。

周围的建议

以下代码显示如何使用Around建议。周围的建议综合了上面的所有三个建议,并在方法执行期间执行。

首先,创建一个实现MethodInterceptor接口的类。

public Object invoke(MethodInvocation methodInvocation)throws Throwable方法是为每个方法调用,我们必须调用“methodInvocation.proceed();" 以运行原始方法,否则原方法将不会运行。

package com.www.w3cschool.cnmon;

import java.util.Arrays;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class AOPAroundMethod implements MethodInterceptor {
  @Override
  public Object invoke(MethodInvocation methodInvocation) throws Throwable {

    System.out.println("Method name : "
        + methodInvocation.getMethod().getName());
    System.out.println("Method arguments : "
        + Arrays.toString(methodInvocation.getArguments()));

    System.out.println("AOPAroundMethod : Before method call.");

    try {
      // proceed to original method call
      Object result = methodInvocation.proceed();

      // same with AfterReturningAdvice
      System.out.println("AOPAroundMethod : after call.");

      return result;

    } catch (IllegalArgumentException e) {
      System.out.println("AOPAroundMethod : Throw exception call.");
      throw e;
    }
  }
}

这里是xml Bean配置文件来安装Around Advice AOP。

<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

  <bean id="myService" class="com.www.w3cschool.cnmon.PrinterService">
    <property name="name" value="printerName" />
    <property name="url" value="http://www.www.w3cschool.cn" />
  </bean>

  <bean id="aopAroundMethodBean" class="com.www.w3cschool.cnmon.AOPAroundMethod" />

  <bean id="myServiceProxy" 
                class="org.springframework.aop.framework.ProxyFactoryBean">

    <property name="target" ref="myService" />

    <property name="interceptorNames">
      <list>
        <value>aopAroundMethodBean</value>
      </list>
    </property>
  </bean>
</beans>

运行main函数,这里是输出。


Download AOP_Around.zip
以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号