【Spring框架四】——Spring AOP 注解实现和xml方式实现

news2024/10/6 15:29:02

系列文章目录

【Spring框架一】——Spring框架简介

【Spring框架二】——什么是Spring IOC、 什么是Spring 依赖注入

【Spring框架三】——Spirng IOC和DI的实现


Spring AOP 注解实现和xml方式实现

  • 系列文章目录
  • 前言
  • 一、什么是Spring AOP(Aspect-Oriented Programming)
    • 什么是横切关注点
  • 二、Spring AOP中的基本概念
    • Cross Cutting Concern
    • Aspect
    • Advice
    • Pointcut
    • Joinpoint
    • Weave
    • TargetObject
    • Proxy
    • Introduction
  • 三、使用xml文件的方式实现Spring AOP
    • 原spring项目的代码结构
      • pom.xml
      • UserManager类
      • UserManagerImpl
      • **Client类**
      • applicationContext.xml
      • 当前运行的结果
    • xml方式实现Spring AOP
      • 补充关于Spring AOP 切入点的表达式
      • 常用表达式示例
  • 四、通过注解的方式实现Spring AOP
  • 五、Spring对AOP的支持
    • 如何强制使用CGLIB
      • xml文件方式
      • 注解的方式
      • 通过注解方式强制使用CGLIB的示例:
    • JDK动态代理的特点
    • CGLIB动态代理的特点
    • 区别
  • 六、总结


前言

Spring AOP是Spring框架中的核心内容之一,本篇博客主要讲解的是如何使用Spring Aop通过本篇博客能够对什么是Spring AOP以及如何将Spring AOP运行到具体业务有一个清晰的步骤。本篇博客主要从两个维度实现Spring AOP 一个是使用纯xml文件方式,另一个是使用纯注解的方式实现。


一、什么是Spring AOP(Aspect-Oriented Programming)

Spring AOP是面向切面编程的技术,能够对程序进行横切关注点的处理,例如日志记录、安全控制、性能统计、事物处理等。
通过AOP一方面可以将一些与业务无关、但是对业务产生重要影响的公共行为(例如事物管理、日志记录等)从业务逻辑中分离出来,这样可以使程序的模块化程度更高、同时也便于维护和扩展。

Spring AOP通过运行时的动态代理的方式,在不修改原有代码的情况下,将切面逻辑织入到目标对象中,从而实现对目标对象的增强。主要依赖与代理模式和反射机制。

备注:如果想要了解什么是代理,可以访问博主的另外两篇博客

设计模式——代理模式

Java JDK动态代理

什么是横切关注点

corss-cutting concern:指的是一个系统中存在的、多个模块都会用到的,与核心业务逻辑无关的公共关注点。例如:日志记录、性能统计、安全控制。
在传统的面向对象编程中,这些横切关注点都会分散到各个模块中,导致代码复杂、难以维护。
而AOP的目的是将这些横切关注点从核心业务逻辑中分离出来,从而使系统更易于维护和扩展。

二、Spring AOP中的基本概念

结合具体业务的示意图:addUser为原有的具体业务的实现,现在需要在其之前之后等使用Spring AOP切入一个与原有业务无关的校验安全性。
我们通过这个业务来理解Spring AOP的概念
在这里插入图片描述

Cross Cutting Concern

横切性关注点:它是一种独立服务,在我们这个例子中它是检查安全性。它会遍布在系统的处理流程之中。

Aspect

切面: 对横切性关注点的模块化,图中为SecurityHandler

Advice

通知:对横切性关注点的具体实现,常见的通知类型有(Before、After、AfterReturning、AfterThrowing、Around)

Pointcut

切点:它定义了Advice应用到那些JoinPoint上,对Spring来说是方法调用
Spring只支持方法的JoinPoint,但是对于AspectJ这个点也可以是属性修改,如。

Joinpoint

连接点:在程序执行过程中某个特定的点,比如某方法调用的时候或者处理异常的时候。 在Spring AOP中,一个连接点 总是 代表一个方法的执行。 通过声明一个org.aspectj.lang.JoinPoint类型的参数可以使通知(Advice)的主体部分获得连接点信息。

