Spring 基于Aspectj的注解开发AOP(一)-前置通知@Before

一、Aspectj 常用注解

 1、@Before 前置通知,相当于BeforeAdvice
        ps:在目标方法之前执行
        应用场景:如在保存之前进行权限校验,只有管理员身份才有权限保存;
    2、@AfterReturning 后置通知,相当于AfterReturningAdvice
        ps:在目标方法之后执行
        应用场景:如在删除一条记录时候,记录是谁什么时候删除的;
    3、@Around 环绕通知,相当于MethodInterceptor
        ps:在目标方法之前和之后执行,可以阻止目标方法执行
        应用场景:如事务处理,在目标方法之前开启事务,目标方法之后提交或回滚事务;
    4、@AfterThrowing 异常抛出通知,相当于ThrowAdvice
        ps:只会在目标方法有异常的情况下,才会执行
    5、@After 最终final通知,不管是否有异常,该通知都会执行;


二、在通知中通过value属性定义切点

在通知中通过value属性定义切点

•通过execution函数,可以定义切点的方法切入

•语法:
    –execution(<访问修饰符>?<返回类型><方法名>(<参数>)<异常>)

•例如
    –匹配所有类public方法execution(public * *(..))

    –匹配指定包下所有类方法execution(* com.imooc.dao.*(..)) 

    -不包含子包–execution(* com.imooc.dao..*(..))  ..*表示包、子孙包下所有类

    –匹配指定类所有方法execution(* com.imooc.service.UserService.*(..))

    –匹配实现特定接口所有类方法    execution(* com.imooc.dao.GenericDAO+.*(..))

    –匹配所有save开头的方法 execution(* save*(..)) 

三、可以在方法中传入JoinPoint对象,用来获取切点信息(ps:案例中有介绍)

四、入门案例 

Spring 基于Aspectj的注解开发AOP(一)-前置通知@Before

applicationContext.xml:

<?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.lucifer.aspectj.demo.ProductDao"/>

    <!--定义切面-->
    <bean id="MyAspectjAnno" class="com.lucifer.aspectj.demo.MyAspectjAnno"/>

</beans>

 ProductDao 目前类:

package com.lucifer.aspectj.demo;

/**
 * @Author: Lucifer
 * @Date: 2019/3/21 00:28
 * @Description:
 */
public class ProductDao {

    public void save(){
        System.out.println("保存商品");
    }

    public void update(){
        System.out.println("修改商品");
    }

    public void delete(){
        System.out.println("删除商品");
    }

    public void findOne(){
        System.out.println("查询一个商品");
    }

    public void findAll(){
        System.out.println("查询所有商品");
    }


}

MyAspectjAnno 切面类:

package com.lucifer.aspectj.demo;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

/**
 * @Author: Lucifer
 * @Date: 2019/3/21 00:31
 * @Description: 切面类
 */
@Aspect
public class MyAspectjAnno {

    @Before(value = "execution(* com.lucifer.aspectj.demo.ProductDao.*(..))")
    public void before(){
        System.out.println("前置通知==============================");
    }

}

test 测试类: 

package com.lucifer.aspectj.demo;

import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

/**
 * @Author: Lucifer
 * @Date: 2019/3/21 00:36
 * @Description:
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Test {

    @Autowired
    private ProductDao productDao;

    @org.junit.Test
    public void demo1(){
        productDao.save();
        productDao.delete();
        productDao.findAll();
        productDao.findOne();
        productDao.update();
    }

}

控制台打印:

Spring 基于Aspectj的注解开发AOP(一)-前置通知@Before

只匹配com.lucifer.aspectj.demo类下的save()方法:

Spring 基于Aspectj的注解开发AOP(一)-前置通知@Before

改变MyAspectjAnno类,将before方法添加JoinPoint 参数;

ps:可以在方法中传入JoinPoint对象,用来获取切点信息

package com.lucifer.aspectj.demo;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

/**
 * @Author: Lucifer
 * @Date: 2019/3/21 00:31
 * @Description: 切面类
 */
@Aspect
public class MyAspectjAnno {

    @Before(value = "execution(* com.lucifer.aspectj.demo.ProductDao.save(..))")
    public void before(JoinPoint joinPoint){
        System.out.println("前置通知=============================="+joinPoint);
    }

}

控制台打印:

Spring 基于Aspectj的注解开发AOP(一)-前置通知@Before

pmo.xml:

<dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>

    <!--引入spring基本的开发包-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.1.5.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</artifactId>
      <version>5.1.5.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-expression</artifactId>
      <version>5.1.5.RELEASE</version>
    </dependency>

    <!--aop-->
    <dependency>
      <groupId>aopalliance</groupId>
      <artifactId>aopalliance</artifactId>
      <version>1.0</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>5.1.5.RELEASE</version>
    </dependency>

    <!--aspectj -->
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.9.2</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aspects</artifactId>
      <version>5.1.3.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>5.1.5.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>5.1.5.RELEASE</version>
    </dependency>

  </dependencies>
  
  <build>
    <finalName>spring-aspectj</finalName>
  </build>