• Spring——AOP


    Spring中的可插拔组件技术

    在这里插入图片描述

    Spring AOP

    • Spring AOP——Aspect Oriented Programming 面向切面编程
    • AOP 的做法是将通用的、与业务无关的功能抽象封装为切面层
    • 切面可配置在目标方法执行前后,做到即插即用

    不修改源码对程序功能进行拓展

    AoP的关键概念

    Spring AoP 与AspectJ的关系

    • Eclipse AspectJ,一种基于Java平台的面向切面编程的语言
    • Spring AoP 使用AspectJWeaver 实现 类与方法匹配
    • Spring AOP 利用代理模式实现对象运行时功能拓展

    几个重要概念
    在这里插入图片描述

    AOP配置过程

    1. 依赖AaspectJ
    2. 实现切面类和方法
    3. 配置Aspect Bean
    4. 定义PointCut
    5. 配置Aadvice

    JoinPoint核心方法

    注解说明
    Object getTarget()获取IoC容器内目标对象
    Signature getSignature()获取目标方法
    Object[] getArgs()获取目标方法参数

    PointCut 切点表达式

    在这里插入图片描述

    五种通知类型

    在这里插入图片描述
    xml配置如下:

     <aop:config>
            
            
            <aop:pointcut id="pointcut" expression="execution(public * com.imooc..*Service.*(..))"/>
            <aop:aspect ref="methodAspect">
                
                <aop:before method="printExecutionTime" pointcut-ref="pointcut"/>
    
                <aop:after-returning method="doAfterReturning" returning="ret" pointcut-ref="pointcut"/>
                <aop:after method="doAfter" pointcut-ref="pointcut"/>
                <aop:after-throwing method="doAfterThrowing" throwing="exception" pointcut-ref="pointcut"/>
            aop:aspect>
        aop:config>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    利用AOP 进行方法性能筛查

    applicationContext.xml:

    
    <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.imooc.spring.aop.dao.UserDao"/>
        <bean id="employeeDao" class="com.imooc.spring.aop.dao.EmployeeDao"/>
        <bean id="userService" class="com.imooc.spring.aop.service.UserService">
            <property name="userDao" ref="userDao"/>
        bean>
        <bean id="employeeService" class="com.imooc.spring.aop.service.EmployeeService">
            <property name="employeeDao" ref="employeeDao"/>
        bean>
    
        
        <bean id="methodChecker" class="com.imooc.spring.aop.aspect.MethodChecker"/>
        <aop:config>
            <aop:pointcut id="pointcut" expression="execution(* com.imooc..*.*(..))"/>
    
            <aop:aspect ref="methodChecker">
                <aop:around method="check" pointcut-ref="pointcut"/>
            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
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    methodChecker:

    package com.imooc.spring.aop.aspect;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    /**
     * todo {类简要说明}
     *
     * @Author wangw
     * @Date 2022/12/1 22:59
     * @Version 1.0
     */
    public class MethodChecker {
        // proceedingJoinPoint是原有JoinPoint的升级,在原有功能基础上,还能控制目标方法是否执行
        public Object check(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
            try {
                long startTime = System.currentTimeMillis();
               Object ret =  proceedingJoinPoint.proceed();
               long endTime = System.currentTimeMillis();
               long duration =endTime-startTime;
               if (duration>=1000){
                   SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:MM:ss SSS");
                   String className = proceedingJoinPoint.getTarget().getClass().getName();
                   String methodName =proceedingJoinPoint.getSignature().getName();
                   Object[] args =proceedingJoinPoint.getArgs();
                   String now = sdf.format(new Date());
                   System.out.println("======"+now+":"+className+"."+methodName+"."+"("+duration+")ms==============");
               }
               return ret;
            } catch (Throwable e) {
                throw e;
            }
        }
    }
    
    
    • 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

    基于注解开发SpringAOP

    在这里插入图片描述
    在这里插入图片描述

    Spring AOP 实现原理

    • Spring 基于代理模式实现动态功能拓展,包含两种形式
    • 目标类拥有接口,通过JDK动态代理实现功能拓展
    • 目标类没有接口,通过CGLib实现功能拓展

    代理模式

    • 代理模式通过代理对象对原对象实现功能拓展

    在这里插入图片描述

    (静态代理 是指必须手动创建按代理类的代理模式使用方式)

    JDK动态代理

        private Object targetObj;
        public ProxyInvocationHandle(Object targetObj){
            this.targetObj =targetObj;
        }
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("前置执行方法");
            Object ret = method.invoke(targetObj,args);
            System.out.println("后置方法");
            return ret;
        }
    
        public static void main(String[] args) {
            UserService userService  = new UserServiceImpl();
            ProxyInvocationHandle proxyInvocationHandle = new ProxyInvocationHandle(userService);
            UserService userServiceProxy = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(),userService.getClass().getInterfaces(),proxyInvocationHandle);
            userServiceProxy.createUser();
            EmployeeService employeeService =new EmployeeServiceImpl();
            ProxyInvocationHandle proxyInvocationHandleProxy = new ProxyInvocationHandle(employeeService);
            EmployeeService employeeServiceProxy = (EmployeeService) Proxy.newProxyInstance(employeeService.getClass().getClassLoader(),employeeService.getClass().getInterfaces(),proxyInvocationHandleProxy);
            employeeServiceProxy.say();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    public interface EmployeeService {
        public void createNewEmployee();
    }
    
    
    • 1
    • 2
    • 3
    • 4
    public class EmployeeServiceImpl implements EmployeeService{
        public void say() {
            System.out.println("hello");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    CGLib

    使用代理时如果没有接口,则使用CGLib
    在这里插入图片描述

    AOP 底层就是使用动态代理实现的!!!

  • 相关阅读:
    # Vue3 setup 函数
    supervisorctl
    Python的输入输出(来自菜鸟教程)
    100天精通Python(基础篇)——第21天:if elif嵌套
    微信小程序有的机型无法播放m3u8格式的直播流,使用H5在微信环境里播放
    西部学刊杂志西部学刊杂志社西部学刊编辑部2022年第22期目录
    ESLint自动修复代码规范错误
    项目沟通和干系人管理
    selinux-policy-default(2:2.20231119-2)软件包内容详细介绍(1)
    GIT教程
  • 原文地址:https://blog.csdn.net/HBUT_WANGWEI/article/details/128123580