天天看点

基于AspectJ的注解AOP开发

AspectJ简介

基于AspectJ的注解AOP开发

环境搭建

使用AspectJ之前需要在pom.xml中引入Spring AOP和AspectJ的相关jar包

 <dependency>

      <groupId>aopalliance</groupId>

      <artifactId>aopalliance</artifactId>

      <version>1.0</version>

    </dependency>

    <dependency>

      <groupId>org.springframework</groupId>

      <artifactId>spring-aop</artifactId>

      <version>4.2.4.RELEASE</version>

    </dependency>

    <!--aspectj的包依赖以上2个包-->

    <dependency>

      <groupId>org.aspectj</groupId>

      <artifactId>aspectjweaver</artifactId>

      <version>1.8.9</version>

    </dependency>

    <dependency>

      <groupId>org.springframework</groupId>

      <artifactId>spring-aspects</artifactId>

      <version>4.2.4.RELEASE</version>

    </dependency>

 配置文件

按以下内容配置好applicationContext.xml文件,即可开始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" 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">

    <!--开启AspectJ的自动代理-->

    <aop:aspectj-autoproxy/>

</beans>

 @AspectJ 注解提供的通知类型

  1. @Before => 相当于BeforeAdvice(前置通知)
  2. @AfterReturning => 相当于AfterReturningAdvice(后置通知)
  3. @Around => 相当于MethodInterceptor(环绕通知)
  4. @AfterThrowing=> 相当于ThrowAdvice(异常通知)
  5. @After => 相当于try-catch语句的finally,不管是否异常都会通知

value属性定义切点

在为一个方法写通知类型时,需要使用value属性来配置方法对应的切点(也就是拦截的方法)

基于AspectJ的注解AOP开发

前置通知的例子

com.aspectJ建了2个类,ProductDao是被代理类,MyAspectAnno是代理类。

基于AspectJ的注解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" 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">

    <!--开启AspectJ的自动代理-->

    <aop:aspectj-autoproxy/>

    <!-- 配置被代理对象 -->

    <bean id="productDao" class="com.aspectJ.ProductDao"></bean>

    <!-- 配置切面 -->

    <bean class="com.aspectJ.MyAspectAnno"></bean>

</beans>

2个类结构:

基于AspectJ的注解AOP开发
基于AspectJ的注解AOP开发

编写测试类

    @org.junit.Test

    public void test() {

        // 加载配置文件

        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext1.xml");

        // 获取bean

        ProductDao productDao = (ProductDao) context.getBean("productDao");

        productDao.save();

        productDao.delete();

    }

运行结果:  

前置增强...execution(void com.aspectJ.ProductDao.save())

保存商品...

删除商品... 

 其它类型通知

后置通知

// 后置通知,拦截update方法

    @AfterReturning(value="execution(* com.aspectJ.ProductDao.update(..))",returning="ret")

    public void afterReturning(Object ret) {

        // ret是拦截的方法返回值

        System.out.println("后置增强" + ret);

    }

 环绕通知

// 环绕通知,拦截所有方法

    @Around(value="execution(* *(..))")

    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {        

        System.out.println("环绕前增强");

        // 执行拦截到的方法

        Object object = joinPoint.proceed();

        System.out.println("环绕后增强");

        return object;

    }

异常抛出通知

// 异常抛出通知

    @AfterThrowing(value="execution(* *(..))", throwing="e")

    public void throwing(Throwable e) {

        System.out.println("异常抛出通知" + e.getMessage());

    }

最终通知(类似finally) 

// 最终通知

    @After(value="execution(* *(..))")

    public void after() {

        System.out.println("最终通知");

    }

起别名:给要拦截的方法起别名,这样在一个方法需要在多处产生通知时使用别名有利于代码的维护.

value后面写要起别名的方法,下面写一个 private void 别名() {},这样就产生了别名,在使用拦截的地方,把value写成value="别名()"就可以了。

// 给拦截的方法起别名

    @Pointcut(value="execution(* com.aspectJ.ProductDao.update(..))")

    private void myPointCut() {}

 // 后置通知,使用别名

    @AfterReturning(value="myPointCut()",returning="ret")

    public void afterReturning(Object ret) {

        // ret是拦截的方法返回值

        System.out.println("后置增强" + ret);

    }