Weave

织入:将Advice应用到TargetObject上的过程叫织入,Spring支持的是动态织入

TargetObject

目标对象:目标对象是被一个或多个切面所通知的对象。

Proxy

代理:AOP代理是在目标对应和切面之间进行通信的对象;Spring AOP默认使用JDK的动态代理,它的代理是运行时创建,也可以使用CGLIB代理

Introduction

引入:引入允许将新的接口和实现引入到现有的类中,从而为类添加额外的行为。

这些核心概念共同构成了Spring AOP的基础,通过它们可以实现对横切关注点的管理和控制,从而提供横切关注点的复用和模块化。

三、使用xml文件的方式实现Spring AOP

原spring项目的代码结构

在这里插入图片描述

pom.xml

<dependencies>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.3.8</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.8</version>
        </dependency>
    <!--spring aop -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.7</version>
        </dependency>
    </dependencies>

UserManager类

package com.wangwei.springaop.service;

public interface UserManager {

   public void addUser(String username, String password);
   
   public void delUser(int userId);
   
   public int findUserById(int userId);
   
   public void modifyUser(int userId, String username, String password);
}

UserManagerImpl

package com.wangwei.springaop.service.impl;

import com.wangwei.springaop.service.UserManager;

public class UserManagerImpl implements UserManager {

   public void addUser(String username, String password) {

      System.out.println("---------UserManagerImpl.add()--------");
   }

   public void delUser(int userId) {

      System.out.println("---------UserManagerImpl.delUser()--------");
   }

   public int findUserById(int userId) {

      System.out.println("---------UserManagerImpl.findUserById()--------");
      return userId;
   }

   public void modifyUser(int userId, String username, String password) {

      System.out.println("---------UserManagerImpl.modifyUser()--------");
   }

}

Client类

package com.wangwei.springaop.client;

import com.wangwei.springaop.service.UserManager;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Client {

   public static void main(String[] args) {
       //读取xml配置文件,申明工厂
      BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");
      //获取beanid为userManager的bean
      UserManager userManager = (UserManager)factory.getBean("userManager");
      userManager.addUser("wangwei", "123");
   }
}


applicationContext.xml

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

   <bean id="userManager" class="com.wangwei.springaop.service.impl.UserManagerImpl"/>


</beans>

当前运行的结果

在这里插入图片描述

xml方式实现Spring AOP

目前业务是需要在程序执行addUser()这个方法之前,通过Spring AOP技术切入一个检查安全性的服务。

我们的横切性关注点(Cross Cutting Concern)就是这个检查安全性的服务
现在我们将这个横切性关注点进行模块化

创建SecurityHandler类,它就代表的是Aspect,是对横切性关注点的模块化

package com.wangwei.springaop.service.impl;

public class SecurityHandler {
   private void checkSecurity() {
      System.out.println("-------checkSecurity-------");
   }
}

在XML配置文件中进行配置

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

   <bean id="userManager" class="com.wangwei.springaop.service.impl.UserManagerImpl"/>

   <bean id ="securityHandlerAspect" class="com.wangwei.springaop.service.impl.SecurityHandler"/>

<!--   配置切面通知和切点-->
   <aop:config>
      <aop:aspect ref="securityHandlerAspect">
         <aop:before method="checkSecurity" pointcut="execution(* com.wangwei.springaop.service.impl.UserManagerImpl.addUser(..))"/>
      </aop:aspect>

   </aop:config>

</beans>

上面的通知(advice)配置的为Before
切点它定义了Advice应用到那些JoinPoint上,这里是通过表达式execution定位到连接点(joinPoint)
joinPoin代表一个方法的执行,这里指的是addUser()这个方法的执行。

实现效果:
在这里插入图片描述

补充关于Spring AOP 切入点的表达式

切入点表达式有两部分组成:签名指示器

签名部分指定了要匹配的连接点的方法签名。
例如:"execution(public * com.example.service…(…))"表示匹配com.example.service包中的所有公共方法。
指示器部分用于进一步细化匹配的连接点。常见的指示器包括:

