Spring AspectJ AOP 简单示例

转自 http://outofmemory.cn/java/spring/AOP/aop-aspectj-example-before-after-AfterReturning-afterThrowing-around

这里我们用一个完整的例子演示spring aspectj aop的使用。

首先新建一个maven项目,在项目的pom.xml中添加spring aop相关的依赖项:

如下是完整的pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.bwu.aop</groupId>
    <artifactId>bwu-aop-demo</artifactId>
    <name>bwu-aop-demo</name>
    <version>1.0-SNAPSHOT</version>
    <description>demo for learning AOP</description>

    <properties>
        <spring.version>3.1.1.RELEASE</spring.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.6.12</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.6.12</version>
        </dependency>
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>2.2</version>
        </dependency>
    </dependencies>

</project>

在maven中我们引入了spring aop相关的依赖,aspectj相关的包有两个,cglib是必须的。

下面我们在项目中新建一个Service类PersonService,它是业务代码,是我们AOP注入的目标类:

package com.bwu.aop.spring.aspect;

import org.springframework.stereotype.Service;

@Service
public class PersonService {

    public void addPerson(String personName) {
        System.out.println("add person " + personName);
    }

    public boolean deletePerson(String personName) {
        System.out.println("delete person " + personName) ;
        return true;
    }

    public void editPerson(String personName) {
        System.out.println("edit person " + personName);
        throw new RuntimeException("edit person throw exception");
    }

}

PersonService类中定义了三个方法,addPerson方法无返回值,而deletePerson方法有返回值,而editPerson方法抛出运行时的异常。

下面我们看Aspect类:

package com.bwu.aop.spring.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class SimpleAspect {
    @Pointcut("execution(* com.bwu.aop.spring.aspect.*Service*.*(..))")
    public void pointCut() {
    }

    @After("pointCut()")
    public void after(JoinPoint joinPoint) {
        System.out.println("after aspect executed");
    }

    @Before("pointCut()")
    public void before(JoinPoint joinPoint) {
        //如果需要这里可以取出参数进行处理
        //Object[] args = joinPoint.getArgs();
        System.out.println("before aspect executing");
    }

    @AfterReturning(pointcut = "pointCut()", returning = "returnVal")
    public void afterReturning(JoinPoint joinPoint, Object returnVal) {
        System.out.println("after Returning executed, return result is "
                + returnVal);
    }

    @Around("pointCut()")
    public void around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("around start..");
        try {
            pjp.proceed();
        } catch (Throwable ex) {
            System.out.println("error in around");
            throw ex;
        }
        System.out.println("around end");
    }

    @AfterThrowing(pointcut = "pointCut()", throwing = "error")
    public void afterThrowing(JoinPoint jp, Throwable error) {
        System.out.println("error:" + error);
    }
}

SimpleAspect类中的第一个方法是pointCut()方法,此方法无任何执行内容,只有一个@Pointcut的注解,其他方法都会引用这个注解中指定的pointcut表达式。

其他几个方法是各种Advice类型的方法实现,在这些方法中都可以通过JoinPoint实例来获得方法执行的上下文信息,参数信息。需要注意AfterReturning和AfterThrowing,After三种不同Advice的执行顺序。

有了spring框架和aspectj以及cglib的支持,我们只需要实现上面两个类就可以使用spring aop的功能了,下面我们看下如何在spring的配置文件中配置spring aop。

<?xml version="1.0" encoding="UTF-8"?>
<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"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                           http://www.springframework.org/schema/aop
                           http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context-3.1.xsd">
    <aop:aspectj-autoproxy />

    <!-- Use context:component-scan will auto register the spring bean with @Componet, @Service, ... -->
    <!-- 
    <context:component-scan base-package="com.bwu.aop" />
     --> 
    <bean id="personService" class="com.bwu.aop.spring.aspect.PersonService"/>
    <bean id="simpleAspect" class="com.bwu.aop.spring.aspect.SimpleAspect"/>
</beans>

注意在beans节点中需要指定aop命名空间,一家chemaLocation地址,启用aop只需要添加就可以了。节点用来指定自动扫描bean的命名空间。

最后我们要测试下aop的效果,需要新建一个SpringAOPMain类作为程序的入口类。

package com.bwu.aop.spring.aspect;

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

public class SpringAOPMain {

    public static void main(String[] args) {
        ApplicationContext appContext = new ClassPathXmlApplicationContext("/appContext.xml");
        PersonService personService = appContext.getBean(PersonService.class);
        String personName = "Jim";
        personService.addPerson(personName);
        personService.deletePerson(personName);
        personService.editPerson(personName);
        ((ClassPathXmlApplicationContext)appContext).close();
    }

}

这个类中我们初始化了ApplicationContext,然后从中得到PersonService的实例,并执行其addPerson,deletePerson,editPerson方法,最后关闭ApplicationContext。

其执行结果如下:

before aspect executing
around start..
add person Jim
after aspect executed
around end
after Returning executed, return result is null
before aspect executing
around start..
delete person Jim
after aspect executed
around end
after Returning executed, return result is null
before aspect executing
around start..
edit person Jim
after aspect executed
error in around
error:java.lang.RuntimeException: edit person throw exception
Exception in thread "main" java.lang.RuntimeException: edit person throw exception ... ...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值