@Aspect

AOP是指在程序运行期间动态地将某段代码切入到指定位置并运行的编程方式。

AOP详解可参考:https://blog.csdn.net/javazejian/article/details/56267036

切点表达式详解可参考:https://www.cnblogs.com/zhangxufeng/p/9160869.html

2-1execution表达式

由于Spring切面粒度最小是达到方法级别,而execution表达式可以用于明确指定方法返回类型、类名、方法名和参数名等与方法相关的部件。并且在Spring中,大部分需要使用AOP的业务场景也只需要达到方法级别即可,因而execution表达式的使用是最为广泛的。如下是execution表达式的语法:

execution([visibility-pattern] ret-type-pattern [declaring-type-pattern]method-name-pattern(param-pattern) [throws-pattern])
  • 中括号[]包括的内容表示在写切点表达式时可以省略。而其他的不能省略,但可用通配符代替。
  • visibility-pattern:方法的可见性,如public, protected;
  • ret-type-pattern:方法的返回值类型,如void, Integer;
  • declaring-type-pattern:方法所在类的全路径(可以包括 类名),如com.myaop.MathCalculator;
  • method-name-pattern:方法名,如division();
  • param-pattern:方法的参数类型,如java.lang.String;
  • throws-pattern:方法抛出的异常类型,如java.lang.Exception。

如下是一个使用execution表达式的例子:

execution(public * com.myaop.MathCalculator.division(Integer,..))

这个切点表达式将会匹配:使用public修饰、返回值为任意类型、是com.myaop.MathCalculator类中的名为division的方法、这个方法可以有多个参数,但第一个参数必须是Integer类型(int不匹配)。

2-2通配符

上述示例中使用了..通配符,通配符主要有两种:

  • *通配符:主要用于匹配单个单词,或者是以某个词为前缀或后缀的单词。
  • 如表达式:
execution(* com.myaop.MathCalculator.*())

返回值为任意类型、在com.myaop.MathCalculator类中、无参的方法。
– 如表达式:

execution(* com.myaop.Math*.*())

返回值为任意类型、在com.myaop.Math为前缀的类中、无参的方法。
* ..通配符:表示0个或多个项,主要用于declaring-type-pattern和param-pattern中。如果用于declaring-type-pattern中,则表示匹配当前包及其子包;如果用于param-pattern中,则表示匹配0个或多个参数。
– 如表达式:

execution(* com..divi*(..))

返回值为任意类型、在 com包及其子包下所有以divi开头、参数任意的方法。
特别注意:如果..用于declaring-type-pattern中,在表示匹配当前包及其子包的同时,还相当于在匹配的declaring-type-pattern结果后 再加了一个分隔符(.)。如果将MathCalculator类放在包路径com.myaop.business下,则有:
– *上图中表达式表示为:返回值为任意类型,在包com包及其子包下的所有类的以divi开头、参数任意的方法。

3-1导入AOP依赖

<dependency>
    <groupid>org.springframework</groupid>
    <artifactid>spring-aspects</artifactid>
    <version>4.3.12.RELEASE</version>
</dependency>

具体使用时还需引进spring-context的相关依赖

<dependency>
    <groupid>org.springframework</groupid>
    <artifactid>spring-context</artifactid>
    <version>5.2.10.RELEASE</version>
</dependency>

3-2创建业务类

创建业务类(MathCalculator)。

package com.myaop;

import org.springframework.stereotype.Component;

@Component
public class MathCalculator {
    public int division(int dividend, int divisor) {
        System.out.println("--&#x6267;&#x884C;division&#x65B9;&#x6CD5;");
        int result = dividend / divisor;
        return result;
    }
}

3-3创建切面类

package com.myaop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Component
//Aspect&#x6CE8;&#x89E3;&#x53EA;&#x662F;&#x7528;&#x6765;&#x544A;&#x8BC9;&#x5BB9;&#x5668;&#x8FD9;&#x662F;&#x4E00;&#x4E2A;&#x5207;&#x9762;&#x7C7B;&#xFF0C;&#x4F46;&#x5E76;&#x4E0D;&#x80FD;&#x5C06;&#x6B64;&#x7C7B;&#x4F5C;&#x4E3A;&#x4E00;&#x4E2A;&#x7EC4;&#x4EF6;&#x6DFB;&#x52A0;&#x8FDB;&#x5BB9;&#x5668;&#x4E2D;
@Aspect
public class MyAspect {

    //&#x5B9A;&#x4E49;&#x5207;&#x70B9;
    @Pointcut("execution(int com.myaop.MathCalculator.*(..))")
    public void pointCut() {
    }

    //&#x524D;&#x7F6E;&#x901A;&#x77E5;&#xFF1A;&#x5728;&#x76EE;&#x6807;&#x65B9;&#x6CD5;&#x6267;&#x884C;&#x524D;&#x6267;&#x884C;
    @Before("pointCut()")
    public void before(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("before &#x65B9;&#x6CD5;" + methodName);
    }

    //&#x540E;&#x7F6E;&#x901A;&#x77E5;&#xFF1A;&#x5728;&#x76EE;&#x6807;&#x65B9;&#x6CD5;&#x6267;&#x884C;&#x540E;&#x6267;&#x884C;&#x3002;&#x65E0;&#x8BBA;&#x76EE;&#x6807;&#x65B9;&#x6CD5;&#x662F;&#x5426;&#x6B63;&#x5E38;&#x6267;&#x884C;&#xFF08;&#x540E;&#x7F6E;&#x901A;&#x77E5;&#x65E0;&#x8BBA;&#x5982;&#x4F55;&#x90FD;&#x4F1A;&#x88AB;&#x6267;&#x884C;&#xFF09;
    @After("pointCut()")
    public void after(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("after &#x65B9;&#x6CD5;" + methodName);
    }

    /**
     * &#x73AF;&#x7ED5;&#x901A;&#x77E5;&#xFF1A;
     * &#x6CE8;&#x610F;&#xFF1A;
     * 1.joinPoint.proceed()&#x6267;&#x884C;&#x540E;&#x7684;&#x7ED3;&#x679C;&#x9700;&#x8981;&#x8FD4;&#x56DE;&#x51FA;&#x53BB;&#x3002;
     */
    @Around("pointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("around &#x65B9;&#x6CD5;" + methodName + "&#xFF0C;proceed()&#x524D;&#x7684;&#x4EE3;&#x7801;&#x5757;&#x6267;&#x884C;");
        Object result = joinPoint.proceed();
        System.out.println("around &#x65B9;&#x6CD5;" + methodName + "&#xFF0C;proceed()&#x540E;&#x7684;&#x4EE3;&#x7801;&#x5757;&#x6267;&#x884C;");
        return result;
    }

    /**
     * &#x8FD4;&#x56DE;&#x901A;&#x77E5;&#xFF1A;&#x5728;&#x76EE;&#x6807;&#x65B9;&#x6CD5;&#x6B63;&#x5E38;&#x6267;&#x884C;&#x5E76;&#x8FD4;&#x56DE;&#x540E;&#x6267;&#x884C;
     * &#x6CE8;&#x610F;&#xFF1A;
     * 1.&#x6CE8;&#x89E3;&#x4E2D;&#x7684;value&#x53C2;&#x6570;&#x9700;&#x8981;&#x653E;&#x5728;&#x6700;&#x524D;&#x9762;
     */
    @AfterReturning(value = "pointCut()", returning = "result")
    public void afterReturning(JoinPoint joinPoint, Object result) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("afterReturning &#x65B9;&#x6CD5;" + methodName);
    }

    /**
     * &#x5F02;&#x5E38;&#x901A;&#x77E5;&#xFF1A;&#x5728;&#x76EE;&#x6807;&#x65B9;&#x6CD5;&#x6267;&#x884C;&#x8FC7;&#x7A0B;&#x4E2D;&#x51FA;&#x73B0;&#x5F02;&#x5E38;&#x4E14;&#x65B9;&#x6CD5;&#x81EA;&#x52A8;&#x7ED3;&#x675F;&#x540E;&#x6267;&#x884C;
     * &#x6CE8;&#x610F;&#xFF1A;
     * 1.&#x5982;&#x679C;&#x76EE;&#x6807;&#x65B9;&#x6CD5;&#x51FA;&#x73B0;&#x5F02;&#x5E38;&#x4F46;&#x662F;&#x88AB;&#x65B9;&#x6CD5;&#x4E2D;&#x7684;try...catch&#x6355;&#x83B7;&#x4E86;&#x800C;&#x6CA1;&#x6709;&#x629B;&#x51FA;&#xFF0C;&#x5219;&#x5F02;&#x5E38;&#x901A;&#x77E5;&#x4E0D;&#x4F1A;&#x6267;&#x884C;
     * 2.&#x6CE8;&#x89E3;&#x4E2D;&#x7684;value&#x53C2;&#x6570;&#x9700;&#x653E;&#x5728;&#x6700;&#x524D;&#x9762;&#x3002;
     */
    @AfterThrowing(value = "pointCut()", throwing = "exception")
    public void afterThrowing(JoinPoint joinPoint, Exception exception) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("afterThrowing &#x65B9;&#x6CD5;" + methodName);
    }
}

3-4创建配置类

通过配置类将切面和业务类作为组件添加到容器中,并通过@EnableAspectJAutoProxy注解开启切面功能。

package com.myaop;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@ComponentScan(value = "com.myaop")
@EnableAspectJAutoProxy
public class MyConfiguration {
}

3-5测试切面功能

package com.myaop;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfiguration.class);
        MathCalculator mathCalculator = context.getBean("mathCalculator", MathCalculator.class);
        mathCalculator.division(1, 1);
    }
}

当mathCalculator.division(1,1)时,运行结果为:

around &#x65B9;&#x6CD5;division&#xFF0C;proceed()&#x524D;&#x7684;&#x4EE3;&#x7801;&#x5757;&#x6267;&#x884C;
before &#x65B9;&#x6CD5;division
after &#x65B9;&#x6CD5;division
afterThrowing &#x65B9;&#x6CD5;division
Exception in thread "main" java.lang.ArithmeticException: / by zero
    at com.myaop.MathCalculator.division(MathCalculator.java:9)
    at com.myaop.MathCalculator$$FastClassBySpringCGLIB$$c5dccaaf.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:769)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747)
    at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:56)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747)
    at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:88)
    at com.myaop.MyAspect.around(MyAspect.java:41)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633)
    at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747)
    at org.springframework.aop.aspectj.AspectJAfterAdvice.invoke(AspectJAfterAdvice.java:47)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747)
    at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:55)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747)
    at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:62)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689)
    at com.myaop.MathCalculator$$EnhancerBySpringCGLIB$$cf10f693.division(<generated>)
    at com.myaop.Main.main(Main.java:9)
</generated></generated>

4-1spring-context.5.2.4.RELEASE

当使用如下依赖版本时:

<dependency>
    <groupid>org.springframework</groupid>
    <artifactid>spring-context</artifactid>
    <version>5.2.4.RELEASE</version>
</dependency>
<dependency>
    <groupid>org.springframework</groupid>
    <artifactid>spring-aspects</artifactid>
    <version>4.3.12.RELEASE</version>
</dependency>

遵循如下规律:

public Object aop(Method method,Object object) {
    try {
        try {
            /*doAround start*/
            doBefore();
            method.invoke(object);
            /*doAround end*/
        }catch(){
            throw ...;
        }
        finally {
            doAfter();
        }
        doAfterReturning();
    } catch (Exception e) {
        doAfterThrowing();
    }
}

doAround start为around通知方法中joinPoint.proceed()之前的代码块;

doAround end为around通知方法中joinPoint.proceed()之后的代码块;

目标方法正常执行的情况下,执行顺序为:@Around @Before 目标方法 @Around @After @AfterReturning;

目标方法抛出了异常的情况下,执行顺序为:@Around @Before 目标方法 @After @AfterThrowing。

4-2spring-context.5.2.10.RELEASE

当使用如下依赖版本时(spring-context.5.2.4RELEASE更新为了spring-context.5.2.10.RELEASE):

<dependency>
    <groupid>org.springframework</groupid>
    <artifactid>spring-context</artifactid>
    <version>5.2.10.RELEASE</version>
</dependency>
<dependency>
    <groupid>org.springframework</groupid>
    <artifactid>spring-aspects</artifactid>
    <version>4.3.12.RELEASE</version>
</dependency>

就不遵循4-1中的规律了。目标方法执行后的通知执行顺序变了。

当mathCalculator.division(1,1)时,运行结果为:

around &#x65B9;&#x6CD5;division&#xFF0C;proceed()&#x524D;&#x7684;&#x4EE3;&#x7801;&#x5757;&#x6267;&#x884C;
before &#x65B9;&#x6CD5;division
afterThrowing &#x65B9;&#x6CD5;division
after &#x65B9;&#x6CD5;division
Exception in thread "main" java.lang.ArithmeticException: / by zero
    at com.myaop.MathCalculator.division(MathCalculator.java:9)
    at com.myaop.MathCalculator$$FastClassBySpringCGLIB$$c5dccaaf.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
    at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:62)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
    at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:55)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
    at org.springframework.aop.aspectj.AspectJAfterAdvice.invoke(AspectJAfterAdvice.java:47)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
    at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:56)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
    at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:88)
    at com.myaop.MyAspect.around(MyAspect.java:41)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633)
    at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)
    at com.myaop.MathCalculator$$EnhancerBySpringCGLIB$$adde1634.division(<generated>)
    at com.myaop.Main.main(Main.java:9)

Process finished with exit code 1
</generated></generated>