execution:匹配方法执行连接点。
within:匹配指定类型内的方法执行连接点。
args:匹配参数类型符合指定类型的方法执行连接点。
annotation:匹配带有指定注解的方法执行连接点。
以下是一些切入点表达式的示例:

  1. execution(public * com.example.service…(…)):匹配com.example.service包中的所有公共方法。
  2. within(com.example.service.*):匹配com.example.service包中所有方法。
  3. execution(* com.example.service.UserService.addUser(…)):匹配com.example.service.UserService类的addUser方法。
  4. args(String, *):匹配第一个参数为String类型的方法。
    annotation(org.springframework.transaction.annotation.Transactional):匹配带有@Transactional注解的方法。

切入点表达式的语法非常灵活,可以根据需要进行组合和定制,以精确地选择要应用切面的连接点。

常用表达式示例

一般用的是execution执行表达式的格式如下:

execution(modifiers-pattern? return-type-pattern declaring-type-pattern? method-name-pattern(param-pattern) throws-pattern?)

其中,各个部分的含义如下:

  1. modifiers-pattern(可选):用于匹配方法的修饰符,如
    public、protected等。可以使用通配符*匹配任意修饰符。
  2. return-type-pattern:用于匹配方法的返回类型,可以是具体的类型或通配符*表示任意类型。
  3. declaring-type-pattern(可选):用于匹配方法所在的类的类型,可以是具体的类型或通配符*表示任意类型。
  4. method-name-pattern:用于匹配方法的名称,可以是具体的方法名或使用通配符
    *匹配任意方法名。
  5. param-pattern:用于匹配方法的参数类型,可以是具体的类型、通配符表示任意类型、…表示任意个参数、()表示一个参数,以及(*, *)表示两个参数等。
  6. throws-pattern(可选):用于匹配方法可能抛出的异常类型,可以是具体的异常类型或通配符*表示任意异常。

下面是一些示例:
execution(public * com.example.service..(…)):匹配com.example.service包中的所有公共方法。
execution(* com.example.service.UserService.addUser(String, )):匹配com.example.service.UserService类的addUser方法,第一个参数为String类型,第二个参数为任意类型。
execution(
com.example.service..(…) throws java.io.IOException):匹配com.example.service包中所有方法,且可能抛出java.io.IOException异常。

四、通过注解的方式实现Spring AOP

下面我们使用纯注解的方式实现上面的业务需求,程序执行addUser()这个方法之前,通过Spring AOP技术切入一个检查安全性的服务。

  1. 还是和之前一样,首先明确横切性关注点是谁,根据上面的需求我们知道了检查安全性的服务为横切性关注点。
  2. 将横切性关注点进行模块化,定义一个SecurityHandler这个也就是切面(Aspect)
    在这里插入图片描述
    代码实例:
  3. 添加@Aspect注解,表名这个类是一个切面,并且添加@Component注解表名将其交给spring ioc进行管理
package com.wangwei.springaop.service.impl;

import org.aspectj.lang.annotation.Aspect;

@Aspect
@Component
public class SecurityHandler {


   private void checkSecurity() {
      System.out.println("-------checkSecurity-------");
   }
}

  1. 将横切性关注点具体实现,也就是通知(advice)我们需要将其设置设置为前置通知,添加@Before注解
package com.wangwei.springaop.service.impl;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
@Component
public class SecurityHandler {

   @Before("")
   private void checkSecurity() {
      System.out.println("-------checkSecurity-------");
   }
}

  1. 定义切点,定义通知(Advice)应用到那些JoinPoint上,我们这儿的连接点是addUser()这个方法。
package com.wangwei.springaop.service.impl;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class SecurityHandler {
//	@Pointcut("execution(* com.wangwei.springaop.service.impl.UserManagerImpl.addUser(..))")
//	public void myServiceMethods() {}
//
//	@Before("myServiceMethods()")
//	private void checkSecurity(JoinPoint joinPoint) {
//		System.out.println("-------checkSecurity-------");
//	}

	@Before("execution(public * com.wangwei.springaop.service.impl.UserManagerImpl.addUser(..))")
	private void checkSecurity(JoinPoint joinPoint) {
		//可以通过在advice中添加JoinPoint类型的参与来获取客户端调用的方法名或者参数等等...
		for (int i = 0; i < joinPoint.getArgs().length; i++) {
			//打印参数
			System.out.println(joinPoint.getArgs()[i]);
		}
		//获取方法名
		System.out.println(joinPoint.getSignature().getName());
		
		System.out.println("-------checkSecurity-------");
	}

}

  1. 另外将其UserManagerImpl类通过@Service也纳入Spring 容器管理
package com.wangwei.springaop.service.impl;

import com.wangwei.springaop.service.UserManager;
import org.springframework.stereotype.Service;

@Service
public class UserManagerImpl implements UserManager {

	public void addUser(String username, String password) {

		System.out.println("---------UserManagerImpl.add()--------");
	}

	public void delUser(int userId) {

		System.out.println("---------UserManagerImpl.delUser()--------");
	}

	public int findUserById(int userId) {

		System.out.println("---------UserManagerImpl.findUserById()--------");
		return userId;
	}

	public void modifyUser(int userId, String username, String password) {

		System.out.println("---------UserManagerImpl.modifyUser()--------");
	}

}

  1. 客户端进行调用
package com.wangwei.springaop.client;

import com.wangwei.springaop.service.UserManager;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@ComponentScan("com.wangwei.springaop")
//启动Aspect的自动代理,Spring默认不会自动启用AspectJ的自动代理功能
@EnableAspectJAutoProxy
public class Client {

	public static void main(String[] args) {
//		BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");
//		UserManager userManager = (UserManager)factory.getBean("userManager");
//		userManager.addUser("wangwei", "123");
		//我们使用AnnotationConfigApplicationContext来加载配置类,使用MyAppApplication.class作为配置类,即告诉Spring使用MyAppApplication这个类中的注解来构建应用程序上下文
		ApplicationContext context = new AnnotationConfigApplicationContext(Client.class);
		/*
		使用context对象来获取我们的bean并进行依赖注入和使用。注意由于使用Spring Aop时将其目标类进行了代理,所以在Spring IOC容器中
		UserManagerImpl的类型变为了代理类
		下面是打印容器中的对象和对象的类型,可以看到UserManagerImpl的类型为Proxy类型
		 */

		String[] beanNames = context.getBeanDefinitionNames();
		for (String beanName : beanNames) {
			Class<?> beanType = context.getType(beanName);
			System.out.println("Bean Name: " + beanName);
			System.out.println("Bean Type: " + beanType);
			System.out.println("-----------------------");
		}
		//由于UserManagerImpl的类型变为了代理类,所以这里通过默认的bean的名称进行获取
		UserManager userManager = (UserManager) context.getBean("userManagerImpl");
		userManager.addUser("wangwei","123");

	}
}

  1. 运行效果
    在这里插入图片描述

五、Spring对AOP的支持

Spring通过JDK的动态代理实现AOP,可以通过使用CGLIB代理实现AOP。

  1. 如果目标对象实现了接口,在默认情况下会采用JDK的动态代理实现AOP
  2. 如果目标对象实现了接口,也可以强制使用CGLIB生成代理实现AOP
  3. 如果目标对象没有实现接口,那么必须引入CGLIB,spring会在JDK的动态代理和CGLIB代理之间切换

如何强制使用CGLIB

在Spring中可以通过配置文件或注解来强制使用CGLIB代理。

xml文件方式

使用proxy-target-class="true"属性来强制使用CGLIB代理。

<aop:config>
    <aop:proxy proxy-target-class="true"/>
    <!-- 其他的切面和通知配置 -->
</aop:config>

注解的方式

在@EnableAspectJAutoProxy注解中设置proxyTargetClass = true,表示强制使用CGLIB代理。

@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class AppConfig {
    // 配置其他的Bean和切面
}

通过注解方式强制使用CGLIB的示例:

客户端代码

package com.wangwei.springaop.client;

