• Spring中基于AOP的@AspectJ


    以下内容引用自http://wiki.jikexueyuan.com/project/spring/aop-with-spring-framenwork/aspectj-based-aop-with-spring.html

    @AspectJ是指将Java方法注解为Java 5注解的常规Java类的方式。通过在基于XML Schema的配置文件中包含以下元素来启用@AspectJ支持。

    <aop:aspectj-autoproxy/>

    还需要使用以下AspectJ库:

       <!-- aspectjrt.jar -->
        <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.8.10</version>
        </dependency>
    
        <!-- aspectjweaver。jar -->
        <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.10</version>
        </dependency>

    集成步骤:

    1、声明一个aspect(方面)

    Aspects类和其他任何正常的bean一样,除了它们将会用@AspectJ注解之外,它和其他类一样可能有方法和字段,如下所示:

    package org.xyz;
    
    import org.aspectj.lang.annotation.Aspect;
    
    @Aspect
    public class AspectModule {
    
    }

    它们将在XML中按照如下进行配置,就和其他任何bean一样:

    <bean id = "myAspect" class = "org.xyz.AspectModule">
       <!-- configure properties of aspect here as normal -->
    </bean>

    2、声明一个pointcut(切入点)

    切入点有助于确定要用不同建议执行的关联点(即方法)。在使用基于@AspectJ的配置时,切入点声明有两部分:

    • 一个切入点表达式,确定我们要用哪些方法执行。

    • 包括名称和任意数量的参数的切入点签名。该方法的实体是无关紧要的,其实应该是空的。

    以下示例定义了一个名为“businessService”的切入点,它将匹配com.xyz.myapp.service包下的类中可用的每个方法的执行:

    import org.aspectj.lang.annotation.Pointcut;
    
    @Pointcut("execution(* com.xyz.myapp.service.*.*(..))") // expression 
    private void businessService() {}  // signature

    以下示例定义了一个名为“getname”的切入点,该切入点将匹配在包com.tutorialspoint下的Student类中可用的getName()方法的执行:

    import org.aspectj.lang.annotation.Pointcut;
    
    @Pointcut("execution(* com.tutorialspoint.Student.getName(..))") 
    private void getname() {}

    提示:

    ①类似:“execution(*com.tutorialspoint.Student.getName(..))”这样的语法叫做AspectJ切入点语法,参考:http://www.cnblogs.com/EasonJim/p/6901806.html

    ②官方文档关于AspectJ的介绍:https://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html#aop-ataspectj

    3、声明建议(通知类型)

    你可以使用代码片段中给出的@{ADVICE-NAME}注释声明建议五个中的任何一个。这假设你已经定义了一个切入点签名方法businessService():

    @Before("businessService()")
    public void doBeforeTask(){
       ...
    }
    
    @After("businessService()")
    public void doAfterTask(){
       ...
    }
    
    @AfterReturning(pointcut="businessService()", returning="retVal")
    public void doAfterReturnningTask(Object retVal) {
       // you can intercept retVal here.
       ...
    }
    
    @AfterThrowing(pointcut="businessService()", throwing="ex")
    public void doAfterThrowingTask(Exception ex) {
      // you can intercept thrown exception here.
      ...
    }
    
    @Around("businessService()")
    public void doAroundTask(){
       ...
    }

    你可以为任何建议内联定义切入点。以下是在建议之前定义内联切入点的示例:

    @Before("execution(* com.xyz.myapp.service.*.*(..))")
    public doBeforeTask(){
       ...
    }

    可以看出代码上的自由度还是非常高的,比如这个在XML中无法实现。

    例子:

    pom.xml:

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
    
      <groupId>com.jsoft.testspring</groupId>
      <artifactId>testaopaspectj</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      <packaging>jar</packaging>
    
      <name>testaopaspectj</name>
      <url>http://maven.apache.org</url>
    
      <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      </properties>
    
      <dependencies>
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>3.8.1</version>
          <scope>test</scope>
        </dependency>
        
        <!-- Spring Core -->
        <!-- http://mvnrepository.com/artifact/org.springframework/spring-core -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>4.1.4.RELEASE</version>
        </dependency>
         
        <!-- Spring Context -->
        <!-- http://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.1.4.RELEASE</version>
        </dependency>
        
        <!-- String AOP -->
        <!-- http://mvnrepository.com/artifact/org.springframework/spring-aop -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>4.1.4.RELEASE</version>
        </dependency>
        
        <!-- aspectjrt.jar -->
        <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.8.10</version>
        </dependency>
    
        <!-- aspectjweaver.jar -->
        <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.10</version>
        </dependency>
        
      </dependencies>
    </project>

    Student.java:

    package com.jsoft.testspring.testaopaspectj;
    
    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();
        }
    }

    Logging.java:

    package com.jsoft.testspring.testaopaspectj;
    
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.AfterThrowing;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    
    @Aspect
    public class Logging {
    
           @Pointcut("execution(* com.jsoft.testspring..*.*(..))")
           private void selectAll(){}
    
           @Before("selectAll()")
           public void beforeAdvice(){
              System.out.println("Going to setup student profile.");
           }
    
           @After("selectAll()")
           public void afterAdvice(){
              System.out.println("Student profile has been setup.");
           }
    
           @AfterReturning(pointcut="selectAll()", returning="retVal")
           public void afterReturningAdvice(Object retVal){
              System.out.println("Returning:" + retVal.toString() );
           }
    
           @AfterThrowing(pointcut="selectAll()", throwing="ex")
           public void AfterThrowingAdvice(IllegalArgumentException ex){
              System.out.println("There has been an exception: " + ex.toString());   
           }  
    }

    beans.xml:

    <?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.xsd 
                            http://www.springframework.org/schema/aop 
                            http://www.springframework.org/schema/aop/spring-aop.xsd">
    
       <aop:aspectj-autoproxy/>
    
       <bean id="student" class="com.jsoft.testspring.testaopaspectj.Student">
          <property name="name"  value="Zara" />
          <property name="age"  value="11"/>      
       </bean>
    
       <bean id="logging" class="com.jsoft.testspring.testaopaspectj.Logging"/> 
    
    </beans>

    这里定义looging的bean是用于实例化。

    App.java:

    package com.jsoft.testspring.testaopaspectj;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    /**
     * Hello world!
     *
     */
    public class App {
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
            Student student = (Student) context.getBean("student");
            student.getName();
            student.getAge();
            student.printThrowException();
        }
    }

    测试结果:

    测试工程:https://github.com/easonjim/5_java_example/tree/master/springtest/test16/testaopaspectj

  • 相关阅读:
    Log4j中conversionPattern的含义
    log4j.xml写入数据库,只有SQL和参数,无其他信息
    windows下根据进程ID强制杀死进程
    github简单使用教程
    junit mockito
    获取oracle 随机数
    循环插入oracle 存储过程
    2.1. 创建GitHub账号
    oracle 复制表结构表数据
    命令模式
  • 原文地址:https://www.cnblogs.com/EasonJim/p/6906218.html
Copyright © 2020-2023  润新知