只是为了自己更容易记住,理解相关内容,所以写了一篇简单的文章,主要还是参考前辈的大作完成。
上一篇文章对Spring的Aop 进行了初步的介绍,对Spring的Aop 有一个初步的概念。
其实Spring Aop 就是一个切面,以前我们需要对某个函数的某个方法设置前置方法及后置方法的时候,我们都需要在该对应的方法出进行调用,或者在调用该方法之前进行调用,都需要对系统代码进行更新, 而Spring Aop 则 提供了另外一种更好的方式去处理。
上一篇只是介绍了Spring的Aop 的最初级内容,现在对Spring Aop 的几种主要的内置方法进行介绍。
1. 创建一个maven 工程,引入上一篇中的文件,pom文件主要内容如下:
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
</dependencies>
引入后,需要进行maven update,引入相应的jar文件,以便后续使用。
2. 创建一个bo接口文件,CustomerBo:
package com.tanj.test.bo;
public interface CustomerBo {
void addCustomer();
String addCustomerReturnValue();
void addCustomerThrowException() throws Exception;
void addCustomerAround(String name);
}
3. 创建bo接口对应的实现类CustomerBoImpl:
package com.tanj.test.bo;
public class CustomerBoImpl implements CustomerBo {
@Override
public void addCustomer() {
System.out.println("addCustomer() is running ");
}
@Override
public String addCustomerReturnValue() {
System.out.println("addCustomerReturnValue() is running ");
return " addCustomerReturnValue return result!";
}
@Override
public void addCustomerThrowException() throws Exception {
System.out.println("addCustomerThrowException() is running ");
throw new Exception(" addCustomerThrowException Throws ");
}
@Override
public void addCustomerAround(String name) {
System.out.println("addCustomerAround() is running . name is :[" +name+ "]");
}
}
4. 创建一个切面类LoggingAspect:
package com.tanj.test.aspect;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import java.util.Arrays;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
//@Aspect
public class LoggingAspect {
@Before("execution(* com.tanj.test.bo.CustomerBo.addCustomer(..))")
public void logBefore(JoinPoint joinpoint) {
System.out.println("******begin******");
System.out.println("JoinPoint logBefore() is running!");
System.out.println("Running Function Name: " + joinpoint.getSignature().getName());
System.out.println("******end******");
}
@After("execution(* com.tanj.test.bo.CustomerBo.addCustomer(..))")
public void logAfter(JoinPoint joinpoint) {
System.out.println("******begin******");
System.out.println("JoinPoint logAfter() is running!");
System.out.println("Running Function Name: " + joinpoint.getSignature().getName());
System.out.println("******end******");
}
@AfterReturning(
pointcut = "execution(* com.tanj.test.bo.CustomerBo.addCustomerReturnValue(..))",
returning= "result")
public void logAfterReturning(JoinPoint joinpoint, Object result) {
System.out.println("******begin******");
System.out.println("logAfterReturning() is running!");
System.out.println("Running Function Name : " + joinpoint.getSignature().getName());
System.out.println("Method returned value is : " + result);
System.out.println("******end******");
}
@AfterThrowing(
pointcut = "execution(* com.tanj.test.bo.CustomerBo.addCustomerThrowException(..))",
throwing= "error")
public void logAfterThrowing(JoinPoint joinpoint, Throwable error) {
System.out.println("******begin******");
System.out.println("logAfterThrowing() is running!");
System.out.println("Running Function Name : " + joinpoint.getSignature().getName());
System.out.println("Exception : " + error);
System.out.println("******end******");
}
@Around("execution(* com.tanj.test.bo.CustomerBo.addCustomerAround(..))")
public void logAround(ProceedingJoinPoint joinpoint) throws Throwable {
System.out.println("******begin******");
System.out.println("logAround() is running!");
System.out.println("joinpoint method : " + joinpoint.getSignature().getName());
System.out.println("joinpoint arguments : " + Arrays.toString(joinpoint.getArgs()));
System.out.println("Around before is running!");
joinpoint.proceed(); //continue on the intercepted method
System.out.println("Around after is running!");
System.out.println("******end******");
}
}
5. 创建Spring的配置文件,放在src/main/resources目录下:
<?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 />
<bean id="customerBo" class="com.tanj.test.bo.CustomerBoImpl" />
<!-- Aspect -->
<bean id="logAspect" class="com.tanj.test.aspect.LoggingAspect" />
</beans>
6. 创建一个测试类MainTest:
package com.tanj.test.main;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.tanj.test.bo.CustomerBo;
public class MainTest {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
MainTest test = new MainTest();
//test.TestBeforeFunction(context);
//test.TestAfterFunction(context);
//test.TestAfterReturnFunction(context);
//test.TestThrowExceptionFunction(context);
//test.TestAroundFunction(context);
}
private void TestBeforeFunction(ClassPathXmlApplicationContext context){
CustomerBo customer = (CustomerBo)context.getBean("customerBo");
customer.addCustomer();
}
private void TestAfterFunction(ClassPathXmlApplicationContext context){
CustomerBo customer = (CustomerBo)context.getBean("customerBo");
customer.addCustomer();
}
private void TestAfterReturnFunction(ClassPathXmlApplicationContext context){
CustomerBo customer = (CustomerBo)context.getBean("customerBo");
customer.addCustomerReturnValue();
}
private void TestThrowExceptionFunction(ClassPathXmlApplicationContext context){
CustomerBo customer = (CustomerBo)context.getBean("customerBo");
try {
customer.addCustomerThrowException();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void TestAroundFunction(ClassPathXmlApplicationContext context){
CustomerBo customer = (CustomerBo)context.getBean("customerBo");
customer.addCustomerAround("Your Name!");
}
}
至此所有代码已经完成,开始测试:
1. Main 方法中都注释了,需要运行哪个文件,就放开注释。
2. 由于没有将测试方法定义为 static ,所以将Spring的ClassPathXmlApplicationContext 作为参数传递到方法中使用。
3. 第一次测试的时候,会发现Spring的Aspect 没有起作用,为什么呢?
注意看类LoggingAspect 定义的上一行代码 注解 @Aspect 被我注释掉了,导致Spring 在扫描这个包的时候,没有找到对应的@Aspect,所以运行的结果和普通的类运行的结果相同,并没有出现切面类中的内容。去掉这一行注释,再次运行,就会发现切面类的信息已经出现。
4. 注意,由于before 和 after 同时定义了,因此在掉用before 和 after 方法的时候,会同时调用,如果只需要测试一个切入点,可以注释掉另外一个切入点。
欢迎拍砖。
主要参考了这篇文章完成:
http://www.yiibai.com/spring/spring-aop-aspectj-annotation-example.html 顺便拍砖,这个里面的内容,部分代码内容变化了,会出现一点小小的引入包问题。