spring中基于Aspectj的AOP学习笔记

使用Aspectj实现AOP
–注解方式
–xml方式
Aspectj是一个基于java语言的AOP框架
环境准备
导入spring aop和aspectj相关的jar包这里直接在pom.xml中引入坐标

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

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

spring中的配置
注解方式

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       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.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.demo1.ProductDao"/>

    <!--定义切面类-->
    <bean  id="myAspect" class="com.aspectj.demo1.MyAspectAnno"/>

</beans>

项目结构
spring中基于Aspectj的AOP学习笔记
目标类

package com.aspectj.demo1;
//目标类
public class ProductDao {

    public void add(){
        System.out.println("保存用户信息...");
    }

    public String delete(){
        System.out.println("删除用户信息...");
        return "返回值";
    }

    public void update(){
        System.out.println("修改用户信息...");
    }

    public void findOne(){
        System.out.println("查询单个用户信息...");
    }

    public void findAll(){
        System.out.println("查询所有用户信息...");
    }
}

@Aspectj提供的不同通知类型
@Before前置通知,在被增强的方法之前执行,相当与BeforAdvice
@AfterReturning后置通知,在被增强的方法之后执行,可以有返回值,相当与AfterRetruningAdvice
@Around环绕通知,在被增强的方法前后各执行一次,相当与MethodInterceptor
@AfterThrowing异常抛出通知,在被增强的方法发生异常时执行,相当于ThrowAdvice
@After最终final通知,不管是否有异常该方法都会执行
在通知中通过value属性定义切点
spring中基于Aspectj的AOP学习笔记
为目标类定义切面类

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;

//切面类
@Aspect
public class MyAspectAnno {
    //要增强的代码
    @Before(value = "execution(* com.aspectj.demo1.ProductDao.add())")
    public void before(JoinPoint joinPoint){
        System.out.println("前置通知===="+joinPoint);
    }

    @AfterReturning(value = "execution(* com.aspectj.demo1.ProductDao.delete())",returning = "result")
    public void afterReturning(Object result){
    //result被增强方法的返回值,可以作为参数
        System.out.println("后置通知===="+result);
    }

    @Around(value = "execution(* com.aspectj.demo1.ProductDao.update())")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("环绕前通知=====");
        Object obj = joinPoint.proceed();//执行目标方法,如果不写目标方法就不被执行
        System.out.println("环绕后通知=====");
        return obj;//返回值为目标方法
    }

    @AfterThrowing(value = "execution(* com.aspectj.demo1.ProductDao.*(..))",throwing = "e")
    public void afterThrowing(Throwable e){
        System.out.println("异常通知===="+e.getMessage());
    }

    @After(value = "execution(* com.aspectj.demo1.ProductDao.findAll())")
    public void after(){
        System.out.println("最终通知,即使被增强的方法出现了异常,我也执行");
    }
    
}

结果如下
spring中基于Aspectj的AOP学习笔记
为了方便还可以这样写

package com.aspectj.demo1;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;

//切面类
//@Aspect
public class MyAspectAnno {
    //要增强的代码
    @Before(value = "myPointCut1()")
    public void before(JoinPoint joinPoint){
        System.out.println("前置通知===="+joinPoint);
    }

    @AfterReturning(value = "myPointCut2()")
    public void afterReturning(Object result){//result被增强方法的返回值
        System.out.println("后置通知===="+result);
    }

    @Around(value = "myPointCut3()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("环绕前通知=====");
        Object obj = joinPoint.proceed();//执行目标方法
        System.out.println("环绕后通知=====");
        return obj;//返回值为目标方法
    }

    @AfterThrowing(value = "myPointCut4()",throwing = "e")
    public void afterThrowing(Throwable e){
        System.out.println("异常通知===="+e.getMessage());
    }

    @After(value = "myPointCut5()")
    public void after(){
        System.out.println("最终通知,即使被增强的方法出现了异常,我也执行");
    }

    @Pointcut(value = "execution(* com.aspectj.demo1.ProductDao.add())")
    private void myPointCut1(){}
    @Pointcut(value = "execution(* com.aspectj.demo1.ProductDao.delete())")
    private void myPointCut2(){}
    @Pointcut(value = "execution(* com.aspectj.demo1.ProductDao.update())")
    private void myPointCut3(){}
    @Pointcut(value = "execution(* com.aspectj.demo1.ProductDao.findOne())")
    private void myPointCut4(){}
    @Pointcut(value = "execution(* com.aspectj.demo1.ProductDao.findAll())")
    private void myPointCut5(){}
}

XML的配置方式

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       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.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.demo1.ProductDao"/>

    <!--定义切面类-->
    <bean  id="myAspect" class="com.aspectj.demo1.MyAspectAnno"/>

    <!--基于XML的方式-->
    <!--aop的配置-->
    <aop:config>
        <!--定义切入点:哪些类的哪些方法需要增强-->
        <aop:pointcut id="myPointCut1" expression="execution(* com.aspectj.demo1.ProductDao.add())"/>
        <aop:pointcut id="myPointCut2" expression="execution(* com.aspectj.demo1.ProductDao.delete())"/>
        <aop:pointcut id="myPointCut3" expression="execution(* com.aspectj.demo1.ProductDao.update())"/>
        <aop:pointcut id="myPointCut4" expression="execution(* com.aspectj.demo1.ProductDao.findOne())"/>
        <aop:pointcut id="myPointCut5" expression="execution(* com.aspectj.demo1.ProductDao.findAll())"/>
        <!--配置切面-->
        <aop:aspect ref="myAspect">
            <aop:before method="before" pointcut-ref="myPointCut1"/>
            <aop:after-returning method="afterReturning" pointcut-ref="myPointCut2" returning="result"/>
            <aop:around method="around" pointcut-ref="myPointCut3" />
            <aop:after-throwing method="afterThrowing" pointcut-ref="myPointCut4" throwing="e"/>
            <aop:after method="after" pointcut-ref="myPointCut5"/>
        </aop:aspect>
    </aop:config>

</beans>