import com.wangwei.springaop.service.UserManager;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@ComponentScan("com.wangwei.springaop")
//启动Aspect的自动代理,Spring默认不会自动启用AspectJ的自动代理功能
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class Client {

	public static void main(String[] args) {
//		BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");
//		UserManager userManager = (UserManager)factory.getBean("userManager");
//		userManager.addUser("wangwei", "123");
		//我们使用AnnotationConfigApplicationContext来加载配置类,使用MyAppApplication.class作为配置类,即告诉Spring使用MyAppApplication这个类中的注解来构建应用程序上下文
		ApplicationContext context = new AnnotationConfigApplicationContext(Client.class);
		/*
		使用context对象来获取我们的bean并进行依赖注入和使用。注意由于使用Spring Aop时将其目标类进行了代理,所以在Spring IOC容器中
		UserManagerImpl的类型变为了代理类
		下面是打印容器中的对象和对象的类型,可以看到UserManagerImpl的类型为Proxy类型
		 */

		String[] beanNames = context.getBeanDefinitionNames();
		for (String beanName : beanNames) {
			Class<?> beanType = context.getType(beanName);
			System.out.println("Bean Name: " + beanName);
			System.out.println("Bean Type: " + beanType);
			System.out.println("-----------------------");
		}
		//由于UserManagerImpl的类型变为了代理类,所以这里通过默认的bean的名称进行获取
		UserManager userManager = (UserManager) context.getBean("userManagerImpl");
		userManager.addUser("wangwei","123");

	}
}

运行截图
可以看到目标类的类型由之前的proxy变为了CGLIB
在这里插入图片描述

JDK动态代理的特点

优势:

  1. 基于接口的代理,适用于接口实现类的代理。
  2. 使用Java自带的反射机制实现代理,无需额外的依赖库。
    劣势:
  3. 代理的目标对象必须实现至少一个接口。
  4. 动态代理的性能相对较低,因为每次调用代理方法都会涉及到反射调用。
  5. 对于无接口的类,无法直接使用JDK动态代理。

CGLIB动态代理的特点

优势:

  1. 基于继承的代理,适用于无接口或者无法通过接口进行代理的类。
  2. 无需目标对象实现接口,可以直接代理普通类。
  3. CGLIB通过生成子类的方式实现代理,因此性能相对较高。
    利弊:
  4. 生成的代理类是目标类的子类,如果目标类被声明为final,将无法使用CGLIB代理。
  5. CGLIB需要额外的依赖库。

区别

  1. JDK动态代理基于接口,通过实现接口的方式进行代理,适用于接口实现类的代理;而CGLIB基于继承,通过生成子类的方式进行代理,适用于无接口或者无法通过接口进行代理的类。
  2. JDK动态代理基于接口,通过实现接口的方式进行代理,适用于接口实现类的代理;而CGLIB基于继承,通过生成子类的方式进行代理,适用于无接口或者无法通过接口进行代理的类。
  3. DK动态代理的性能相对较低,因为每次调用代理方法都会涉及到反射调用;而CGLIB通过生成子类的方式实现代理,性能相对较高。
  4. JDK动态代理对于无接口的类无法直接使用,而CGLIB可以直接代理普通类。

六、总结

将Spring AOP运行到具体业务的步骤:

  1. 抽象出横切性关注点
  2. 将横切性关注点进行模块化,模块化的结果就是切面(Aspect)
  3. 将横切性关注点具体实现,实现的结果为通知(advice)并定义通知的类型
  4. 定义切点,也就是将通知advice应用到那些连接点上(joinpoint)

这个过程中涉及到代理、织入(weave)、引入。

如果选择JDK动态代理还是CGLIB代理:

选择使用JDK动态代理还是CGLIB取决于具体的需求。

  1. 如果目标类实现了接口且性能要求较低,可以选择JDK动态代理;
  2. .如果目标类无接口或者无法通过接口进行代理,或者性能要求较高,可以选择CGLIB代理。
  3. spring框架会自动在动态代理和CGLIB代理之间切换

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/543509.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

OpenAI 宣布推出适用于 iPhone 和 iPad 的 ChatGPT 官方应用程序。

&#x1f680; OpenAI 宣布推出适用于 iPhone 和 iPad 的 ChatGPT 官方应用程序。 OpenAI 宣布推出适用于 iPhone 和 iPad 的 ChatGPT 官方应用程序。 该应用程序具备即时回答各种问题、量身定制的建议、创意灵感、专业意见和个性化学习等功能和特性&#xff0c;可以帮助提高…

【密码产品篇】服务器密码机密钥体系结构

【密码产品篇】服务器密码机密钥体系结构 标准GM/T 0030-2014中规定服务器密码机必须至少支持三层密码体系结构&#xff0c;包括&#xff1a;“管理密钥、用户密钥/设备密钥/密钥加密密钥、会话密钥”。除"管理密钥"外&#xff0c;其他密钥可被用户使用&#xff0c;…

在图片上添加水印的四个方法

如何在图片上添加水印&#xff1f;在当今开放的互联网环境中&#xff0c;平时对于图片的使用已经变成非常广泛&#xff0c;越来越多的人开始关注图片的版权问题。如今&#xff0c;人们越来越注重防盗意识&#xff0c;这是因为我们在网上发布的图片很容易被别有用心之人盗用&…

Maven仓库

1、仓库 仓库&#xff1a;用于存储资源&#xff0c;主要是各种jar包 关于仓库&#xff0c;我们前面讲到了有三种&#xff1a;本地仓库&#xff0c;私服&#xff0c;中央仓库&#xff0c;其中私服和中央仓库都属于远程仓库 中央仓库&#xff1a;maven团队自身维护的仓库&#…

Java面试知识点(全)- Java并发-多线程JUC一

Java面试知识点(全) 导航&#xff1a; https://nanxiang.blog.csdn.net/article/details/130640392 注&#xff1a;随时更新 JUC框架 五个部分&#xff1a; 主要包含: (注意: 网上找的图&#xff0c;主体上可以看出其分类关系也够了) Lock框架和Tools类(把图中这两个放到一起…

一起Linux操作系统部署的Mysql数据库服务器/目录空间占用异常的分析事例

一台Linux操作系统部署的Mysql数据库服务器平时“/"目录占用很低&#xff0c;但每个小时都会出现一次根目录空间占用高的情况&#xff0c;本文系从OS侧对异常事件进行分析排查的过程。 1、初步分析 主机已进行监控&#xff0c;分析监控图表 可见该数据库服务器日常根目录…

王炸功能ChatGPT 联网插件功能放开,视频文章一键变思维导图

就在上周5月13日&#xff0c;Open AI 发文称&#xff1a;“我们将在下周向所有ChatGPT Plus 用户开放联网功能和众多插件”。 这意味着什么&#xff1f; 首先联网功能将使得ChatGPT不再局限于回答2021年9月之前的信息&#xff0c;能直接联网查询最新消息。 而插件功能就可以在…

基于LT6911UXC的LVDS视频接口调试经验

项目方案采用龙讯半导体LT6911系列。 该方案采用HDMI输出转LVDS接口。在本方案中有两种显示屏&#xff1b;一个是10.4寸&#xff0c;一个是15.6寸。分别应 单LVDS与双LVDS接口。 10.4寸屏幕的分辨率为1024*768&#xff1b;单八LVDS信号&#xff1b; 15.6寸的屏幕的分辨率为19…

SSD202D-MIPI屏点亮

调试mipi 点屏参考 - SigmaStarDocs Panel开发参考 - SigmaStarDocs 1.首先要看点屏参考,看懂硬件接线这些原理,然后依据实际的接线配置屏参 和RGB是复用的,所以不一样, 然后配置内核,我是直接编译mipi的内核 2.配置屏参,

如何进行测试分析与设计-HTSM启发式测试策略模型 | 京东云技术团队

测试&#xff0c;没有分析与设计就失去了灵魂&#xff1b; 测试人员在编写用例之前&#xff0c;该如何进行测试分析与设计呢&#xff1f;上次在《测试的底层逻辑》中讲到了【输入输出测试模型】&#xff0c;还讲到了【2W1H测试分析法】&#xff0c;但2W1H分析法是初步的分析方…

Sharding-JDBC分库分表

