Spring中基于AOP的@AspectJ
@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
==>如有问题,请联系我:easonjim#163.com,或者下方发表评论。<==