SpringAop 2.x
简介:
基于命名空间的配置,原理是使用后处理器,更简单。
特点:
简化配置,
非侵入性编写通知时不需要实现任何接口。
使用AspectJ表达式定义切点。
基本用法:
配置advice
定义增强类,不需要实现任何接口,但有多种写法。
配置PointCut并织入
AspectJ表达式
简介:切点表达式,一种表达式,用来定义切点位置。
用法:
within 语法:within(包名.类名) 匹配该类中的所有方法。
execution
匹配特定包中的特定类中特定返回值类型的特定参数的特定方法。
语法:execution(表达式)
表达式:返回值类型 包名.类名.方法名(参数类型)
通配符:*和…
…表示参数任意。
配置方式:
基本用法: 添加jar包
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!--ioc01-core-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
<!--ioc01-bean-->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<!--ioc01-context-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<!--ioc01-expression-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
</dependency>
<!--Aop依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
<!--cglib技术-->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
</dependency>
书写接口UserService
package springaop07.service;
/**
* package_name:springaop01.service
*
* author:徐亚远 Date:2020/2/18 18:29
* 项目名:springDemo01
* Description:
**/
public interface UserService {
/**
* @Author : 徐亚远
* @Date : 2020/2/18 20:34
* @param username
* @param password
* @Description :
*/
void login(String username, String password);
}
书写接口的实现类UserServiceImpl
package springaop07.service.impl;
import springaop07.service.UserService;
/**
* package_name:springaop01.service.impl
* Author:徐亚远
* Date:2020/2/18 18:29
* 项目名:springDemo01
* Desription:
**/
public class UserServlceImpl implements UserService {
/**
* @param password
* @param username
* @Author : 徐亚远
* @Date : 2020/2/18 21:03
* @Description :
*/
@Override
public void login(String username, String password) {
System.out.println("loginUserServiceImpl登录方法执行:" + username + " " + password);
//异常通知时取消注释
//int i = 10/0;
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
书写通知类
package springaop07.advice;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.reflect.MethodSignature;
import java.lang.reflect.Method;
import java.util.Arrays;
/**
* package_name:springaop07.advice
*
* @author:徐亚远 Date:2020/2/20 14:06
* 项目名:springDemo01
* Description:TODO
* Version: 1.0
**/
public class UserAdvice {
private Long time;
public Long getTime() {
return time;
}
public void setTime(Long time) {
this.time = time;
}
//配置前置通知方法
public void log(JoinPoint joinPoint){
//签名
Signature signature = joinPoint.getSignature();
//方法名
String methodName = signature.getName();
//转换为方法签名,本质上是方法签名
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
//参数
Object [] args = joinPoint.getArgs();
//目标类
Object target = joinPoint.getThis();
System.out.println("前置通知: "+"methodName: "+methodName+" "+"args:"+Arrays.toString(args) +" "+"target: "+target);
}
//配置后置通知方法
public void afterLog(JoinPoint joinPoint,Object value){
//签名
Signature signature = joinPoint.getSignature();
//方法名
String methodName = signature.getName();
//转换为方法签名,本质上是方法签名
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
//参数
Object [] args = joinPoint.getArgs();
//目标类
Object target = joinPoint.getThis();
System.out.println("后置通知: "+"methodName: "+methodName+" "+"args:"+Arrays.toString(args) +" "+"target: "+target);
}
public void throwLog(JoinPoint joinPoint,Exception ex){
//签名
Signature signature = joinPoint.getSignature();
//方法名
String methodName = signature.getName();
//转换为方法签名,本质上是方法签名
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
//参数
Object [] args = joinPoint.getArgs();
//目标类
Object target = joinPoint.getThis();
System.out.println("异置通知: "+"methodName: "+methodName+" "+"args:"+Arrays.toString(args) +" "+"target: "+target);
}
public Object aroundLog(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("方法执行前");
Long startTime = System.currentTimeMillis();
Object proceed = joinPoint.proceed();
Long endTime = System.currentTimeMillis();
if (endTime-startTime > time){
System.out.println("给管理员人发送短息:登录时间过长请优化");
}else {
System.out.println("方法执行后花费["+(endTime-startTime)+"]"+"ms");
}
return proceed;
}
}
配置spring.xml配置文件
当实现某个通知时把该通知的注解取消,在下面的配置文件中
注意异常通知时在UserServiceImpl类中取消//int i = 10/0;这个注解
<?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">
<!--springAop 2.x配置-->
<!--配置目标类实例-->
<bean id="userService" class="springaop07.service.impl.UserServlceImpl"/>
<!--配置advice通知-->
<bean id="userAdvice" class="springaop07.advice.UserAdvice">
<property name="time" value="3000"/>
</bean>
<!--配置切入点并织入 引入 <aop:config>命名空间-->
<aop:config>
<!--配置切入点-->
<aop:pointcut id="us" expression="within(springaop07.service.impl.UserServlceImpl)"/>
<!--织入配置通知-->
<aop:aspect ref="userAdvice">
<!--前置通知 将userAdvice类中的log方法织入到us对应的切入点-->
<!--<aop:before method="log" pointcut-ref="us"/>-->
<!--后置通知 将userAdvice类中的afterLog方法织入到us对应的切入点-->
<!--<aop:after-returning method="afterLog" pointcut-ref="us" returning="value"/>-->
<!--异置通知 将userAdvice类中的afterLog方法织入到us对应的切入点-->
<!--<aop:after-throwing method="throwLog" pointcut-ref="us" throwing="ex"/>-->
<!--环绕通知 将userAdvice类中的afterLog方法织入到us对应的切入点-->
<aop:around method="aroundLog" pointcut-ref="us"/>
</aop:aspect>
</aop:config>
</beans>
环绕通知的结果如图:
前置通知的结果如图:
后置通知结果如图:
异常通知结果如图: