欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

spring之AspectJ实现AOP

程序员文章站 2022-05-24 12:31:30
...

一、基于注解的AspectJ

1、要在spring应用中使用AspectJ注解,必须在classpath下包含AspectJ类库:

   com.springsource.org.aopalliance.jar 和 com.springsource.org.aspectj.weaver.jar;将aop schema添加到 <beans> 根元素中;在Spring IoC 容器中启用 AspectJ直接支持,只要在 bean 配置文件中定义一个空的XML元素 <aop:aspectj-autoproxy>;当Spring IoC 容器检测到 bean 配置文件中的 <aop:aspectj-autoproxy> 元素时,就会自动为与 AspectJ 切面匹配的 bean 创建代理。

2、通知是标有某种注解的简单的java方法,AspectJ支持5种类型的通知注解:

1)@Before:前置通知,在方法执行之前执行

2)@After:最终增强

3)@AfterReturning:后置通知,在方法返回结果之后执行

4)@AfterThrowing:异常通知,在方法抛出异常后执行

5)@Around:环绕通知,围绕着方法的执行

3. 典型的切点表达式是根据方法的签名来匹配各种方法:

       -execution(* *.*(..)):第一个*代表匹配任意修饰符和返回值,第二个*代表任意类的对象,第三个*代表任意方法,参数列表中..匹配任意数量的参数。

       - execution (* com.bupt.springtest.aop.ArithmeticCalculator.*(..)):匹配 ArithmeticCalculator 中声明的所有方法,第一个 * 代表任意修饰符及任意返回值;第二个 *     代表任一方法; .. 匹配任意数量的参数。若目标类或接口与该切面在同一个包中,可以省略包名。

       - execution (public * ArithmeticCalculator.*(..)):匹配ArithmeticCalculator 类中的所有公有方法。
       - execution (public double ArithmeticCalculator.*(..)):匹配ArithmeticCalculator 中返回double类型数值的方法

       - execution (public double ArithmeticCalculator.*(double, ..)):匹配第一个参数为double类型的方法, .. 匹配任意数量任意类型的参数

       - execution (public double ArithmeticCalculator.*(double, double)):匹配参数类型为double, double类型的方法

4、案例

1、创建一个接口

package cn.happy.service;

public interface ISomeService {
    public void doSome();
    public String add();

    public void insert();
    public void update();
    public void delete();
    public void select();
}

2、实现接口类

package cn.happy.service;

public class SomeService implements ISomeService {
    public void doSome() {
        System.out.println("code  ok");
    }

    public String add() {
        System.out.println("=========log日志===============");
        //int i = 5/0;
        return "add";
    }

    public void insert() {
        System.out.println("insert");
    }

    public void update() {
        System.out.println("update");
    }

    public void delete() {
        System.out.println("delete");
    }

    public void select() {
        int i = 5/0;
        System.out.println("select");
    }
}

3、编写增强类

package cn.happy.service;

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

@Aspect
public class MyAspect {
    @Before(value="execution(* *..service.*.*(..))")
    public void myAspectj(){
        System.out.println("---我是前置增强---");
    }
 
    @AfterReturning(value="execution(* *..service.*.*(..))")
    public void myAspectjAfter(){
        System.out.println("---我是后置增强---");
    }

   @Around(value="execution(* *..service.*.*(..))")
    public Object myAspectjAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("---我是环绕前增强---");
        Object result = proceedingJoinPoint.proceed();
        System.out.println("---我是环绕后增强---");
        if (result!= null) {
            String str = (String)result;  //可以改变返回值
            return  str.toUpperCase();
        } else {
            return null;
        }
    }


   异常增强
    @Pointcut("execution(* *..service.*.*(..))")  表达式注解
    public void myPoincut(){}
      @AfterThrowing("myPoincut()")
    public void throwing(){
        System.out.println("---error---");
    }

     //切点表达式
     @Pointcut("execution(* *..service.*.insert(..))")
    public void insert(){}



     @Pointcut("execution(* *..service.*.update(..))")
    public void update(){}
     @Pointcut("execution(* *..service.*.delete(..))")
    public void delete(){}

    @Before("insert()||update()||delete()")
    public void myAspectj(){
        System.out.println("---我是前置增强开启事物---");
    }


    //最终增强
    @After("execution(* *..service.*.*(..))")
    public void after(){
        System.out.println("我是最终增强");
    }
}

  

4、编写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:p="http://www.springframework.org/schema/p"
       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
">
    <!--注解实现-->
    <!--目标对象-->
    <bean id="SomeService" class="cn.happy.serviceXML.SomeService"></bean>

      <!--增强  通知–&gt   -->
    <bean id="beforeAdvice" class="cn.happy.service.MyAspect"></bean>

    <aop:aspectj-autoproxy></aop:aspectj-autoproxy> 

    

   
</beans>

5、编写测试类

package cn.happy;



import cn.happy.service.ISomeService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class test {
    @Test
    public  void  testAspect(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        ISomeService someService = (ISomeService)context.getBean("SomeService");

        someService.insert();
        someService.update();
        someService.delete();
        someService.select();
    }
}

  

二、基于xml的AspectJ实现

1、基于xml的实现需要在xml配置文件中加入<aop>节点。

2、案例

1)创建接口类

package cn.happy.serviceXML;

public interface ISomeService {
    public void doSome();
    public String add();


}

2)实现接口类

package cn.happy.serviceXML;


public class SomeService implements ISomeService {
    public void doSome() {
        System.out.println("code  ok");
    }

    public String add() {
        System.out.println("log------");
        //int i = 5/0;
        return "add";
    }


}

3)编写增强类

package cn.happy.serviceXML;

import org.aspectj.lang.ProceedingJoinPoint;

public class MyAspect {
    public void myBefore(){
        System.out.println("=========before============");
    }

    public void after(){
        System.out.println("============after===============");
    }

    public Object myArround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("我是环绕前增强");
        Object result = proceedingJoinPoint.proceed();
        System.out.println("我是环绕后增强");
        if (result!= null) {
            String str = (String)result;  //可以改变返回值
            return  str.toUpperCase();
        } else {
            return null;
        }
    } 
}

4).编写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:p="http://www.springframework.org/schema/p"
       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
">
    <!--目标对象-->
    <bean id="SomeService" class="cn.happy.serviceXML.SomeService"></bean>

   

    <!--增强类-->
    <bean id="aspect" class="cn.happy.serviceXML.MyAspect"></bean>

    <!--aop-->
    <aop:config>
        <!--设置一个切点-->
        <aop:pointcut id="mycut" expression="execution(* *..serviceXML.*.*(..))"></aop:pointcut>
       <aop:aspect ref="aspect">
           <aop:before method="myBefore" pointcut-ref="mycut"></aop:before>
           <!--<aop:after-returning method="after" pointcut-ref="mycut"></aop:after-returning>-->
           <!--<aop:around method="myArround" pointcut-ref="mycut"></aop:around>-->
       </aop:aspect>
    </aop:config>
</beans>

5)编写测试类

package cn.happy;


import cn.happy.serviceXML.ISomeService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class test01 {
    // AspectJ XML
    @Test
    public void testAspectXML(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        ISomeService someService= (ISomeService)context.getBean("SomeService");
        someService.add();
        someService.doSome();
    }
}