Spring 中基于AOP的@AspectJ

@AspectJ 作为通过 Java 5 注释注释的普通的 Java 类,它指的是声明 aspects 的一种风格。通过在你的基于架构的 XML 配置文件中包含以下元素,@AspectJ 支持是可用的。

<aop:aspectj-autoproxy/>

如果需要使用该注解,需要包含一下几个包:
- aspectjrt.jar
- aspectjweaver.jar
- aspectj.jar
- aopalliance.jar

Aspects 类就和其他正常的bean一样,可以有方法和成员,除了该类是用@Aspect 注解的:

package org.xyz;

import org.aspectj.lang.annotation.Aspect;

@Aspect
public class AspectModule {
}

它们就和其他任何一个bean一样配置在XML中:

<bean id = "myAspect" class = "org.xyz.AspectModule">
   
bean>

Declaring a pointcut

声明一个切点:一个切点帮助决定使用不同的advices执行的感兴趣的点(比如方法)。当使用@AspectJ-based配置的时候,切点声明有两部分。

  • 一个切点表达式确定哪些方法是我感兴趣的
  • 切点的特征包括名称和任意数量的参数,该方法的实际主体时不想关的,实际上应该是空的。

下面的例子定义了一个名称为businessService的切点,该切点匹配com.xyz.myapp.service包中任意类的任意方法

import org.aspectj.lang.annotation.Pointcut;

@Pointcut("execution(* com.xyz.myapp.service.*.*(..))") // expression 
private void businessService() {}  // signature

下面的例子定义了一个名称为getname的切点,这个切点将匹配com.tutorialspoint包中Student类的getName()方法。

import org.aspectj.lang.annotation.Pointcut;

@Pointcut("execution(* com.tutorialspoint.Student.getName(..))") 
private void getname() {}

Declaring advices

你可以使用@{ADVICE-NAME}注解声明任何五种advices中的一种,这些都是在假定你已经定义了一个businessService()切点声明前提下的。

@Before("businessService()")
public void doBeforeTask(){
   ...
}

@After("businessService()")
public void doAfterTask(){
   ...
}

@AfterReturning(pointcut = "businessService()", returning = "retVal")
public void doAfterReturnningTask(Object retVal) {
   // you can intercept retVal here.
   ...
}

@AfterThrowing(pointcut = "businessService()", throwing = "ex")
public void doAfterThrowingTask(Exception ex) {
  // you can intercept thrown exception here.
  ...
}

@Around("businessService()")
public void doAroundTask(){
   ...
}

你也可以在advices中定义一个切点,下面就是一个例子:

@Before("execution(* com.xyz.myapp.service.*.*(..))")
public doBeforeTask(){
   ...
}

@AspectJ Based AOP Example

Student.java

package com.soygrow.AspectJAnnotation;

public class Student {
    private Integer age;
    private String name;

    public void setAge(Integer age) {
        this.age = age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        System.out.println("Name : " + name);
        return name;
    }

    public Integer getAge() {
        System.out.println("Age : " + age);
        return age;
    }

    public void printThrowException() {
        System.out.println("Exception raised");
        throw  new IllegalArgumentException();
    }
}

Logging.java

package com.soygrow.AspectJAnnotation;

import org.aspectj.lang.annotation.*;

@Aspect
public class Logging {
    /**
     * Following is the definition for a pointcut to select
     * all the methods available. So advices will be called
     * for all the methods.
     */
    @Pointcut("execution(* com.soygrow.AspectJAnnotation.*.*(..))")
    private void selectAll() {
    }

    /**
     * This is the method which I would like to execute
     * before a selected method execution.
     */
    @Before("selectAll()")
    public void beforeAdvice() {
        System.out.println("Going to setup student profile.");
    }

    /**
     * This is the method which I would like to execute
     * after a selected method execution.
     */
    @After("selectAll()")
    public void afterAdvice() {
        System.out.println("Student profile has been setup.");
    }

    /**
     * This is the method which I would like to execute
     * when any method returns.
     */
    @AfterReturning(pointcut = "selectAll()", returning = "object")
    public void afterReturningAdvice(Object object) {
        System.out.println("Returning : " + object.toString());
    }

    /**
     * This is the method which I would like to execute
     * if there is an exception raised by any method.
     */
    @AfterThrowing(pointcut = "selectAll()", throwing = "ex")
    public void AfterThrowingAdvice(IllegalArgumentException ex) {
        System.out.println("There has been an exception : " + ex.toString());
    }
}

MainApp.java

package com.soygrow.AspectJAnnotation;

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

public class MainApp {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("AspectJBeans.xml");
        Student student = (Student) context.getBean("student");
        student.getAge();
        student.getName();

        student.printThrowException();
    }
}

AspectJBeans.xml


<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">

    <aop:aspectj-autoproxy/>

    
    <bean id = "student" class = "com.soygrow.AspectJAnnotation.Student">
        <property name = "name" value = "Zara" />
        <property name = "age"  value = "11"/>
    bean>

    
    <bean id = "logging" class = "com.soygrow.AspectJAnnotation.Logging"/>
beans>

如果一切正常,运行结果:

Going to setup student profile.
Age : 11
Student profile has been setup.
Returning : 11
Going to setup student profile.
Name : Zara
Student profile has been setup.
Returning : Zara
Going to setup student profile.
Exception raised
Student profile has been setup.
There has been an exception : java.lang.IllegalArgumentException

如果在XML配置文件中去掉,那么就不会运行AspectJ相关代码

遇到的问题

Exception in thread “main” org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘student’ defined in class path resource [AspectJBeans.xml]: Initialization of bean failed; nested exception is java.lang.IllegalArgumentException: error at ::0 can’t find referenced pointcut selectAll
at

问题是我用的AspectJ库文件的版本过低导致的,将版本从1.5.4升级到1.7.4就没有这个问题了

你可能感兴趣的:(Spring,Java,Spring,AOP)