@AspectJ注解方式的aop

@AspectJ注解方式的aop

第一步:导入依赖
  <dependencies>


       <!-- 引入spring 依赖 作为CGLIB的依赖 -->
       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-context</artifactId>
           <version>5.3.12</version>
       </dependency>

       <!-- aspect -->
       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-aspects</artifactId>
           <version>5.3.12</version>
       </dependency>
       <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 -->
       <dependency>
           <groupId>org.slf4j</groupId>
           <artifactId>slf4j-log4j12</artifactId>
           <version>1.7.25</version>
       </dependency>
       <dependency>
           <groupId>junit</groupId>
           <artifactId>junit</artifactId>
           <version>4.12</version>
           <scope>compile</scope>
       </dependency>
       <!--spring 集成测试-->
        <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-test</artifactId>
           <version>5.3.7</version>
           <scope>test</scope>
       </dependency>
   </dependencies>
第二步:开启@aspect注册 和包扫描
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns="http://www.springframework.org/schema/beans"
      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.xsd
      http://www.springframework.org/schema/aop
      http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">


   <!--使用bean 注解扫描 自动开启注解功能
    *就是如果某个类上面带有特定的注解
    @Component,@Repository,@Service,@Controller 就会将这个对象作为bean注入到spring容器中
   -->
   <context:component-scan base-package="com.bird"/>

   <!-- 配置aop的aspectj的自动代理:
       *自动扫描bean组件中,含有@Aspect的bean 将其作为aop管理 开启自动代理
   -->
   <aop:aspectj-autoproxy/>

</beans>
第三步:定义目标对象并注入到spring容器中
public interface ICustomerService {
   public void save();
   public int find();
   public  int error();
}
@Component
public class ICustomerServiceImpl implements ICustomerService {
   public void save() {
       System.out.println("客户保存了。。。。。");
  }

   public int find() {
       System.out.println("客户查询数量了。。。。。");
       return 100;
  }

   @Override
   public int error() {
       int a = 1 / 0;
       return 0;
  }
}
=======上面是基于接口的动态代理========下面是基于类的动态代理=========
@Service
public class ProductService {
   public void save() {
       System.out.println("商品保存了。。。。。");
  }

   public int find() {
       System.out.println("商品查询数量了。。。。。");
       return 99;
  }
}
第四步:编写通知类 并注入到spring容器中
package com.bird.advice.annotationaspectjaop.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
* @data 2021/11/28 10:03
* @author: bird
* @description: 这个是基于注解的方式定义的通知类
*/
@Component(value = "myAspect") // 将当前类注入到spring容器中
@Aspect //将该类标识为切面类(这里面有方法进行增强),相当于<aop:aspect ref=”myAspect”> //声明但前的这个类是通知类 专门用来增强
public class MyAspect {

   // 这个是基于接口的
   // 切入点:切入点就是拦截方法 意思就是要对哪些方法进行拦截 然后在通知里面进行拦截
   @Pointcut(value = "execution(* com.bird.advice.annotationaspectjaop.targetobject.ICustomerServiceImpl.save(..))")
   public void myPointcut() {
  }

   // 这个是基于类 进行切入点的
   @Pointcut(value = "execution(* com.bird.advice.annotationaspectjaop.targetobject.ProductService.save(..))")
   public void mypointcut2() {
  }

   @Pointcut(value = "execution(* com.bird.advice.annotationaspectjaop.targetobject.ProductService.find(..))")
   public void myPointcut3() {
  }

   @Pointcut(value = "execution(* com.bird.advice.annotationaspectjaop.targetobject.ICustomerServiceImpl.find(..))")
   public void myPointcut4() {
  }

   @Pointcut(value = "execution(* com.bird.advice.annotationaspectjaop.targetobject.ICustomerServiceImpl.error(..))")
   public void myPointcut5() {

  }


   // 前置通知 在save方法执行之前 执行的方法
   @Before(value = "myPointcut()|| mypointcut2()")
   public void before(JoinPoint joinPoint) {
       System.out.println("=======前置通知。。。。。");
  }


   // 后置通知
   @AfterReturning(value = "myPointcut()|| mypointcut2()||myPointcut3()", returning = "returnVal")
   public Object afterReturning(JoinPoint joinPoint, Object returnVal) {
       System.out.println("++++++++后置通知+++++++++++++:结果" + returnVal);
       return returnVal;
  }


   // 环绕通知
   @Around(value = "myPointcut4()")
   public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
       System.out.println("环绕通知------前");
       Object proceed = proceedingJoinPoint.proceed();
       System.out.println("环绕通知------后");
       return proceed;
  }

   // 抛出通知 若目标方法执行时 抛出了异常 那么就会执行这个增强
   @AfterThrowing(value = "myPointcut5()", throwing = "ex")
   public void afterThrowing(JoinPoint joinPoint, Throwable ex) {
       StackTraceElement[] stackTrace = ex.getStackTrace();
       StackTraceElement stackTraceElement = stackTrace[0];
       System.out.println("---抛出通知......------抛出的信息:" + ex.getMessage() + "具体的错误行:" + stackTraceElement);
  }

   // 最终通知 无论目标方法是否发生了异常都会执行下面的方法
   @After(value = "myPointcut5()")
   public void after(JoinPoint joinPoint) {
       System.out.println("--最终通知-----不管是否发生了异常----");
  }

}
第五步:测试
package com.bird.jdkproxy;

import com.bird.advice.annotationaspectjaop.targetobject.ICustomerService;
import com.bird.advice.annotationaspectjaop.targetobject.ProductService;
import org.junit.Test;
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;

/**
* @data 2021/11/28 10:21
* @author: bird
* @description: 这个是基于注解的方式实现的aop
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext-annotation-aspect.xml") // 加载指定位置的bean
public class SpringAspectTest {


   @Autowired
   private ICustomerService customerService;


   @Autowired
   private ProductService productService;

   @Test
   public void test() {
       // 基于接口
       customerService.save();
       customerService.find();
       System.out.println("******************************************************");
       // 基于类
       productService.find();
       productService.save();

       System.out.println("%%%%%%%%%%%%%下面是抛出异常通知%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
       customerService.error();

  }
}

 

 

 

posted on 2021-11-28 12:30  奋斗的小鸟22  阅读(61)  评论(0)    收藏  举报

导航