zoukankan      html  css  js  c++  java
  • Spring深入浅出(十三),AOP,AspectJ,基于注解开发

    一、概述

    在 Spring 中,尽管使用 XML 配置文件可以实现 AOP 开发,但是如果所有的相关配置都集中在配置文件中,势必会导致 XML 配置文件过于臃肿,从而给维护和升级带来一定的困难。
    为此,AspectJ 框架为 AOP 开发提供了一套注解。AspectJ 允许使用注解定义切面、切入点和增强处理,Spring 框架可以根据这些注解生成 AOP 代理。

    名称说明
    @Aspect 用于定义一个切面。
    @Pointcut 用于定义一个切入点。
    @Before 用于定义前置通知,相当于 BeforeAdvice。
    @AfterReturning 用于定义后置通知,相当于 AfterReturningAdvice。
    @Around 用于定义环绕通知,相当于MethodInterceptor。
    @AfterThrowing 用于定义抛出通知,相当于ThrowAdvice。
    @After 用于定义最终final通知,不管是否异常,该通知都会执行。
    @DeclareParents 用于定义引介通知,相当于IntroductionInterceptor(不要求掌握)。

    启用 @AspectJ 注解有以下两种方法:

    1)使用@Configuration和@EnableAspectJAutoProxy注解

    @Configuration 
    @EnableAspectJAutoProxy
    public class Appconfig {
    }

    2)基于XML配置

    <aop:aspectj-autoproxy>

    3)相关类库的引用,参考上一篇文章Spring深入浅出(十二),AOP,基于XML开发 

    二、基于 AOP 的 @AspectJ 示例

    1. 创建aspect 模块 

    package com.clzhang.spring.demo;
    
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.AfterThrowing;
    import org.aspectj.lang.annotation.AfterReturning;
    
    @Aspect
    public class Logging {
        /**
         * Following is the definition for a pointcut to select all the methods
         * available. So advice will be called for all the methods.
         */
        @Pointcut("execution(* com.clzhang.spring.demo.*.*(..))")
        private void selectAll() {
        }
    
        /**
         * This is the method which I would like to execute before a selected method
         * execution.
         */
        @Before("selectAll()")
        public void beforeAdvice() {
            System.out.println("Going to setup student profile.");
        }
    
        /**
         * This is the method which I would like to execute after a selected method
         * execution.
         */
        @After("selectAll()")
        public void afterAdvice() {
            System.out.println("Student profile has been setup.");
        }
    
        /**
         * This is the method which I would like to execute when any method returns.
         */
        @AfterReturning(pointcut = "selectAll()", returning = "retVal")
        public void afterReturningAdvice(Object retVal) {
            System.out.println("Returning:" + retVal.toString());
        }
    
        /**
         * This is the method which I would like to execute if there is an exception
         * raised by any method.
         */
        @AfterThrowing(pointcut = "selectAll()", throwing = "ex")
        public void AfterThrowingAdvice(IllegalArgumentException ex) {
            System.out.println("There has been an exception: " + ex.toString());
        }
    }

     2. 创建Bean类 

    package com.clzhang.spring.demo;
    
    public class Student {
        private Integer age;
        private String name;
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        public Integer getAge() {
            System.out.println("Age : " + age);
            return age;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getName() {
            System.out.println("Name : " + name);
            return name;
        }
    
        public void printThrowException() {
            System.out.println("Exception raised");
            throw new IllegalArgumentException();
        }
    }

     3. 创建主程序 

    package com.clzhang.spring.demo;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    public class MainApp {
       public static void main(String[] args) {
          ApplicationContext context = 
                 new ClassPathXmlApplicationContext("Beans.xml");
          Student student = (Student) context.getBean("student");
          System.out.println("-----Invoke getName begin-----");
          String myName = student.getName();
          System.out.println("-----Invoke getName end. Name is:" + myName + "----");
          student.getAge();     
          student.printThrowException();
       }
    }

     4. 创建配置文件 

    <?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-3.0.xsd 
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
    
       <aop:aspectj-autoproxy/>
    
       <!-- Definition for student bean -->
       <bean id="student" class="com.clzhang.spring.demo.Student">
          <property name="name"  value="Zara" />
          <property name="age"  value="11"/>      
       </bean>
    
       <!-- Definition for logging aspect -->
       <bean id="logging" class="com.clzhang.spring.demo.Logging"/> 
    
    </beans>

     5. 运行输出 

    -----Invoke getName begin-----
    Going to setup student profile.
    Name : Zara
    Student profile has been setup.
    Returning:Zara
    -----Invoke getName end. Name is:Zara----
    Going to setup student profile.
    Age : 11
    Student profile has been setup.
    Returning:11
    Going to setup student profile.
    Exception raised
    Student profile has been setup.
    There has been an exception: java.lang.IllegalArgumentException

     本文参考:

    https://www.w3cschool.cn/wkspring/k4q21mm8.html

  • 相关阅读:
    深拷贝与浅拷贝+可变与不可变的数据类型
    列表+列表循环+列表切片+元祖
    接口+session与cookie的区别+http状态码
    JSP中文乱码问题终极解决方案
    关于AS使用git的那些奇葩事儿
    ListView中动态显示隐藏HeaderView和FooterView
    关于沉浸式的那些奇葩问题
    Android Bug分析系列:第三方平台安装app启动后,home键回到桌面后点击app启动时会再次启动入口类bug的原因剖析
    快速搭建tab
    使用 gradle 在编译时动态设置 Android resValue / BuildConfig / Manifes中<meta-data>变量的值
  • 原文地址:https://www.cnblogs.com/nayitian/p/15010330.html
Copyright © 2011-2022 走看看