Sharding-JDBC分库分表 一 分库分表概述 ​ 分库分表&#xff0c;就是为了解决由于数据量过大而导致数据库性能降低的问题&#xff0c;将原来独立的数据库拆分成若干数据库组成&#xff0c;将数据大表拆分为若干数据表组成&#xff0c;使得单一数据库&#xff0c;单一数据表的…

深度学习在语音识别方面的应用

前言 语音识别是一项非常重要的技术&#xff0c;它可以将人类的语音转化为计算机可以理解的形式。深度学习是一种非常强大的机器学习技术&#xff0c;它在语音识别方面也有广泛的应用。本文将详细介绍深度学习在语音识别方面的应用。 语音识别的基本步骤 语音识别的基本步骤包…

KDZD5550系列电压击穿试验仪系统组成

一、产品概述 KDZD5550系列电压击穿试验仪根据国家GB1408.1-2006《绝缘材料电气强度试验方法》其作用可称为电气绝缘强度试验仪、介质强度测试仪等。其工作原理是&#xff1a;把一个高于正常工作的电压加在被测设备的绝缘体上&#xff0c;持续一段规定的时间&#xff0c;加在上…

《软技能:代码以外的生存指南》阅读总结

文章收录&#xff1a; 个人网址&#xff1a;http://linglan01.cn/Github仓库&#xff1a;https://github.com/CatsAndMice/blog/issues 推荐一篇蛮有营养的文章速读《软技能 代码之外的生存指南》。 我比较喜欢实体书籍&#xff0c;所以自己干脆买一本《软技能&#xff1a;代码…

2023年5月DAMA-CDGA/CDGP数据治理认证考试报名

DAMA认证为数据管理专业人士提供职业目标晋升规划&#xff0c;彰显了职业发展里程碑及发展阶梯定义&#xff0c;帮助数据管理从业人士获得企业数字化转型战略下的必备职业能力&#xff0c;促进开展工作实践应用及实际问题解决&#xff0c;形成企业所需的新数字经济下的核心职业…

c++(类和对象下)

本节目标 1. 再谈构造函数 2. Static成员 3. 友元 4. 内部类 5.匿名对象 6.拷贝对象时的一些编译器优化 7. 再次理解封装 目录 1、再谈构造函数 1.1构造函数体赋值 1.2初始化列表 2 static 成员 2.1概念 2.2特性 3.友元 3.1友元函数 3.2友元类 4.内部类 5匿名对…

甘特图控件DHTMLX Gantt教程:用PHP:Laravel实现Gantt(上)

DHTMLX Gantt是用于跨浏览器和跨平台应用程序的功能齐全的Gantt图表。可满足项目管理应用程序的大部分开发需求&#xff0c;具备完善的甘特图图表库&#xff0c;功能强大&#xff0c;价格便宜&#xff0c;提供丰富而灵活的JavaScript API接口&#xff0c;与各种服务器端技术&am…

国考省考行测:资料分析:增量减量计算公式,百分数化分数

国考省考行测&#xff1a;增量减量计算公式 2022找工作是学历、能力和运气的超强结合体! 公务员特招重点就是专业技能&#xff0c;附带行测和申论&#xff0c;而常规国考省考最重要的还是申论和行测&#xff0c;所以大家认真准备吧&#xff0c;我讲一起屡屡申论和行测的重要知…

医院安全(不良)事件管理系统源码,PHP语言开发

医院不良事件上报系统源码 医院安全(不良)事件管理系统 ,是以提高医院医疗服务质量为目的&#xff0c;收集、处理医院内发生的医院安全不良相关事件&#xff0c;进行统计分析&#xff0c;并持续整改&#xff0c;完成闭环管理&#xff1b;为医院医疗服务质量的提升提供信息支撑…

Minio有了这篇文章,比SDK要好入门多了

想学minio&#xff0c;看小编这边文章可以解决你很多问题 一、安装minio1.1、创建文件夹&#xff0c;并在指定文件夹中下载minio文件1.2、赋予minio文件执行权限1.3、启动minio1.4、修改环境变量1.5、指定端口启动minio服务1.6、访问界面 二、Springboot整合Minio2.1、引入mave…