# 5环绕通知
- 环绕通知可以完成:前置通知、返回后通知、异常通知、后置通知的所有工作,实际项目中会经常用到
利用真实案例来讲解环绕通知的使用方法,常见如下:
在实际项目中,由于不断的数据累积,用户量的增大,可能会导致生产环境中系统越来越慢,那我们如何该定位到是 哪一个方法 执行慢呢?看似简单,但实际并不轻松,因为一个大型系统,类和方法成千上万,难道我们要为每一个方法都去增加响应的代码,去捕捉他们的执行时间吗?这样做的效率实在是太差了。
这时候就想做使用Spring AOP,在方法运行前,保存一个时间,方法运行后,保存一个时间,单个通知是很难做到的,Spring为我们提供了一个功能最强大的选择环绕通知,利用环绕通知我们可以控制目标方法完整的运行周期
# 利用AOP环绕通知进行方法性能筛选
package com.torey.spring.aop.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
/**
* @Author http://torey611.gitee.io/li-tao-feng/
* @Email torey6061@qq.com
* @Date 2021/5/2 10:12
* @描述: 演示环绕通知的用法;在实际项目中,
* 由于不断的数据累积,用户量的增大,可能会导致生产环境中系统越来越慢,那我们如何该定位到是 哪一个方法 执行慢呢?看似简单,但实际并不轻松,因为一个大型系统,类和方法成千上万,难道我们要为每一个方法都去增加响应的代码,去捕捉他们的执行时间吗?这样做的效率实在是太差了。
* 这时候就想做使用Spring AOP,在方法运行前,保存一个时间,方法运行后,保存一个时间,单个通知是很难做到的,Spring为我们提供了一个功能最强大的选择**环绕通知**,利用环绕通知我们可以控制目标方法完整的运行周期
*/
public class MethodChecked {
//ProceedingJoinPoint是JoinPoint的升级版,除了原有的功能,还可以控制目标方法是否执行
//环绕通知可以完成:前置通知、返回后通知、异常通知、后置通知的所有工作,实际项目中会经常用到
public Object check(ProceedingJoinPoint pjp) throws Throwable {
try {
System.out.println(this.getClass().getName() + "check();环绕通知,方法开始"+this.hashCode());
long stateTime = System.currentTimeMillis();
//执行目标方法,如果proceed()方法不写,则目标方法不会执行
//返回值为:目标方法的返回值
Object ret = pjp.proceed();
long endTime = System.currentTimeMillis();
long yongShi=endTime - stateTime;
System.out.println("方法执行时间为:" + endTime + "-" + stateTime + "=" + yongShi);
if(yongShi>=1000){
String className = pjp.getTarget().getClass().getName();
String methodName = pjp.getSignature().getName();
System.out.println(className+"."+methodName+"方法执行超过了1秒");
}
System.out.println(this.getClass().getName() + "check();环绕通知,方法结束"+this.hashCode());
return ret;
} catch (Throwable throwable) {
throw throwable;
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
运行结果如下:
com.torey.spring.aop.aspect.MethodCheckedcheck();环绕通知,方法开始1577592551
com.torey.spring.aop.service.UserService.createUser();执行创建用户业务逻辑
com.torey.spring.aop.aspect.MethodCheckedcheck();环绕通知,方法开始1577592551
com.torey.spring.aop.dao.UserDao.insert();新增数据
方法执行时间为:1619925450648-1619925449636=1012
com.torey.spring.aop.dao.UserDao.insert方法执行超过了1秒
com.torey.spring.aop.aspect.MethodCheckedcheck();环绕通知,方法结束1577592551
方法执行时间为:1619925450650-1619925449610=1040
com.torey.spring.aop.service.UserService.createUser方法执行超过了1秒
com.torey.spring.aop.aspect.MethodCheckedcheck();环绕通知,方法结束1577592551
com.torey.spring.aop.aspect.MethodCheckedcheck();环绕通知,方法开始1577592551
按类型A方式生成5位随机密码
方法执行时间为:1619925450651-1619925450651=0
com.torey.spring.aop.aspect.MethodCheckedcheck();环绕通知,方法结束1577592551
返回值为:ddsseeee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns="http://www.springframework.org/schema/beans"
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.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="userDao" class="com.torey.spring.aop.dao.UserDao"></bean>
<bean id="employeeDao" class="com.torey.spring.aop.dao.EmployeeDao"></bean>
<bean id="userService" class="com.torey.spring.aop.service.UserService">
<property name="userDao" ref="userDao"></property>
</bean>
<bean id="employeeService" class="com.torey.spring.aop.service.EmployeeService">
<property name="employeeDao" ref="employeeDao"></property>
</bean>
<!--AOP配置-->
<bean id="methodChecked" class="com.torey.spring.aop.aspect.MethodChecked"></bean>
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* com.torey..*.*(..))"></aop:pointcut>
<aop:aspect ref="methodChecked">
<!--环绕通知-->
<aop:around method="check" pointcut-ref="pointcut" ></aop:around>
</aop:aspect>
</aop:config>
</beans>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.torey.spring.aop;
import com.torey.spring.aop.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @Author http://torey611.gitee.io/li-tao-feng/
* @Email torey6061@qq.com
* @Date 2021/5/1 15:55
* @描述:
*/
public class SpringApplication {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
UserService bean = context.getBean("userService", UserService.class);
bean.createUser();
String pas = bean.generateRandomPassWord("类型A", 5);
System.out.println("返回值为:"+ pas);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 导航,上一页,下一页
# 支持我-微信扫一扫-加入微信公众号
# 赞赏作者
# 种一棵树,最好的时间是十年前,其次是现在
立志用功,如种树然。方其根芽,犹未有干;及其有干,尚未有枝;枝而后叶,叶而后花、实。初种根时,只管栽培灌溉,勿作枝想,勿作实想。悬想何益?何不忘栽培之功,怕没有枝叶花实?