首页 > 其他分享 >【Spring AOP】SpringAOP配置过程——基于XML&&基于注解 && Spring AOP实现原理

【Spring AOP】SpringAOP配置过程——基于XML&&基于注解 && Spring AOP实现原理

时间:2024-03-01 21:12:10浏览次数:22  
标签:Spring new 切面 && AOP import pjp

概念

  • Spring AOP - Aspect Oriented Programming 面向切面编程
  • AOP的做法是将通用与业务无关的功能抽象封装为切面类
  • 切面可配置在目标方法的执行前、后运行,真正做到即插即用
  • 可以在不修改源码的情况下对程序进行扩展

AOP配置过程——基于XML配置

0. 添加依赖创建配置文件

添加依赖-aspectjweaver

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.2.25.RELEASE</version>
    </dependency>

    <!--Spring AOP的底层依赖-->
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.9.6</version>
    </dependency>

SpringAOP和AspectJ的关系

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

创建配置文件: 新增context和aop的xmlns

<?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"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    
</beans>

具体的schema可以在spring官网找到,步骤如下:







几个关键概念

1. 实现切面类/方法

  • Aspect,切面,具体的可插拔组件功能类,通常一个切面只实现一个通用功能
  • Target Class/Method:目标类、目标方法,指真正要执行与业务相关的方法

JoinPoint

  • 连接点,切面运行过程中包含了目标类/方法元数据的对象

2. 配置Aspect Bean

3. 定义PointCut

  • PointCut,切入点,使用execution表达式说明切面要作用在系统的哪些类上
  • 使用execution表达式描述切面的作用范围

4. 配置Advice通知

  • Advice,通知,说明具体切面的执行时机,Spring包含了五种不同类型的通知

Around Advice环绕通知

  1. 实现切面类/方法
    ProceedingJoinPoint是JoinPoint的升级版,在原有功能外,还可以控制目标方法是否执行,需要强制返回目标方法返回值
package com.EveX.spring.aop.aspect;

import org.aspectj.lang.ProceedingJoinPoint;

import java.text.SimpleDateFormat;
import java.util.Date;

/*检查程序运行时间的切面类*/
public class MethodChecker {
    public Object check(ProceedingJoinPoint pjp) throws Throwable {
        try {
            long stime = new Date().getTime();  //开始执行时间
            Object ret = pjp.proceed();// 执行目标方法
            long etime = new Date().getTime();  //结束执行时间
            long duration = etime - stime;  //程序执行时长
            if(duration > 1000) {
                String className = pjp.getTarget().getClass().getName();  //获取目标对象的类名
                String methodName = pjp.getSignature().getName();  //获取目标方法名
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss SS");
                String now = dateFormat.format(new Date());
                System.out.println("=====>" + now + ":" + className + "." + methodName + "(" + duration + "ms)<=====");
            }
            return ret;
        } catch (Throwable e) {
            System.out.println("Exception message:" + e.getMessage());
            throw e;
        }

    }
}
  1. 配置Aspect Bean
<bean id="methodChecker" class="com.EveX.spring.aop.aspect.MethodChecker"></bean>
  1. 定义PointCut
  2. 配置Advice通知
    <aop:config>
        <!--定义切入点-->
        <aop:pointcut id="pointcut" expression="execution(* com.EveX..*.*(..))"/>
        <!--定义切面-->
        <aop:aspect ref="methodChecker">
            <!--配置around advice通知-->
            <aop:around method="check" pointcut-ref="pointcut"></aop:around>
        </aop:aspect>
    </aop:config>

AOP配置过程——基于注解配置

  1. 开启context包扫描初始化Ioc容器+启动Spring AOP注解模式
<?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"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    
    <!--初始化IoC容器-->
    <context:component-scan base-package="com.EveX"></context:component-scan>
    <!--启动Spring AOP注解模式-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
  1. 在切面类中添加注解
package com.EveX.spring.aop.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.Date;

/*检查程序运行时间的切面类*/
@Component
@Aspect // 标记当前类是一个切面类
public class MethodChecker {
    /*环绕通知,参数为execution表达式*/
    @Around("execution(* com.EveX..*.*(..))")
    public Object check(ProceedingJoinPoint pjp) throws Throwable {
        try {
            long stime = new Date().getTime();  //开始执行时间
            Object ret = pjp.proceed();// 执行目标方法
            long etime = new Date().getTime();  //结束执行时间
            long duration = etime - stime;  //程序执行时长
            if(duration > 1000) {
                String className = pjp.getTarget().getClass().getName();  //获取目标对象的类名
                String methodName = pjp.getSignature().getName();  //获取目标方法名
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss SS");
                String now = dateFormat.format(new Date());
                System.out.println("=====>" + now + ":" + className + "." + methodName + "(" + duration + "ms)<=====");
            }
            return ret;
        } catch (Throwable e) {
            System.out.println("Exception message:" + e.getMessage());
            throw e;
        }

    }
}

