准备工作
- 需要jdk5.0及以上。
- 引入所需jar包,在03节导入的jar包,使用注解操作aop时会出错,故新上传一份jar包文件,可在文章末尾进行下载。
- 需要在配置文件中勾选aop、context命名空间(若果没有在本地配置,则需要联网)。
关于@AspectJ
- 这是一个面向切面的框架,可以是aop使用更加便捷、灵活。
- 与xml文件方式不同的是需要添加一个切入点函数(返回值为void,函数体为空)。
@Aspect包含的注解
- @Aspect:用于定义一个切面。
- @Pointcut:用于定义一个切入点。
- @Before:用于定义一个前置通知。通常需要一个value属性,用于指定一个切入点表达式。
- @AfterReturning:用于定义一个后置通知。 有pointcut、value、returning三个属性,pointcut和value属性都用于指定切入点表达式,returning属性可用于访问目标方法的返回值,属性值与通知方法中的形参名一致。
- @AfterThrowing:用于定义一个异常通知。有pointcut、value、throwing三个属性,pointcut和value属性都用于指定切入点表达式,throwing属性用于访问目标方法抛出的异常,该属性值与异常通知方法中的参数一致。
- @Around:用于一个环绕通知。有一个value属性,用于指定该通知被植入的切入点。
- @After:用于定义最终final通知,不管是否异常,该通知都会执行。使用时需要指定一个value属性,用于指定该通知被植入的切入点
核心代码
package com.sunqg.service.imp;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import com.sunqg.service.ProductService;
@Component("productService")
public class ProductServiceImp implements ProductService {
@Override
public void browseBefore(String loginName, String ProductName) {
System.out.print("执行业务方法 前置通知");
}
@Override
public void browseThrow(String loginName, String productName) {
System.out.print("模拟用户浏览 异常通知");
throw new RuntimeException("特定的异常通知");
}
@Override
public void browseAround(String loginName, String productName) {
System.out.print("模拟用户浏览 环绕通知");
int i = 100000;
while(i>0)
i--;
}
@Override
public void browseAfter(String loginName, String productName) {
System.out.print("模拟用户浏览 返回通知");
}
}
package com.sunqg.aop;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
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 org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Aspect
@Component("allLogAdvice")
public class AllLogAdvice {
@Pointcut("execution(* com.sunqg.service.imp.ProductServiceImp.*(..))")
private void allMethod(){}
@Before("allMethod()")
public void BeforeAdvice(JoinPoint joinPoint){
List<Object> args = Arrays.asList(joinPoint.getArgs());
String logInfoText = "\n前置通知:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())
+args.get(1).toString() + "浏览商品" + args.get(1).toString();
System.out.print(logInfoText);
}
@AfterReturning("allMethod()")
public void AfterAdvice(JoinPoint joinPoint){
List <Object> args = Arrays.asList(joinPoint.getArgs());
String logInfoText = "\n返回通知:" + new SimpleDateFormat("yyy-MM-dd HH:mm:ss").format(new Date())
+ args.get(1).toString();
System.out.print(logInfoText);
}
@AfterThrowing(pointcut="allMethod()", throwing="e")
public void ThrowAdvice(JoinPoint joinPoint,Exception e){
String targetClassName = joinPoint.getTarget().getClass().getName();
String targetMethodName = joinPoint.getSignature().getName();
String logInfoText = "\n异常通知:执行" + targetClassName + "类的" + targetMethodName + "方法时出现异常";
System.out.println(logInfoText);
}
@Around("allMethod()")
public void AroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable{
long beginTime = System.currentTimeMillis();
joinPoint.proceed();
long endTime = System.currentTimeMillis();
String targetMethodName = joinPoint.getSignature().getName();
String logInfoText = "\n环绕通知:" + targetMethodName + "方法调用前的时间为" + beginTime + "毫秒," + "调用后的时间为:"
+ endTime + "毫秒";
System.out.print(logInfoText);
}
}
package com.sunqg.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.sunqg.service.ProductService;
import com.sunqg.service.UserService;
public class TestLogin {
@Test
public void main(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
ProductService productService = (ProductService) ctx.getBean("productService");
productService.browse("sunqg", "框架技术精讲与案例整合");
}
}
<?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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
<!-- 配置自动扫描的包 -->
<context:component-scan base-package="com.sunqg"></context:component-scan>
<!-- 开启基于@AspectJ切面的注解处理器 -->
<aop:aspectj-autoproxy/>
</beans>
aop注解所需的jar包