1 概述
面向方面编程(AOP)框架是Spring框架的关键组件之一。面向方面编程需要将程序逻辑分解成称为所谓问题的不同部分。横跨应用程序多个点的功能称为横切关注点。这些交叉问题在概念上与应用程序的业务逻辑分开。有各种常见的很好的例子,如日志记录,审计,声明式交易,安全性,缓存等。
OOP模块化的关键单元是类,而在AOP中,模块化的单元是方面。依赖注入可帮助您将应用程序对象彼此分离,而AOP可帮助您将交叉关注与其影响的对象分离开来。AOP就像Perl,.NET,Java等编程语言中的触发器。
Spring AOP模块允许拦截器拦截应用程序。例如,执行方法时,可以在方法执行之前或之后添加额外的功能。
2 核心概念
在我们开始使用AOP之前,让我们熟悉AOP的概念和术语。这些术语并非特定于Spring,而是与AOP相关。
Sr.No. | 条款和说明 |
---|---|
1 | Aspect 一个模块,它具有一组提供交叉要求的API。例如,日志记录模块将被称为AOP方面。根据需求,应用程序可以有任何数量的方面。 |
2 | Join point 这代表了您的应用程序中可插入AOP方面的一点。您也可以说,它是应用程序中使用Spring AOP框架进行操作的实际位置。 |
3 | Advice
扫描二维码关注公众号,回复:
812128 查看本文章
这是在方法执行之前或之后执行的实际操作。这是Spring AOP框架在程序执行期间调用的实际代码片段。 |
4 | PointCut 这是一组需要执行建议的一个或多个连接点。您可以使用表达式或模式指定PointCuts,如我们将在AOP示例中看到的那样。 |
5 | Introduction 介绍允许您将新方法或属性添加到现有类。 |
6 | Target object 目标被一个或多个方面提供建议。该对象将始终是代理对象。也称为建议对象。 |
7 | Weaving 编织是将方面与其他应用程序类型或对象链接以创建建议对象的过程。这可以在编译时,加载时或运行时完成。 |
3 Advice类型
Spring方面可以使用下表中提到的五种建议。
Sr.No. | 建议和说明 |
---|---|
1 | before 在方法执行之前运行建议。 |
2 | after 无论结果如何,在方法执行后运行建议。 |
3 | after-returning 只有当方法成功完成时,才会在方法执行后运行通知。 |
4 | after-throwing 只有当方法通过抛出异常退出时,才会在方法执行后运行通知。 |
5 | around 在调用建议的方法之前和之后运行建议。 |
4 实现
Spring支持@AspectJ注释风格方法和基于模式的方法来实现自定义方面。
基于XML模式
方面是使用常规类和基于XML的配置来实现的。
要使用本节中描述的AOP名称空间标记,您需要导入spring AOP模式,如下所述 -
<?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 "> <!-- bean definition & AOP specific configuration --> </beans>
声明一个Aspect
使用<aop:aspect>元素声明一个Aspect,并且使用ref属性引用辅助bean ,如下所示。
<aop:config> <aop:aspect id = "myAspect" ref = "aBean"> ... </aop:aspect> </aop:config> <bean id = "aBean" class = "..."> ... </bean>
在这里,“aBean”将被配置,并像其他Spring bean那样依赖注入,就像你在前面的章节中看到的一样。
声明一个PointCut
一个切入点有助于确定不同的意见执行感兴趣的连接点(即方法)。在使用基于XML Schema的配置时,PointCut将被定义如下 -
<aop:config> <aop:aspect id = "myAspect" ref = "aBean"> <aop:PointCut id = "businessService" expression = "execution(* com.xyz.myapp.service.*.*(..))"/> ... </aop:aspect> </aop:config> <bean id = "aBean" class = "..."> ... </bean>
以下示例定义了一个名为'businessService'的PointCut,它将与com.tutorialspoint包下的Student类中可用的getName()方法的执行相匹配。
<aop:config> <aop:aspect id = "myAspect" ref = "aBean"> <aop:PointCut id = "businessService" expression = "execution(* com.tutorialspoint.Student.getName(..))"/> ... </aop:aspect> </aop:config> <bean id = "aBean" class = "..."> ... </bean>
声明Advices
您可以使用<aop:{ADVICE NAME}>元素在<aop:aspect>中声明五个建议中的任何一个,如下所示。
<aop:config> <aop:aspect id = "myAspect" ref = "aBean"> <aop:PointCut id = "businessService" expression = "execution(* com.xyz.myapp.service.*.*(..))"/> <!-- a before advice definition --> <aop:before PointCut-ref = "businessService" method = "doRequiredTask"/> <!-- an after advice definition --> <aop:after PointCut-ref = "businessService" method = "doRequiredTask"/> <!-- an after-returning advice definition --> <!--The doRequiredTask method must have parameter named retVal --> <aop:after-returning PointCut-ref = "businessService" returning = "retVal" method = "doRequiredTask"/> <!-- an after-throwing advice definition --> <!--The doRequiredTask method must have parameter named ex --> <aop:after-throwing PointCut-ref = "businessService" throwing = "ex" method = "doRequiredTask"/> <!-- an around advice definition --> <aop:around PointCut-ref = "businessService" method = "doRequiredTask"/> ... </aop:aspect> </aop:config> <bean id = "aBean" class = "..."> ... </bean>
您可以 针对不同的建议使用相同的doRequiredTask或不同的方法。这些方法将被定义为方面模块的一部分。
基于@AspectJ
@AspectJ引用一种将方面声明为Java 5注释中标注的常规Java类的样式。@AspectJ引用一种将方面声明为Java 5注释中标注的常规Java类的样式。通过在基于XML架构的配置文件中包含以下元素来启用@AspectJ支持。
<aop:aspectj-autoproxy/>
声明一个Aspect
方面类与任何其他正常的bean类似,并且可能像任何其他类一样具有方法和字段,但它们将使用@Aspect注释,如下所示。
package org.xyz; import org.aspectj.lang.annotation.Aspect; @Aspect public class AspectModule { }
它们将像下面的任何其他bean一样在XML中进行配置。
<bean id = "myAspect" class = "org.xyz.AspectModule"> <!-- configure properties of aspect here as normal --> </bean>
声明一个PointCut
一个切入点有助于确定不同的意见执行感兴趣的连接点(即方法)。在使用基于@AspectJ的配置时,PointCut声明包含两个部分 -
-
一个PointCut表达式,它确切地确定我们感兴趣的方法执行。
-
包含名称和任意数量参数的PointCut签名。该方法的实际内容是不相关的,实际上应该是空的。
以下示例定义了一个名为'businessService'的PointCut,它将与包com.xyz.myapp.service下的类中可用的每个方法的执行相匹配。
import org.aspectj.lang.annotation.PointCut; @PointCut("execution(* com.xyz.myapp.service.*.*(..))") // expression private void businessService() {} // signature
以下示例定义了一个名为'getname'的PointCut,它将与com.tutorialspoint包下的Student类中可用的getName()方法的执行相匹配。
import org.aspectj.lang.annotation.PointCut; @PointCut("execution(* com.tutorialspoint.Student.getName(..))") private void getname() {}
声明Advices
您可以使用@ {ADVICE-NAME}注释声明以下给出的五种建议中的任何一种。这假定您已经定义了PointCut签名方法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(){ ... }
您可以为任何建议内联定义PointCut。以下是定义内联PointCut for before advice的示例。
@Before("execution(* com.xyz.myapp.service.*.*(..))") public doBeforeTask(){ ... }
5 基于XML的应用程序
在本章中,我们将使用Spring AOP框架编写实际的AOP应用程序。在开始使用Spring-WS框架编写第一个示例之前,您必须确保已经按照Spring Web Services - 环境设置章节中的说明正确设置了Spring AOP环境。
现在,继续编写一个简单的控制台控制的Spring AOP应用程序,它将演示AOP概念。
创建一个项目
第1步 - 打开命令控制台,进入C:\ MVN目录并执行以下mvn命令。
C:\MVN>mvn archetype:generate -DgroupId = com.tutorialspoint -DartifactId = Student -DarchetypeArtifactId = maven-archetype-quickstart -DinteractiveMode = false
Maven将开始处理并创建完整的Java应用程序项目结构。
[INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building Maven Stub Project (No POM) 1 [INFO] ------------------------------------------------------------------------ [INFO] [INFO] >>> maven-archetype-plugin:2.4:generate (default-cli) > generate-sources @ standalone-pom >>> [INFO] [INFO] <<< maven-archetype-plugin:2.4:generate (default-cli) < generate-sources @ standalone-pom <<< [INFO] [INFO] --- maven-archetype-plugin:2.4:generate (default-cli) @ standalone-pom -- - [INFO] Generating project in Batch mode Downloading: https://repo.maven.apache.org/maven2/org/apache/maven/archetypes/ma ven-archetype-quickstart/1.0/maven-archetype-quickstart-1.0.jar Downloaded: https://repo.maven.apache.org/maven2/org/apache/maven/archetypes/mav en-archetype-quickstart/1.0/maven-archetype-quickstart-1.0.jar (5 KB at 1.1 KB/s ec) Downloading: https://repo.maven.apache.org/maven2/org/apache/maven/archetypes/ma ven-archetype-quickstart/1.0/maven-archetype-quickstart-1.0.pom Downloaded: https://repo.maven.apache.org/maven2/org/apache/maven/archetypes/mav en-archetype-quickstart/1.0/maven-archetype-quickstart-1.0.pom (703 B at 1.2 KB/ sec) [INFO] ------------------------------------------------------------------------- --- [INFO] Using following parameters for creating project from Old (1.x) Archetype: maven-archetype-quickstart:1.0 [INFO] ------------------------------------------------------------------------- --- [INFO] Parameter: groupId, Value: com.tutorialspoint [INFO] Parameter: packageName, Value: com.tutorialspoint [INFO] Parameter: package, Value: com.tutorialspoint [INFO] Parameter: artifactId, Value: Student [INFO] Parameter: basedir, Value: C:\MVN [INFO] Parameter: version, Value: 1.0-SNAPSHOT [INFO] project created from Old (1.x) Archetype in dir: C:\MVN\Student [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 01:17 min [INFO] Finished at: 2017-02-19T21:11:14+05:30 [INFO] Final Memory: 15M/114M [INFO] ------------------------------------------------------------------------
第2步 - 转到C:/ MVN目录。您将看到一个创建的Java应用程序项目,名为student(如artifactId中所指定)。更新POM.xml以包含Spring-AOP依赖项。添加MainApp.java,Student.java和Logging.java文件。
的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/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.tutorialspoint</groupId> <artifactId>Student</artifactId> <packaging>jar</packaging> <version>1.0-SNAPSHOT</version> <name>Student</name> <url>http://maven.apache.org</url> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>4.1.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.1.4.RELEASE</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.6.8</version> </dependency> </dependencies> </project> package com.tutorialspoint; public class Logging { /** * This is the method which I would like to execute * before a selected method execution. */ 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. */ 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. */ 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. */ public void AfterThrowingAdvice(IllegalArgumentException ex) { System.out.println("There has been an exception: " + ex.toString()); } }
以下是Student.java文件的内容。
package com.tutorialspoint; 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(); } }
以下是MainApp.java文件的内容。
package com.tutorialspoint; 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"); student.getName(); student.getAge(); student.printThrowException(); } }
第3步 - 在src> main>资源文件夹下添加配置文件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-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd "> <aop:config> <aop:aspect id = "log" ref = "logging"> <aop:PointCut id = "selectAll" expression = "execution(* com.tutorialspoint.*.*(..))"/> <aop:before PointCut-ref = "selectAll" method = "beforeAdvice"/> <aop:after PointCut-ref = "selectAll" method = "afterAdvice"/> <aop:after-returning PointCut-ref = "selectAll" returning = "retVal" method = "afterReturningAdvice"/> <aop:after-throwing PointCut-ref = "selectAll" throwing = "ex" method = "AfterThrowingAdvice"/> </aop:aspect> </aop:config> <!-- Definition for student bean --> <bean id = "student" class = "com.tutorialspoint.Student"> <property name = "name" value = "Zara" /> <property name = "age" value = "11"/> </bean> <!-- Definition for logging aspect --> <bean id = "logging" class = "com.tutorialspoint.Logging"/> </beans>
第4步 - 打开命令控制台,进入C:\ MVN目录并执行以下mvn命令。
C:\MVN>Student> mvn package
Maven将开始处理和下载所需的库。
[INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building Student 1.0-SNAPSHOT [INFO] ------------------------------------------------------------------------ Downloading: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven -jar-plugin/2.4/maven-jar-plugin-2.4.pom Downloaded: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven- jar-plugin/2.4/maven-jar-plugin-2.4.pom (6 KB at 2.2 KB/sec) Downloading: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven -jar-plugin/2.4/maven-jar-plugin-2.4.jar Downloaded: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven- jar-plugin/2.4/maven-jar-plugin-2.4.jar (34 KB at 31.6 KB/sec) Downloading: https://repo.maven.apache.org/maven2/org/springframework/spring-aop /4.1.0.RELEASE/spring-aop-4.1.0.RELEASE.pom Downloaded: https://repo.maven.apache.org/maven2/org/springframework/spring-aop/ 4.1.0.RELEASE/spring-aop-4.1.0.RELEASE.pom (3 KB at 3.7 KB/sec) Downloading: https://repo.maven.apache.org/maven2/org/springframework/spring-bea ns/4.1.0.RELEASE/spring-beans-4.1.0.RELEASE.pom Downloaded: https://repo.maven.apache.org/maven2/org/springframework/spring-bean s/4.1.0.RELEASE/spring-beans-4.1.0.RELEASE.pom (3 KB at 4.1 KB/sec) Downloading: https://repo.maven.apache.org/maven2/org/springframework/spring-cor e/4.1.0.RELEASE/spring-core-4.1.0.RELEASE.pom Downloaded: https://repo.maven.apache.org/maven2/org/springframework/spring-core /4.1.0.RELEASE/spring-core-4.1.0.RELEASE.pom (3 KB at 4.0 KB/sec) Downloading: https://repo.maven.apache.org/maven2/org/springframework/spring-aop /4.1.0.RELEASE/spring-aop-4.1.0.RELEASE.jar Downloading: https://repo.maven.apache.org/maven2/org/springframework/spring-cor e/4.1.0.RELEASE/spring-core-4.1.0.RELEASE.jar Downloading: https://repo.maven.apache.org/maven2/org/springframework/spring-bea ns/4.1.0.RELEASE/spring-beans-4.1.0.RELEASE.jar Downloaded: https://repo.maven.apache.org/maven2/org/springframework/spring-aop/ 4.1.0.RELEASE/spring-aop-4.1.0.RELEASE.jar (351 KB at 43.9 KB/sec) Downloaded: https://repo.maven.apache.org/maven2/org/springframework/spring-bean s/4.1.0.RELEASE/spring-beans-4.1.0.RELEASE.jar (685 KB at 37.5 KB/sec) Downloaded: https://repo.maven.apache.org/maven2/org/springframework/spring-core /4.1.0.RELEASE/spring-core-4.1.0.RELEASE.jar (982 KB at 47.1 KB/sec) [INFO] [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ Student -- - [WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent! [INFO] skip non existing resourceDirectory C:\MVN\Student\src\main\resources [INFO] [INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ Student --- [INFO] Changes detected - recompiling the module! [WARNING] File encoding has not been set, using platform encoding Cp1252, i.e. b uild is platform dependent! [INFO] Compiling 1 source file to C:\MVN\Student\target\classes [INFO] [INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ St udent --- [WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent! [INFO] skip non existing resourceDirectory C:\MVN\Student\src\test\resources [INFO] [INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ Student --- [INFO] Changes detected - recompiling the module! [WARNING] File encoding has not been set, using platform encoding Cp1252, i.e. b uild is platform dependent! [INFO] Compiling 1 source file to C:\MVN\Student\target\test-classes [INFO] [INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ Student --- [INFO] Surefire report directory: C:\MVN\Student\target\surefire-reports Downloading: https://repo.maven.apache.org/maven2/org/apache/maven/surefire/sure fire-junit3/2.12.4/surefire-junit3-2.12.4.pom Downloaded: https://repo.maven.apache.org/maven2/org/apache/maven/surefire/suref ire-junit3/2.12.4/surefire-junit3-2.12.4.pom (2 KB at 1.3 KB/sec) Downloading: https://repo.maven.apache.org/maven2/org/apache/maven/surefire/sure fire-junit3/2.12.4/surefire-junit3-2.12.4.jar Downloaded: https://repo.maven.apache.org/maven2/org/apache/maven/surefire/suref ire-junit3/2.12.4/surefire-junit3-2.12.4.jar (26 KB at 27.7 KB/sec) ------------------------------------------------------- T E S T S ------------------------------------------------------- Running com.tutorialspoint.AppTest Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.002 sec Results : Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 [INFO] [INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ Student --- Downloading: https://repo.maven.apache.org/maven2/classworlds/classworlds/1.1-al pha-2/classworlds-1.1-alpha-2.jar Downloaded: https://repo.maven.apache.org/maven2/classworlds/classworlds/1.1-alp ha-2/classworlds-1.1-alpha-2.jar (37 KB at 35.8 KB/sec) [INFO] Building jar: C:\MVN\Student\target\Student-1.0-SNAPSHOT.jar [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 38.441 s [INFO] Finished at: 2017-02-19T21:18:59+05:30 [INFO] Final Memory: 18M/109M [INFO] ------------------------------------------------------------------------
在Eclipse中导入项目
第1步 - 打开Eclipse。
第2步 - 选择文件→导入→选项。
第3步 - 选择Maven项目选项。点击下一步按钮。
第4步 - 选择项目位置,其中学生项目是使用Maven创建的。
第5步 - 点击完成按钮。
运行项目
完成创建源文件和配置文件后,运行您的应用程序。右键单击应用程序中的MainApp.java并使用作为Java应用程序命令运行。如果你的应用程序一切正常,它将打印下面的消息。
Going to setup student profile. Name : Zara Student profile has been setup. Returning: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 Exception in thread "main" java.lang.IllegalArgumentException at com.tutorialspoint.Student.printThrowException(Student.java:25) at com.tutorialspoint.Student$$FastClassBySpringCGLIB$$7dc55815.invoke(<generated>) at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:717) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:52) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.aspectj.AspectJAfterAdvice.invoke(AspectJAfterAdvice.java:43) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:52) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:58) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653) at com.tutorialspoint.Student$$EnhancerBySpringCGLIB$$56a970f2.printThrowException(<generated>) at com.tutorialspoint.MainApp.main(MainApp.java:16)
6 基于XML的PointCut
加入点Join Point
JoinPoint代表了应用程序中可以插入AOP方面的一个点。您也可以说,它是应用程序中使用Spring AOP框架进行操作的实际位置。考虑下面的例子 -
-
包中包含的所有方法类。
-
一类的特定方法。
切入点PointCut
PointCut是一组需要执行建议的一个或多个JoinPoints。您可以使用表达式或模式指定PointCuts,如我们将在AOP示例中看到的那样。在Spring中,PointCut帮助使用特定的JoinPoints来应用建议。考虑下面的例子 -
-
expression =“execution(* com.tutorialspoint。*。*(..))”
-
expression =“execution(* com.tutorialspoint.Student.getName(..))”
语法
<aop:config> <aop:aspect id = "log" ref = "adviceClass"> <aop:PointCut id = "PointCut-id" expression = "execution( expression )"/> </aop:aspect> </aop:config>
哪里,
-
adviceClass - 包含建议方法的类的ref
-
PointCut-id - PointCut的ID
-
execution(expression) - 表达式覆盖要应用建议的方法。
为了理解上面提到的有关JoinPoint和PointCut的概念,让我们编写一个实现少量PointCut的例子。为了编写我们的示例,我们提供了一些可用的Eclipse IDE,并使用以下步骤创建Spring应用程序。
步 | 描述 |
---|---|
1 | 更新根据Spring AOP - Application章节创建的项目Student。 |
2 | 更新bean配置并按照下面的说明运行应用程序。 |
以下是Logging.java文件的内容。这实际上是一个aspect模块的样本,它定义了在各个点上调用的方法。
package com.tutorialspoint; public class Logging { /** * This is the method which I would like to execute * before a selected method execution. */ public void beforeAdvice(){ System.out.println("Going to setup student profile."); } }
以下是Student.java文件的内容。
package com.tutorialspoint; 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(); } }
以下是MainApp.java文件的内容。
package com.tutorialspoint; 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"); student.getName(); student.getAge(); } }
以下是配置文件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-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd "> <aop:config> <aop:aspect id = "log" ref = "logging"> <aop:PointCut id = "selectAll" expression = "execution(* com.tutorialspoint.*.*(..))"/> <aop:before PointCut-ref = "selectAll" method = "beforeAdvice"/> </aop:aspect> </aop:config> <!-- Definition for student bean --> <bean id = "student" class = "com.tutorialspoint.Student"> <property name = "name" value = "Zara" /> <property name = "age" value = "11"/> </bean> <!-- Definition for logging aspect --> <bean id = "logging" class = "com.tutorialspoint.Logging"/> </beans>
完成创建源和bean配置文件后,运行该应用程序。如果应用程序一切正常,它将打印以下消息。
Going to setup student profile. Name : Zara Going to setup student profile. Age : 11
上面定义的<aop:pointcut>选择在com.tutorialspoint包下定义的所有方法。让我们假设,您想要在特定方法之前或之后执行您的建议,您可以定义PointCut以通过用实际的类和方法名称替换PointCut定义中的星号(*)来缩小执行范围。以下是一个修改的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-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd "> <aop:config> <aop:aspect id = "log" ref = "logging"> <aop:PointCut id = "selectAll" expression = "execution(* com.tutorialspoint.Student.getName(..))"/> <aop:before PointCut-ref = "selectAll" method = "beforeAdvice"/> </aop:aspect> </aop:config> <!-- Definition for student bean --> <bean id = "student" class = "com.tutorialspoint.Student"> <property name = "name" value = "Zara" /> <property name = "age" value = "11"/> </bean> <!-- Definition for logging aspect --> <bean id = "logging" class = "com.tutorialspoint.Logging"/> </beans>
运行项目
完成创建源文件和配置文件后,运行您的应用程序。右键单击应用程序中的MainApp.java并使用作为Java应用程序命令运行。如果你的应用程序一切正常,它将打印下面的消息。
Going to setup student profile. Name : Zara Age : 11
7 基于XML的Advice
Before是一种建议类型,它确保在方法执行之前运行建议。以下是before建议的语法。
语法
<aop:config> <aop:aspect id = "log" ref = "logging"> <aop:PointCut id = "PointCut-id" expression = "execution( expression )"/> <aop:before PointCut-ref = "PointCut-id" method = "methodName"/> </aop:aspect> </aop:config>
在这里,
-
PointCut-id - PointCut的ID。
-
methodName - 要调用的函数之前调用的函数的方法名称。
为了理解上述有关Before Advice的概念,让我们编写一个例子,它将实现Before Advice。为了编写我们的示例,我们提供了一些可用的Eclipse IDE,并使用以下步骤创建Spring应用程序。
步 | 描述 |
---|---|
1 | 更新根据Spring AOP - Application章节创建的项目Student。 |
2 | 更新bean配置并按照下面的说明运行应用程序。 |
以下是Logging.java文件的内容。这实际上是一个aspect模块的样本,它定义了在各个点上调用的方法。
package com.tutorialspoint; public class Logging { /** * This is the method which I would like to execute * before a selected method execution. */ public void beforeAdvice(){ System.out.println("Going to setup student profile."); } }
以下是Student.java文件的内容。
package com.tutorialspoint; 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(); } }
以下是MainApp.java文件的内容。
package com.tutorialspoint; 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"); student.getName(); student.getAge(); } }
以下是配置文件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-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd "> <aop:config> <aop:aspect id = "log" ref = "logging"> <aop:PointCut id = "selectAll" expression = "execution(* com.tutorialspoint.Student.getName(..))"/> <aop:before PointCut-ref = "selectAll" method = "beforeAdvice"/> </aop:aspect> </aop:config> <!-- Definition for student bean --> <bean id = "student" class = "com.tutorialspoint.Student"> <property name = "name" value = "Zara" /> <property name = "age" value = "11"/> </bean> <!-- Definition for logging aspect --> <bean id = "logging" class = "com.tutorialspoint.Logging"/> </beans>
运行项目
完成创建源文件和配置文件后,运行您的应用程序。右键单击应用程序中的MainApp.java,并使用作为Java应用程序命令运行。如果你的应用程序一切正常,它将打印下面的消息。
Going to setup student profile. Name : Zara Age : 11
8 基于XML的Advice After
@After是一个建议类型,它确保在方法执行后运行通知。以下是@After建议的语法。
语法
@PointCut("execution(* com.tutorialspoint.Student.getAge(..))") private void selectGetName(){} @After("selectGetAge()") public void afterAdvice(){ System.out.println("Student profile setup completed."); }
在这里,
-
@PointCut - 将一个函数标记为PointCut
-
执行(表达式) - 表达式覆盖要应用建议的方法。
-
@After - 在PointCut覆盖的方法之前将函数标记为要执行的建议。
为了理解上述与@After Advice相关的概念,让我们编写一个实现@After Advice的例子。为了编写我们的示例,我们提供了一些可用的Eclipse IDE,并使用以下步骤创建Spring应用程序。
步 | 描述 |
---|---|
1 | 更新根据Spring AOP - Application章节创建的项目Student。 |
2 | 更新bean配置并按照下面的说明运行应用程序。 |
以下是Logging.java文件的内容。这实际上是一个aspect模块的样本,它定义了在各个点上调用的方法。
package com.tutorialspoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.PointCut; import org.aspectj.lang.annotation.After; @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.tutorialspoint.Student.getAge(..))") private void selectGetAge(){} /** * This is the method which I would like to execute * after a selected method execution. */ @After("selectGetAge()") public void afterAdvice(){ System.out.println("Student profile setup completed."); } }
以下是Student.java文件的内容。
package com.tutorialspoint; 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(); } }
以下是MainApp.java文件的内容。
package com.tutorialspoint; 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"); student.getName(); student.getAge(); } }
以下是配置文件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-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.tutorialspoint.Student"> <property name = "name" value = "Zara" /> <property name = "age" value = "11"/> </bean> <!-- Definition for logging aspect --> <bean id = "logging" class = "com.tutorialspoint.Logging"/> </beans>
运行项目
完成创建源文件和配置文件后,运行您的应用程序。右键单击应用程序中的MainApp.java并使用作为Java应用程序命令运行。如果你的应用程序一切正常,它将打印下面的消息。
Name : Zara Age : 11 Student profile setup completed.
上面定义的@Pointcut使用表达式来选择在com.tutorialspoint包下的类(es)中定义的方法getAge()。@After建议使用上面定义的PointCut作为参数。在上述PointCut覆盖的每个方法之前,有效地调用After()方法。
9 基于XML的返回Adivice After
After是一种建议类型,只有当方法成功完成时,才能确保在方法执行后运行通知。以下是after建议的语法。
语法
<aop:config> <aop:aspect id = "log" ref = "logging"> <aop:PointCut id = "PointCut-id" expression = "execution( expression )"/> <aop:after-returning PointCut-ref = "PointCut-id" returning = "retVal" method = "methodName"/> </aop:aspect> </aop:config>
哪里,
-
PointCut-id - PointCut的ID。
-
methodName - 被调用函数成功返回后要调用的函数的方法名称。
为了理解上述有关返回建议后的概念,让我们编写一个将在返回建议后执行的示例。为了编写我们的示例,只需要很少的建议,让我们有一个可用的Eclipse IDE,并使用以下步骤创建一个Spring应用程序 -
步 | 描述 |
---|---|
1 | 更新根据Spring AOP - Application章节创建的项目Student。 |
2 | 更新bean配置并按照下面的说明运行应用程序。 |
以下是Logging.java文件的内容。这实际上是一个aspect模块的样本,它定义了在各个点上调用的方法。
package com.tutorialspoint; public class Logging { /** * This is the method which I would like to execute * when any method returns. */ public void afterReturningAdvice(Object retVal){ System.out.println("Returning:" + retVal.toString() ); } }
以下是Student.java文件的内容。
package com.tutorialspoint; 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 ); System.out.println("Exception raised"); throw new IllegalArgumentException(); 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(); } }
以下是MainApp.java文件的内容。
package com.tutorialspoint; 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"); student.getName(); student.getAge(); } }
以下是配置文件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-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd "> <aop:config> <aop:aspect id = "log" ref = "logging"> <aop:PointCut id = "selectAll" expression = "execution(* com.tutorialspoint.*.*(..))"/> <aop:after-returning PointCut-ref = "selectAll" method = "afterReturningAdvice" returning = "retVal"/> </aop:aspect> </aop:config> <!-- Definition for student bean --> <bean id = "student" class = "com.tutorialspoint.Student"> <property name = "name" value = "Zara" /> <property name = "age" value = "11"/> </bean> <!-- Definition for logging aspect --> <bean id = "logging" class = "com.tutorialspoint.Logging"/> </beans>
运行项目
完成创建源文件和配置文件后,运行您的应用程序。右键单击应用程序中的MainApp.java并使用作为Java应用程序命令运行。如果你的应用程序一切正常,它将打印下面的消息。
Name : Zara Returning : Name Age : 11 Exception raised
10 基于XML的After Throwing Advice
After-throwing是一种建议类型,只有当方法通过抛出异常退出时,才能确保在方法执行后运行通知。以下是投掷后建议的语法。
语法
<aop:config> <aop:aspect id = "log" ref = "logging"> <aop:PointCut id = "PointCut-id" expression = "execution( expression )"/> <aop:after-throwing PointCut-ref = "PointCut-id" throwing = "ex" method = "methodName"/> </aop:aspect> </aop:config>
哪里,
-
PointCut-id - PointCut的ID。
-
ex - 抛出异常。
-
methodName - 当被调用函数抛出异常并退出时要调用的函数的方法名称。
为了理解上述有关投掷建议的概念,让我们编写一个实施投掷建议后的示例。为了编写我们的示例,只需要很少的建议,让我们有一个可用的Eclipse IDE,并使用以下步骤创建一个Spring应用程序 -
步 | 描述 |
---|---|
1 | 更新根据Spring AOP - Application章节创建的项目Student。 |
2 | 更新bean配置并按照下面的说明运行应用程序。 |
以下是Logging.java文件的内容。这实际上是一个aspect模块的样本,它定义了在各个点上调用的方法。
package com.tutorialspoint; public class Logging { /** * This is the method which I would like to execute * if there is an exception raised. */ public void afterThrowingAdvice(IllegalArgumentException ex) { System.out.println("There has been an exception: " + ex.toString()); } }
以下是Student.java文件的内容。
package com.tutorialspoint; 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(); } }
以下是MainApp.java文件的内容。
package com.tutorialspoint; 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"); student.printThrowException(); } }
以下是配置文件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-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd "> <aop:config> <aop:aspect id = "log" ref = "logging"> <aop:PointCut id = "selectAll" expression = "execution(* com.tutorialspoint.*.*(..))"/> <aop:after-throwing PointCut-ref = "selectAll" throwing = "ex" method = "afterThrowingAdvice"/> </aop:aspect> </aop:config> <!-- Definition for student bean --> <bean id = "student" class = "com.tutorialspoint.Student"> <property name = "name" value = "Zara" /> <property name = "age" value = "11"/> </bean> <!-- Definition for logging aspect --> <bean id = "logging" class = "com.tutorialspoint.Logging"/> </beans>
运行项目
完成创建源文件和配置文件后,运行您的应用程序。右键单击应用程序中的MainApp.java并使用作为Java应用程序命令运行。如果你的应用程序一切正常,它将打印下面的消息。
Exception raised There has been an exception: java.lang.IllegalArgumentException Exception in thread "main" java.lang.IllegalArgumentException at com.tutorialspoint.Student.printThrowException(Student.java:25) at com.tutorialspoint.Student$$FastClassBySpringCGLIB$$7dc55815.invoke(<generated>>) at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:717) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:58) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653) at com.tutorialspoint.Student$$EnhancerBySpringCGLIB$$8514cd8.printThrowException(<generated>) at com.tutorialspoint.MainApp.main(MainApp.java:15)
11 基于XML的Around Advice
Around是一种建议类型,可确保在方法执行之前和之后运行通知。以下是around建议的语法。
语法
<aop:config> <aop:aspect id = "log" ref = "logging"> <aop:PointCut id = "PointCut-id" expression = "execution( expression )"/> <aop:around PointCut-ref = "PointCut-id" method = "methodName"/> </aop:aspect> </aop:config>
哪里,
-
PointCut-id - PointCut的ID。
-
methodName - 要调用的函数之前调用的函数的方法名称。
为了理解上述有关Around Advice的概念,让我们编写一个实施Around Advice的示例。为了编写我们的示例,只需要很少的建议,让我们有一个可用的Eclipse IDE,并使用以下步骤创建一个Spring应用程序 -
步 | 描述 |
---|---|
1 | 更新根据Spring AOP - Application章节创建的项目Student。 |
2 | 更新bean配置并按照下面的说明运行应用程序。 |
以下是Logging.java文件的内容。这实际上是一个aspect模块的样本,它定义了在各个点上调用的方法。
package com.tutorialspoint; import org.aspectj.lang.ProceedingJoinPoint; public class Logging { /** * This is the method which I would like to execute * around a selected method execution. */ public String aroundAdvice(ProceedingJoinPoint jp) throws Throwable{ System.out.println("Around advice"); Object[] args = jp.getArgs(); if(args.length>0){ System.out.print("Arguments passed: " ); for (int i = 0; i < args.length; i++) { System.out.print("arg "+(i+1)+": "+args[i]); } } Object result = jp.proceed(args); System.out.println("Returning " + result); return result.toString(); } }
以下是Student.java文件的内容。
package com.tutorialspoint; 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(); } }
以下是MainApp.java文件的内容。
package com.tutorialspoint; 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"); student.getName(); } }
以下是配置文件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-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd "> <aop:config> <aop:aspect id = "log" ref = "logging"> <aop:PointCut id = "selectName" expression = "execution(* com.tutorialspoint.Student.getName(..))"/> <aop:around PointCut-ref = "selectName" method = "aroundAdvice"/> </aop:aspect> </aop:config> <!-- Definition for student bean --> <bean id = "student" class = "com.tutorialspoint.Student"> <property name = "name" value = "Zara" /> <property name = "age" value = "11"/> </bean> <!-- Definition for logging aspect --> <bean id = "logging" class = "com.tutorialspoint.Logging"/> </beans>
运行项目
完成创建源文件和配置文件后,运行您的应用程序。右键单击应用程序中的MainApp.java并使用作为Java应用程序命令运行。如果你的应用程序一切正常,它将打印下面的消息。
Around advice Name : Zara Returning Zara
12 基于注解的应用程序
让我们编写一个将使用基于Annotation的配置实现建议的示例。为此,让我们有一个可用的Eclipse IDE,并使用以下步骤创建Spring应用程序。
步 | 描述 |
---|---|
1 | 更新根据Spring AOP - Application章节创建的项目Student。 |
2 | 更新bean配置并按照下面的说明运行应用程序。 |
以下是Logging.java文件的内容。这实际上是一个aspect模块的样本,它定义了在各个点上调用的方法。
package com.tutorialspoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.PointCut; @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.tutorialspoint.*.*(..))") 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."); } }
以下是Student.java文件的内容。
package com.tutorialspoint; 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(); } }
以下是MainApp.java文件的内容。
package com.tutorialspoint; 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"); student.getName(); student.getAge(); } }
以下是配置文件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-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.tutorialspoint.Student"> <property name = "name" value = "Zara" /> <property name = "age" value = "11"/> </bean> <!-- Definition for logging aspect --> <bean id = "logging" class = "com.tutorialspoint.Logging"/> </beans>
运行项目
完成创建源文件和配置文件后,运行您的应用程序。右键单击应用程序中的MainApp.java并使用作为Java应用程序命令运行。如果你的应用程序一切正常,它将打印下面的消息。
Going to setup student profile. Name : Zara Going to setup student profile. Age : 11
13 基于注解的PointCut
JoinPoint
JoinPoint代表了应用程序中可以插入AOP方面的一个点。您也可以说,它是应用程序中使用Spring AOP框架进行操作的实际位置。考虑下面的例子 -
-
包中包含的所有方法类。
-
一类的特定方法。
切入点
PointCut是一组需要执行建议的一个或多个JoinPoint。您可以使用表达式或模式指定PointCuts,如我们将在AOP示例中看到的那样。在Spring中,PointCut帮助使用特定的JoinPoints来应用建议。考虑下面的例子 -
-
@PointCut(“execution(* com.tutorialspoint。*。*(..))”)
-
@PointCut(“execution(* com.tutorialspoint.Student.getName(..))”)
语法
@Aspect public class Logging { @PointCut("execution(* com.tutorialspoint.*.*(..))") private void selectAll(){} }
哪里,
-
@Aspect - 将类标记为包含建议方法的类。
-
@PointCut - 将一个函数标记为PointCut
-
execution(expression) - 表达式覆盖要应用建议的方法。
为了理解上面提到的有关JoinPoint和PointCut的概念,让我们编写一个实现少量PointCut的例子。为了编写我们的示例,只需要很少的建议,让我们有一个可用的Eclipse IDE,并使用以下步骤创建一个Spring应用程序 -
步 | 描述 |
---|---|
1 | 更新根据Spring AOP - Application章节创建的项目Student。 |
2 | 更新bean配置并按照下面的说明运行应用程序。 |
以下是Logging.java文件的内容。这实际上是一个aspect模块的样本,它定义了在各个点上调用的方法。
package com.tutorialspoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.PointCut; import org.aspectj.lang.annotation.Before; @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.tutorialspoint.*.*(..))") 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."); } }
以下是Student.java文件的内容。
package com.tutorialspoint; 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(); } }
以下是MainApp.java文件的内容。
package com.tutorialspoint; 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"); student.getName(); student.getAge(); } }
以下是配置文件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-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.tutorialspoint.Student"> <property name = "name" value = "Zara" /> <property name = "age" value = "11"/> </bean> <!-- Definition for logging aspect --> <bean id = "logging" class = "com.tutorialspoint.Logging"/> </beans>
运行项目
完成创建源文件和配置文件后,运行您的应用程序。右键单击应用程序中的MainApp.java并使用作为Java应用程序命令运行。如果你的应用程序一切正常,它将打印下面的消息。
Going to setup student profile. Name : Zara Going to setup student profile. Age : 11
上面定义的@Pointcut使用表达式来选择包com.tutorialspoint下定义的所有方法。@Before建议使用上面定义的PointCut作为参数。有效的方法是在上述PointCut覆盖的每个方法之前调用Before()方法。
14 基于注解的Before Advice
@Before是一种建议类型,它确保在方法执行之前运行通知。以下是@Before建议的语法。
语法
@PointCut("execution(* com.tutorialspoint.Student.getName(..))") private void selectGetName(){} @Before("selectGetName()") public void beforeAdvice(){ System.out.println("Going to setup student profile."); }
哪里,
-
@PointCut - 将一个函数标记为PointCut
-
execution(expression) - 表达式覆盖要应用建议的方法。
-
@Before - 在PointCut覆盖的方法之前将函数标记为要执行的建议。
为了理解上述有关@Before Advice的概念,让我们编写一个实现@Before Advice的例子。为了编写我们的示例,只需要很少的建议,让我们有一个可用的Eclipse IDE,并使用以下步骤创建一个Spring应用程序 -
步 | 描述 |
---|---|
1 | 更新根据Spring AOP - Application章节创建的项目Student。 |
2 | 更新bean配置并按照下面的说明运行应用程序。 |
以下是Logging.java文件的内容。这实际上是一个aspect模块的样本,它定义了在各个点上调用的方法。
package com.tutorialspoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.PointCut; import org.aspectj.lang.annotation.Before; @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.tutorialspoint.Student.getName(..))") private void selectGetName(){} /** * This is the method which I would like to execute * before a selected method execution. */ @Before("selectGetName()") public void beforeAdvice(){ System.out.println("Going to setup student profile."); } }
以下是Student.java文件的内容。
package com.tutorialspoint; 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(); } }
以下是MainApp.java文件的内容。
package com.tutorialspoint; 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"); student.getName(); student.getAge(); } }
以下是配置文件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-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.tutorialspoint.Student"> <property name = "name" value = "Zara" /> <property name = "age" value = "11"/> </bean> <!-- Definition for logging aspect --> <bean id = "logging" class = "com.tutorialspoint.Logging"/> </beans>
运行项目
完成创建源文件和配置文件后,运行您的应用程序。右键单击应用程序中的MainApp.java并使用作为Java应用程序命令运行。如果你的应用程序一切正常,它将打印下面的消息。
Going to setup student profile. Name : Zara Age : 11
上面定义的@Pointcut使用表达式来选择在com.tutorialspoint包下的类(es)中定义的方法getAge()。@After建议使用上面定义的PointCut作为参数。在上述PointCut覆盖的每个方法之前,有效地调用After()方法。
15 基于注解的After Advice
@After是一个建议类型,它确保在方法执行后运行通知。以下是@After建议的语法。
语法
@PointCut("execution(* com.tutorialspoint.Student.getAge(..))") private void selectGetName(){} @After("selectGetAge()") public void afterAdvice(){ System.out.println("Student profile setup completed."); }
哪里,
-
@PointCut - 将一个函数标记为PointCut
-
execution(expression) - 表达式覆盖要应用建议的方法。
-
@After - 在PointCut覆盖的方法之前将函数标记为要执行的建议。
为了理解上述与@After Advice相关的概念,让我们编写一个实现@After Advice的例子。为了编写我们的示例,我们提供了一些可用的Eclipse IDE,并使用以下步骤创建Spring应用程序。
步 | 描述 |
---|---|
1 | 更新根据Spring AOP - Application章节创建的项目Student。 |
2 | 更新bean配置并按照下面的说明运行应用程序。 |
以下是Logging.java文件的内容。这实际上是一个aspect模块的样本,它定义了在各个点上调用的方法。
package com.tutorialspoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.PointCut; import org.aspectj.lang.annotation.After; @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.tutorialspoint.Student.getAge(..))") private void selectGetAge(){} /** * This is the method which I would like to execute * after a selected method execution. */ @After("selectGetAge()") public void afterAdvice(){ System.out.println("Student profile setup completed."); } }
以下是Student.java文件的内容。
package com.tutorialspoint; 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(); } }
以下是MainApp.java文件的内容。
package com.tutorialspoint; 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"); student.getName(); student.getAge(); } }
以下是配置文件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-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.tutorialspoint.Student"> <property name = "name" value = "Zara" /> <property name = "age" value = "11"/> </bean> <!-- Definition for logging aspect --> <bean id = "logging" class = "com.tutorialspoint.Logging"/> </beans>
运行项目
完成创建源文件和配置文件后,运行您的应用程序。右键单击应用程序中的MainApp.java并使用作为Java应用程序命令运行。如果你的应用程序一切正常,它将打印下面的消息。
Name : Zara Age : 11 Student profile setup completed.
上面定义的@Pointcut使用表达式来选择在com.tutorialspoint包下的类(es)中定义的方法getAge()。@After建议使用上面定义的PointCut作为参数。在上述PointCut覆盖的每个方法之前,有效地调用After()方法。
16 基于注解的After Returning Advice
@AfterReturning是一个通知类型,它确保在方法成功执行后运行通知。以下是@AfterReturning建议的语法。
语法
@AfterReturning(PointCut = "execution(* com.tutorialspoint.Student.*(..))", returning = "retVal") public void afterReturningAdvice(JoinPoint jp, Object retVal){ System.out.println("Method Signature: " + jp.getSignature()); System.out.println("Returning:" + retVal.toString() ); }
哪里,
-
@AfterReturning - 如果方法成功返回,则将函数标记为要在PointCut覆盖的方法之前执行的建议。
-
PointCut - 提供一个表达式来选择一个函数
-
execution(expression) - 表达式覆盖要应用建议的方法。
-
returning - 要返回的变量的名称。
要理解上述与@AfterReturning Advice相关的概念,让我们编写一个示例,它将实现@AfterReturning Advice。为了编写我们的示例,我们提供了一些可用的Eclipse IDE,并使用以下步骤创建Spring应用程序。
步 | 描述 |
---|---|
1 | 更新根据Spring AOP - Application章节创建的项目Student。 |
2 | 更新bean配置并按照下面的说明运行应用程序。 |
以下是Logging.java文件的内容。这实际上是一个aspect模块的样本,它定义了在各个点上调用的方法。
package com.tutorialspoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.AfterReturning; @Aspect public class Logging { /** * This is the method which I would like to execute * after a selected method execution. */ @AfterReturning(PointCut = "execution(* com.tutorialspoint.Student.*(..))", returning = "retVal") public void afterReturningAdvice(JoinPoint jp, Object retVal){ System.out.println("Method Signature: " + jp.getSignature()); System.out.println("Returning:" + retVal.toString() ); } }
以下是Student.java文件的内容。
package com.tutorialspoint; 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(); } }
以下是MainApp.java文件的内容。
package com.tutorialspoint; 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"); student.getAge(); } }
以下是配置文件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-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.tutorialspoint.Student"> <property name = "name" value = "Zara" /> <property name = "age" value = "11"/> </bean> <!-- Definition for logging aspect --> <bean id = "logging" class = "com.tutorialspoint.Logging"/> </beans>
运行项目
完成创建源文件和配置文件后,运行您的应用程序。右键单击应用程序中的MainApp.java并使用作为Java应用程序命令运行。如果你的应用程序一切正常,它将打印下面的消息。
Age : 11 Method Signature: Integer com.tutorialspoint.Student.getAge() Returning 11
17 基于注解的After Throwing Advice
@AfterThrowing是一种通知类型,可确保在方法抛出异常时运行通知。以下是@AfterThrowing建议的语法。
语法
@AfterThrowing(PointCut = "execution(* com.tutorialspoint.Student.*(..))", throwing = "error") public void afterThrowingAdvice(JoinPoint jp, Throwable error){ System.out.println("Method Signature: " + jp.getSignature()); System.out.println("Exception: "+error); }
哪里,
-
@AfterThrowing - 如果方法抛出异常,则将函数标记为要在PointCut覆盖的方法之前执行的建议。
-
PointCut - 提供一个表达式来选择一个函数。
-
execution(expression) - 表达式覆盖要应用建议的方法。
-
throwing - 要返回的异常的名称。
为了理解上述有关@AfterThrowing Advice的概念,让我们编写一个实现@AfterThrowing Advice的例子。为了编写我们的示例,我们提供了一些可用的Eclipse IDE,并使用以下步骤创建Spring应用程序。
步 | 描述 |
---|---|
1 | 更新根据Spring AOP - Application章节创建的项目Student。 |
2 | 更新bean配置并按照下面的说明运行应用程序。 |
以下是Logging.java文件的内容。这实际上是一个aspect模块的样本,它定义了在各个点上调用的方法。
package com.tutorialspoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.AfterThrowing; @Aspect public class Logging { /** * This is the method which I would like to execute * after a selected method execution throws exception. */ @AfterThrowing(PointCut = "execution(* com.tutorialspoint.Student.*(..))", throwing = "error") public void afterThrowingAdvice(JoinPoint jp, Throwable error){ System.out.println("Method Signature: " + jp.getSignature()); System.out.println("Exception: "+error); } }
以下是Student.java文件的内容。
package com.tutorialspoint; 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(); } }
以下是MainApp.java文件的内容。
package com.tutorialspoint; 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"); student.printThrowException(); } }
以下是配置文件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-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.tutorialspoint.Student"> <property name = "name" value = "Zara" /> <property name = "age" value = "11"/> </bean> <!-- Definition for logging aspect --> <bean id = "logging" class = "com.tutorialspoint.Logging"/> </beans>
运行项目
完成创建源文件和配置文件后,运行您的应用程序。右键单击应用程序中的MainApp.java并使用作为Java应用程序命令运行。如果你的应用程序一切正常,它将打印下面的消息。
Exception raised Method Signature: void com.tutorialspoint.Student.printThrowException() Exception: java.lang.IllegalArgumentException Exception in thread "main" java.lang.IllegalArgumentException at com.tutorialspoint.Student.printThrowException(Student.java:25) at com.tutorialspoint.Student$$FastClassBySpringCGLIB$$7dc55815.invoke(<generated>) at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:717) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:58) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653) at com.tutorialspoint.Student$$EnhancerBySpringCGLIB$$99b0a988.printThrowException(<generated>) at com.tutorialspoint.MainApp.main(MainApp.java:13)
18 基于注解的Around Advice
@Around是一个建议类型,它确保了建议可以在方法执行前后运行。以下是@Around建议的语法。
语法
@PointCut("execution(* com.tutorialspoint.Student.getAge(..))") private void selectGetName(){} @Around("selectGetAge()") public void aroundAdvice(ProceedingJoinPoint proceedingJoinPoint){ System.out.println("Around advice"); Object[] args = jp.getArgs(); if(args.length>0){ System.out.print("Arguments passed: " ); for (int i = 0; i < args.length; i++) { System.out.print("arg "+(i+1)+": "+args[i]); } } Object result = jp.proceed(args); System.out.println("Returning " + result); return result.toString(); }
哪里,
-
@PointCut - 将一个函数标记为PointCut
-
执行(表达式) - 表达式覆盖要应用建议的方法。
-
@Around - 在PointCut覆盖的方法之前将函数标记为要执行的建议。
为了理解上述有关@Around Advice的概念,让我们编写一个实现@Around Advice的示例。为了编写我们的示例,只需要很少的建议,让我们有一个可用的Eclipse IDE,并使用以下步骤创建一个Spring应用程序 -
步 | 描述 |
---|---|
1 | 更新根据Spring AOP - Application章节创建的项目Student。 |
2 | 更新bean配置并按照下面的说明运行应用程序。 |
以下是Logging.java文件的内容。这实际上是一个aspect模块的样本,它定义了在各个点上调用的方法。
package com.tutorialspoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.PointCut; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.ProceedingJoinPoint; @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.tutorialspoint.Student.getAge(..))") private void selectGetAge(){} /** * This is the method which I would like to execute * around a selected method execution. */ @Around("selectGetAge()") public void aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{ System.out.println("Around advice"); Object[] args = proceedingJoinPoint.getArgs(); if(args.length>0){ System.out.print("Arguments passed: " ); for (int i = 0; i < args.length; i++) { System.out.print("arg "+(i+1)+": "+args[i]); } } Object result = proceedingJoinPoint.proceed(args); System.out.println("Returning " + result); } }
以下是Student.java文件的内容。
package com.tutorialspoint; 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(); } }
以下是MainApp.java文件的内容。
package com.tutorialspoint; 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"); student.getAge(); } }
以下是配置文件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-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.tutorialspoint.Student"> <property name = "name" value = "Zara" /> <property name = "age" value = "11"/> </bean> <!-- Definition for logging aspect --> <bean id = "logging" class = "com.tutorialspoint.Logging"/> </beans>
运行项目
完成创建源文件和配置文件后,运行您的应用程序。右键单击应用程序中的MainApp.java并使用作为Java应用程序命令运行。如果你的应用程序一切正常,它将打印下面的消息。
Around advice Age : 11 Returning 11
19 代理
到目前为止,我们已经使用<aop:config>或<aop:aspectj-autoproxy>声明了方面。我们可以编程方式创建代理,也可以使用代理对象以编程方式调用方面。
语法
//Create object to be proxied Student student = new Student(); //Create the Proxy Factory AspectJProxyFactory proxyFactory = new AspectJProxyFactory(student); //Add Aspect class to the factory proxyFactory.addAspect(Logging.class); //Get the proxy object Student proxyStudent = proxyFactory.getProxy(); //Invoke the proxied method. proxyStudent.getAge();
哪里,
-
AspectJProxyFactory - 创建代理对象的工厂类。
-
Logging.class - 包含建议的Aspect类。
-
Student - 商务课程建议。
为了理解上述与代理有关的概念,让我们编写一个实现代理的例子。为了编写我们的示例,只需要很少的建议,让我们有一个可用的Eclipse IDE,并使用以下步骤创建一个Spring应用程序 -
步 | 描述 |
---|---|
1 | 更新根据Spring AOP - Application章节创建的项目Student。 |
2 | 更新bean配置并按照下面的说明运行应用程序。 |
以下是Logging.java文件的内容。这实际上是一个aspect模块的样本,它定义了在各个点上调用的方法。
package com.tutorialspoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.PointCut; import org.aspectj.lang.annotation.Before; @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.tutorialspoint.Student.getAge(..))") private void selectGetAge(){} /** * This is the method which I would like to execute * before a selected method execution. */ @Before("selectGetAge()") public void beforeAdvice(){ System.out.println("Going to setup student profile."); } }
以下是Student.java文件的内容。
package com.tutorialspoint; public class Student { private Integer age; public void setAge(Integer age) { this.age = age; } public Integer getAge() { System.out.println("Age : " + age ); return age; } }
以下是MainApp.java文件的内容。
package com.tutorialspoint; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.aop.aspectj.annotation.AspectJProxyFactory; public class MainApp { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml"); Student student = (Student) context.getBean("student"); //Create the Proxy Factory AspectJProxyFactory proxyFactory = new AspectJProxyFactory(student); //Add Aspect class to the factory proxyFactory.addAspect(Logging.class); //Get the proxy object Student proxyStudent = proxyFactory.getProxy(); //Invoke the proxied method. proxyStudent.getAge(); } }
以下是配置文件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-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd "> <!-- Definition for student bean --> <bean id = "student" class = "com.tutorialspoint.Student"> <property name = "age" value = "11"/> </bean> <!-- Definition for logging aspect --> <bean id = "logging" class = "com.tutorialspoint.Logging"/> </beans>
运行项目
完成创建源文件和配置文件后,运行您的应用程序。右键单击应用程序中的MainApp.java并使用作为Java应用程序命令运行。如果你的应用程序一切正常,它将打印下面的消息。
Going to setup student profile. Age : 11
20 自定义注解
根据PointCut表达式,可能会出现这种情况,它们会应用于其他建议不适用的其他bean。例如,请考虑以下表达式。
execution(* com.tutorialspoint.*.getAge(..))
一个新的spring bean添加了getAge()方法,并且该建议将开始被应用到它,尽管它可能不是有意的。为了达到这个目的,我们可以创建一个自定义注释并注释应用建议的方法。
@Before("@annotation(com.tutorialspoint.Loggable)")
为了理解上述有关@Before Advice的概念,让我们编写一个实现@Before Advice的例子。为了编写我们的示例,我们提供了一些可用的Eclipse IDE,并使用以下步骤创建Spring应用程序。
步 | 描述 |
---|---|
1 | 更新根据Spring AOP - Application章节创建的项目Student。 |
2 | 更新bean配置并按照下面的说明运行应用程序。 |
以下是Logging.java文件的内容。这实际上是一个aspect模块的样本,它定义了在各个点上调用的方法。
package com.tutorialspoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; @Aspect public class Logging { /** * This is the method which I would like to execute * before a selected method execution. */ @Before("@annotation(com.tutorialspoint.Loggable)") public void beforeAdvice(){ System.out.println("Going to setup student profile."); } }
以下是Loggable.java文件的内容-
package com.tutorialspoint; public @interface Loggable { }
以下是Student.java文件的内容。
package com.tutorialspoint; 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; } @Loggable public String getName() { System.out.println("Name : " + name ); return name; } public void printThrowException(){ System.out.println("Exception raised"); throw new IllegalArgumentException(); } }
以下是MainApp.java文件的内容。
package com.tutorialspoint; 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"); student.getName(); student.getAge(); } }
以下是配置文件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-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.tutorialspoint.Student"> <property name = "name" value = "Zara" /> <property name = "age" value = "11"/> </bean> <!-- Definition for logging aspect --> <bean id = "logging" class = "com.tutorialspoint.Logging"/> </beans>
运行项目
完成创建源文件和配置文件后,运行您的应用程序。右键单击应用程序中的MainApp.java并使用作为Java应用程序命令运行。如果你的应用程序一切正常,它将打印下面的消息。
Going to setup student profile. Name : Zara Age : 11