Spring AOP实现原理

Spring 基于代理模式实现功能动态扩展,包含两种形式:

  1. 目标类拥有接口,通过JDK动态代理实现功能扩展
  2. 目标类没有接口,通过CGLib组件通过继承的方式实现功能扩展

CGLib实现代理类:

  • CGLib是运行时字节码增强技术
  • AOP会在运行时生成目标继承类字节码的方式进行行为扩展

标签:Spring,new,切面,&&,AOP,import,pjp
From: https://www.cnblogs.com/Eve7Xu/p/18040710

相关文章

  • Spring-Boot学习
    Spring-boot学习笔记从零开始创建项目先创建一个空的Maven项目,然后在pom.xml引入Spring-boot-starter的父依赖<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.2......
  • SpringCloud Alibaba-4-Feign远程调用
    远程调用:在分布式系统中,我们使用springboot创建了各种各样服务,那么这些服务之间如何进行远程调用呢。如:订单微服务怎么去调用商品微服务?Ribbon:是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法和服务调用。Ribbon支持的负载均衡策略:BestAvailableRuleAvai......
  • 在 Spring Boot 3.x 中使用 SpringDoc 2 / Swagger V3
    SpringDocV1只支持到SpringBoot2.xspringdoc-openapiv1.7.0isthelatestOpenSourcereleasesupportingSpringBoot2.xand1.x.SpringBoot3.x要用SpringDoc2/SwaggerV3,并且包名也改成了springdoc-openapi-starter-webmvc-uiSpringDocV2https://spr......
  • spring cloud gateway使用 uri: lb://方式配置时,服务名的特殊要求
    在gateway中配置uri配置有三种方式,包括第一种:ws(websocket)方式:uri:ws://localhost:9000第二种:http方式:uri:http://localhost:8130/第三种:lb(注册中心中服务名字)方式:uri:lb://brilliance-consumer  其中ws和http方式不容易出错,因为http格式比较固定,但是lb方式比......
  • SpringBoot定时任务:使用shedlock解决SpringBoot分布式定时任务
    第一步:引入shedlock包maven中pom文件添加如下配置:<dependency><groupId>net.javacrumbs.shedlock</groupId><artifactId>shedlock-spring</artifactId><version>4.33.0</version>使用其他版本</dependency>第二步:添加shedlock-p......
  • Spring Boot + liteflow 规则引擎,太香了!
    作者:豫州牧链接:https://juejin.cn/post/72967717700987453441、前言在日常的开发过程中,经常会遇到一些串行或者并行的业务流程问题,而业务之间不必存在相关性。在这样的场景下,使用策略和模板模式的结合可以很好的解决这个问题,但是使用编码的方式会使得文件太多,在业务的部分环......
  • Spring @Configuration 和 @Component 区别
    Spring@Configuration和@Component区别一句话概括就是@Configuration中所有带@Bean注解的方法都会被动态代理,因此调用该方法返回的都是同一个实例。 @Configuration注解:@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Componentpublic@......
  • springboot应用中根据特定条件使用CommandLineRunner
    PS使用SpringBoot3.1.2进行测试1.使用@ConditionalOnProperty仅当特定属性存在或具有特定值时,注释@ConditionalOnProperty才会创建bean。在此示例中,仅当或文件中的CommandLineRunner属性db.init.enabled设置为true时才会执行application.propertiesapplication.ymlpac......
  • Spring Boot学习日记17
    尝试整合JDBC spring:datasource:username:rootpassword:123456url:jdbc:mysql://localhost:3306/mybatis?useSSL=true&userUniceode=true&characterEncoding=utf8driver-class-name:com.mysql.cj.jdbc.Driverpackagecom.example.spri......
  • Spring Boot学习日记9
    在springboot项目中的resources目录下新建一个文件application.yml编写一个实体类Dog;packagecom.example.springboot02configure.pojo;importorg.springframework.beans.factory.annotation.Value;importorg.springframework.stereotype.Component;@Component//添加......