# 5环绕通知

回到spring AOP导航页

  • 环绕通知可以完成:前置通知、返回后通知、异常通知、后置通知的所有工作,实际项目中会经常用到

利用真实案例来讲解环绕通知的使用方法,常见如下:
在实际项目中,由于不断的数据累积,用户量的增大,可能会导致生产环境中系统越来越慢,那我们如何该定位到是 哪一个方法 执行慢呢?看似简单,但实际并不轻松,因为一个大型系统,类和方法成千上万,难道我们要为每一个方法都去增加响应的代码,去捕捉他们的执行时间吗?这样做的效率实在是太差了。
这时候就想做使用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

运行结果如下:

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

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
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

# 导航,上一页,下一页

4AOP通知
6利用注解配置Spring AOP

# 支持我-微信扫一扫-加入微信公众号

Aseven公众号

# 赞赏作者

赞赏作者

# 种一棵树,最好的时间是十年前,其次是现在

立志用功,如种树然。方其根芽,犹未有干;及其有干,尚未有枝;枝而后叶,叶而后花、实。初种根时,只管栽培灌溉,勿作枝想,勿作实想。悬想何益?何不忘栽培之功,怕没有枝叶花实?