Original: https://www.cnblogs.com/certainTao/p/15363906.html
Author: certainTao
Title: @Aspect

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/585273/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 简单易用的任务队列-beanstalkd

    概述 beanstalkd 是一个简单快速的分布式工作队列系统,协议基于 ASCII 编码运行在 TCP 上。其最初设计的目的是通过后台异步执行耗时任务的方式降低高容量 Web 应…

    Linux 2023年6月7日
    0105
  • Jenkins

    Jenkins Jenkins jenkins简介 jenkins工作原理 jenkins特点 CI/CD是什么 使用tomcat容器安装jenkins jenkins流水线项目发…

    Linux 2023年6月6日
    0118
  • 【MQTT】阿里云搭建MQTT物联网平台通信

    MQTT环境搭建和测试 物联网环境搭建 MQTT.fx使用 物联网环境搭建 1.首先进入阿里云官网注册并登录你的账号。2.点击控制台。3.在产品与服务下面搜索物联网平台4.点击公共…

    Linux 2023年6月13日
    085
  • python的日期处理

    俗话说,工欲善其事必先利其器,所以在使用日期前要先对日期进行处理,所以时间戳和字符串的来回来去转换这个事肯定是要搞的 这次的函数有一个?有两个?有三个?有四个!上代码! 哈哈,像不…

    Linux 2023年6月6日
    085
  • Sublime Text 左侧不显示目录树如何解决

    方法一: 依次点击 View – Side Bar – Show Side Side点击后左侧的目录树就会显示出来了,如下图所示方法二:快捷键 Mac : …

    Linux 2023年6月13日
    099
  • 学习linux(centos7)记录的笔记

    此随笔用于记录学习《linux鸟哥的私房菜》过程中1.遇到的问题及解决的过程 2.有必要记录的重要内容 3.对应书上操作的记录 开始于2021年6月18号 一个磁盘的分区通过格式化…

    Linux 2023年6月6日
    088
  • Docker 环境 Nacos2 MySQL8

    本文介绍 docker 环境下安装并单机运行 Nacos2,使用 docker 环境下的 MySQL 8 存储数据。 1 拉取镜像 1.1 创建目录 在硬盘上创建 nacos 的有…

    Linux 2023年6月7日
    099
  • Failed to configure a DataSource ‘url’ attribute问题解决

    才写了一行代码又报错了.. *************************** APPLICATION FAILED TO START ********************…

    Linux 2023年6月13日
    083
  • 如何使用 Javascript 将图标字体渲染为图片

    前言 在软件开发中肯定要用到图标,比如下图的 Groove 音乐中就用到了许多图标。一种获取这些图标的方法是把 Groove 音乐截个图,然后熟练地开启 Photoshop,开始抠…

    Linux 2023年6月7日
    0109
  • mysql内连接查询之自连接

    连接查询:当查询数据时,通过连接操作查询出存放在多个表中的不同数据,当两个或者多个表中存在相同意义的字段时,便可以通过这些字段对不同的表进行连接查询。自连接:如果在一个连接查询中,…

    Linux 2023年6月7日
    091
  • 线程池如何保证核心线程一直存活

    转载请注明出处: 查看 ThreadPoolExecutor 类中的 getTask 方法,这个方法可以保持核心线程在没有任务的时候也可以一直处于存活状态 核心在于 workQue…

    Linux 2023年6月14日
    0158
  • 离线版centos8安装docker笔记

    嗨嗨哈哈,已经很久没有坐下来胡编乱造一点笔记了,平时云服务器搞惯了,一个命令就安装好了docker了的,但这次生不逢时的新机房就没那么幸运了,有多不逢时超乎想象,不仅仅服务器没有外…

    Linux 2023年5月27日
    0133
  • 人人都写过的5个Bug!

    大家好,我是良许。 计算机专业的小伙伴,在学校期间一定学过 C 语言。它是众多高级语言的鼻祖,深入学习这门语言会对计算机原理、操作系统、内存管理等等底层相关的知识会有更深入的了解,…

    Linux 2023年5月27日
    0133
  • redis查看状态信息

    redis查看状态信息 info all|default Info 指定项 server服务器信息 redis_version : Redis 服务器版本 redis_git_sh…

    Linux 2023年5月28日
    099
  • Redis多线程原理详解

    从上图中可以看出只有以下3个地方用的是多线程,其他地方都是单线程: 1:接收请求参数 2:解析请求参数 3:请求响应,即将结果返回给client 很明显以上3点各个请求都是互相独立…

    Linux 2023年5月28日
    084
  • 【4】2022年6月

    6月15日 今早10点教师资格面试成绩出来了,幸好一次性通过。笔面都一次性通过,比我预想的顺利,谢谢各位考官的照顾。 我知道自己面试的时候既感冒又受伤,状态是不好的,发挥不了真实的…

    Linux 2023年6月13日
    078
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球