• 基于注解的AOP配置之四种通知日志记录案例(不建议)


    1、 创建maven的jar工程,导入依赖

    <dependencies>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>5.0.2.RELEASE</version>
            </dependency>
    
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjweaver</artifactId>
                <version>1.8.7</version>
            </dependency>
        </dependencies>

    2、 编写业务层的接口

    public interface IAccountService {
    
        /**
         * 模拟保存账户
         */
       void saveAccount();
    }

    3、编写业务层接口的实现类:

    @Service("accountService")
    public class AccountServiceImpl implements IAccountService{
        @Override
        public void saveAccount() {
            System.out.println("执行了保存");
           // int i=1/0;
        }
    }

    4、 创建一个具有公共代码的类

    @Component("logger")  // 要将通知bean交个spring来管理,否则通知bean不生效
    @Aspect//表示当前类是一个切面类
    public class Logger { @Pointcut("execution(* com.itheima.service.impl.*.*(..))") private void pt1(){} //前置通知 @Before("pt1()") public void beforePrintLog(){ System.out.println("前置通知Logger类中的beforePrintLog方法开始记录日志了。。。"); } //后置通知 @AfterReturning("pt1()") public void afterReturningPrintLog(){ System.out.println("后置通知Logger类中的afterReturningPrintLog方法开始记录日志了。。。"); } // 异常通知 @AfterThrowing("pt1()") public void afterThrowingPrintLog(){ System.out.println("异常通知Logger类中的afterThrowingPrintLog方法开始记录日志了。。。"); } //最终通知 @After("pt1()") public void afterPrintLog(){ System.out.println("最终通知Logger类中的afterPrintLog方法开始记录日志了。。。"); } }

    Logger类上面写@Aspect注解,表示当前类是一个切面类

    前置通知用@Before("pt1()")注解,

    后置通知用@AfterReturning("pt1()")注解,

    异常通知用@AfterThrowing("pt1()")注解,

    最终通知用@After("pt1()")注解,

    环绕通知用@Around("pt1()")注解

    Logger类中定义一个方法pt1,使用@Pointcut注解指定切入点表达式

    注意引用切入点表达式时,@Before、@AfterReturning、@AfterThrowing、@After注解中的pt1后面的()一定要加上,否则会报错。

    5、编写配置文件bean.xml,配置spring创建容器时要扫描的包

    <?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"
           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">
    
        <!-- 配置spring创建容器时要扫描的包-->
        <context:component-scan base-package="com.itheima"></context:component-scan>
        <!-- 配置spring开启注解AOP的支持-->
        <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    </beans>

    6、测试

    public class AOPTest {
    public static void main(String[] args) {
    //1.获取容器
    ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
    // ApplicationContext ac = new AnnotationConfigApplicationContext(Logger.class);
    //2.获取对象
    IAccountService as = (IAccountService)ac.getBean("accountService");
    //3.执行方法
    as.saveAccount();
    }
    }

    结果:

    发现最终通知在后置通知之前先执行,

    发现最终通知在异常通知之前先执行,

    Spring基于注解的AOP中,这四个通知类型确实有顺序调用的问题,所以在实际开发中一般选择用环绕通知。因为环绕通知不存在这个问题,因为代码是我们自己写的,我们想让他们什么时候执行就什么时候执行,故如果是基于注解的AOP,建议用环绕通知,因为前面四个通知在执行调用顺序上有问题

    不使用XML而是使用纯注解实现AOP

    1、注释掉bean.xml中的

     2、给Logger类添加注解

    @Component("logger")
    @Aspect//表示当前类是一个切面类
    @ComponentScan(basePackages = "com.itheima")
    @EnableAspectJAutoProxy
    public class Logger {
        @Pointcut("execution(* com.itheima.service.impl.*.*(..))")
        private void pt1(){}
        //前置通知
        @Before("pt1()")
        public  void beforePrintLog(){
            System.out.println("前置通知Logger类中的beforePrintLog方法开始记录日志了。。。");
        }
        //后置通知
        @AfterReturning("pt1()")
        public  void afterReturningPrintLog(){
            System.out.println("后置通知Logger类中的afterReturningPrintLog方法开始记录日志了。。。");
        }
        // 异常通知
        @AfterThrowing("pt1()")
        public  void afterThrowingPrintLog(){
            System.out.println("异常通知Logger类中的afterThrowingPrintLog方法开始记录日志了。。。");
        }
        //最终通知
        @After("pt1()")
        public  void afterPrintLog(){
            System.out.println("最终通知Logger类中的afterPrintLog方法开始记录日志了。。。");
        }
    
    }

    使用注解@ComponentScan(basePackage=“com.itheima”)替换<context:component-scan>标签

    使用@EnableAspectJAutoProxy替换<aop:aspectj-autoproxy>标签。

    3、测试:

    public class AOPTest {
        public static void main(String[] args) {
            //1.获取容器
    //        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
            ApplicationContext ac = new AnnotationConfigApplicationContext(Logger.class);
            //2.获取对象
            IAccountService as = (IAccountService)ac.getBean("accountService");
            //3.执行方法
            as.saveAccount();
        }
    }

    结果:

     

  • 相关阅读:
    mac终端命令
    转:使用 Spring Data JPA 简化 JPA 开发
    一步步学习 Spring Data 系列之JPA(一)
    一步步学习 Spring Data 系列之JPA(二)
    xmlplus 组件设计系列之零
    前端框架沉思录(上)
    xmlplus 组件设计系列之十
    xmlplus 组件设计系列之九
    xmlplus 组件设计系列之八
    xmlplus 组件设计系列之七
  • 原文地址:https://www.cnblogs.com/zwh0910/p/14628864.html
Copyright © 2020-2023  润新知