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>
        <!-- pointcut 切点,使用excution表达式描述切面的作用范围-->
        <!-- execution(public * com.imooc..*.*(..))表达式说明切面作用在com.imooc包下的所有类的所有方法上 -->
        <aop:pointcut id="pointcut" expression="execution(public * com.imooc..*Service.*(..))"/>
        <aop:aspect ref="methodAspect">
            <!-- before 通知,代表在目标方法之前运行methodAspect.printExecutionTime-->
            <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>

利用AOP 进行方法性能筛查

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.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="methodAspect" class="com.imooc.spring.aop.aspect.MethodAspect"></bean>
    <aop:config>
        &lt;!&ndash; pointcut 切点,使用excution表达式描述切面的作用范围&ndash;&gt;
        &lt;!&ndash; execution(public * com.imooc..*.*(..))表达式说明切面作用在com.imooc包下的所有类的所有方法上 &ndash;&gt;
        <aop:pointcut id="pointcut" expression="execution(public * com.imooc..*Service.*(..))"/>
        <aop:aspect ref="methodAspect">
            &lt;!&ndash; before 通知,代表在目标方法之前运行methodAspect.printExecutionTime&ndash;&gt;
            <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>-->
    <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>

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

基于注解开发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();
    }
public interface EmployeeService {
    public void createNewEmployee();
}

public class EmployeeServiceImpl implements EmployeeService{
    public void say() {
        System.out.println("hello");
    }
}

CGLib

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

知虚

权当做笔记,打赏随您心意

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值