AspectJ使用

2023-11-19

一、AOP介绍

AOP:Aspect-Oriented Programming,面向切面编程,是一种新的方法论(编程范式),是对传统 OOP(Object-Oriented Programming,面向对象编程)的补充。旨在通过允许横切关注点的分离,提高模块化。如在方法执行前、或执行后、或是在执行中出现异常后这些地方进行拦截处理或叫做增强处理。主要应用于:日志收集、事务管理、安全检查、缓存、对象池管理等。

AOP实现的关键就在于AOP框架自动创建的AOP代理,AOP代理则可分为静态代理(例如:原生AspectJ)和动态代理(例如:spring aop)两大类,其中静态代理是指使用AOP框架提供的命令进行编译,从而在编译阶段就可生成 AOP 代理类,因此也称为编译时增强;而动态代理则在运行时借助于JDK动态代理、CGLIB等在内存中“临时”生成AOP动态代理类,因此也被称为运行时增强。

AOP基本概念:

  • 切入点(pointcut):在哪些类、哪些方法上切入,通常是一个正则表达式
  • 执行点(JoinPoint):通过pointcut选取出来的集合中的具体的一个执行点,我们就叫JoinPoint
  • 通知(advice):在方法前、方法后、方法前后、异常等做什么。
  • 切面(aspect):切面 = pointcut + advice。即在什么时机、什么地方、做什么。
  • 织入(weaving):把切面加入对象,并创建出代理对象的过程。

二、AspectJ介绍

AspectJ:全称Eclipse AspectJ,官网The AspectJ Project | The Eclipse Foundation 是Java社区里最完整最流行的AOP框架,即AOP的java版实现,它定义了AOP语法,它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件。(除了AspectJ外,还有很多AOP实现,例如ASMDex)

aspectJ可以单独使用,也可以整合到其它框架中。单独使用AspectJ时需要使用专门的编译器ajc。java的编译器是javac,AspectJ的编译器是ajc,aj是首字母缩写,c即compiler。

1、AspectJ原理:

AspectJ属于静态织入,通过修改代码来实现,有如下几个织入的时机:

  1. ​编译期织入(Compile-time weaving): 如类 A 使用 AspectJ 添加了一个属性,类 B 引用了它,这个场景就需要编译期的时候就进行织入,否则没法编译类 B。
  2. 编译后织入(Post-compile weaving): 也就是已经生成了 .class 文件,或已经打成 jar 包了,这种情况我们需要增强处理的话,就要用到编译后织入。
  3. 类加载后织入(Load-time weaving): 指的是在加载类的时候进行织入,要实现这个时期的织入,有几种常见的方法。1、自定义类加载器来干这个,这个应该是最容易想到的办法,在被织入类加载到 JVM 前去对它进行加载,这样就可以在加载的时候定义行为了。2、在 JVM 启动的时候指定 AspectJ 提供的 agent:-javaagent:xxx/xxx/aspectjweaver.jar。

AspectJ可以做Spring AOP干不了的事情,它是AOP编程的完全解决方案,Spring AOP则致力于解决企业级开发中最普遍的AOP(方法织入)。而不是成为像AspectJ一样的AOP方案。因为AspectJ在实际运行之前就完成了织入,所以说它生成的类是没有额外运行时开销的。

Spring AOP

AspectJ

在纯 Java 中实现

使用 Java 编程语言的扩展实现

不需要单独的编译过程

除非设置 LTW,否则需要 AspectJ 编译器 (ajc)

只能使用运行时织入

运行时织入不可用。支持编译时、编译后和加载时织入

功能不强-仅支持方法级编织

更强大 - 可以编织字段、方法、构造函数、静态初始值设定项、最终类/方法等......。

只能在由 Spring 容器管理的 bean 上实现

可以在所有域对象上实现

仅支持方法执行切入点

支持所有切入点

代理是由目标对象创建的, 并且切面应用在这些代理上

在执行应用程序之前 (在运行时) 前, 各方面直接在代码中进行织入

比 AspectJ 慢多了

更好的性能

易于学习和应用

相对于 Spring AOP 来说更复杂

在实际生产中,我们用得最多的还是 Spring AOP。

2、AspectJ的使用:https://javadoop.com/post/aspectj

前面介绍了 Spring AOP 的各种用法,包括随着 Spring 的演进而发展出来的几种配置方式。但是我们始终没有使用到 AspectJ,即使是在基于注解的 @AspectJ 的配置方式中,Spring 也仅仅是使用了 AspectJ 包中的一些注解而已,并没有依赖于 AspectJ 实现具体的功能,接下来将介绍AspectJ的使用

2.1)代码如下

1)maven依赖:

<!-- aspectj -->
<dependency>
	   <groupId>org.aspectj</groupId>
	   <artifactId>aspectjrt</artifactId>
	   <version>1.8.13</version>
</dependency>
<dependency>
	    <groupId>org.aspectj</groupId>
	    <artifactId>aspectjweaver</artifactId>
	    <version>1.8.13</version>
</dependency>

2)定义一个类,对其进行weaving:

package a.b.c.tftest.model;

public class Account {
    public int balance = 20;

    public boolean pay(int amount) {
        if (balance < amount) {
            return false;
        }
        balance -= amount;
        return true;
    }
}

3)接下来,我们定义两个Aspect来进行weaving演示:

A、AccountAspect:

用 AspectJ 的语法来写,对交易进行拦截,如此次交易超过余额,直接拒绝。AccountAspect 需要以 .aj 结尾,如我们在a.b.c.tftest.aspectj 下新建文件 AccountAspect.aj,内容如下:

package a.b.c.tftest.aspectj;

import a.b.c.tftest.model.Account;

public aspect AccountAspect {
    pointcut callPay(int amount, Account account):
            call(boolean a.b.c.tftest.model.Account.pay(int)) && args(amount) && target(account);

    before(int amount, Account account): callPay(amount, account) {
        System.out.println("[AccountAspect]付款前总金额: " + account.balance);
        System.out.println("[AccountAspect]需要付款: " + amount);
    }

    boolean around(int amount, Account account): callPay(amount, account) {
        if (account.balance < amount) {
            System.out.println("[AccountAspect]拒绝付款!");
            return false;
        }
        return proceed(amount, account);
    }

    after(int amount, Account balance): callPay(amount, balance) {
        System.out.println("[AccountAspect]付款后,剩余:" + balance.balance);
    }
}

 B、ProfilingAspect:用 Java 来写,用于记录方法的执行时间

package a.b.c.tftest.aspectj;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class ProfilingAspect {
    
    @Pointcut("execution(* a.b.c.tftest.model.*.*(..))")
    public void modelLayer() {
    }

    @Around("modelLayer()")
    public Object logProfile(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        Object result = joinPoint.proceed();
        System.out.println("[ProfilingAspect]方法: 【" + joinPoint.getSignature() + "】结束,用时: " + (System.currentTimeMillis() - start));

        return result;
    }
}

4)定一个主类:

package a.b.c.tftest;

import a.b.c.tftest.model.Account;
import cn.edu.nuc.test.User;

public class App {
    public static void main(String[] args) {
        testCompileTime();
    }
    public static void testCompileTime() {
        Account account = new Account();
        System.out.println("==================");
        account.pay(10);
        account.pay(50);
        System.out.println("==================");
    }
}

可以看到:AspectJ的语法比较难理解,使用AspectJ提供的注解来写还是比较方便的(Spring AOP也是使用了AspectJ提供的注解)。代码结构如下:

接下来,我们讨论怎么样将定义好的两个 Aspects 织入到我们的 Account 的付款方法 pay(amount) 中,也就是三种织入时机分别是怎么实现的。

2.2【Complie-Time Weaving】示例

这是最简单的使用方式,在编译期的时候进行织入,这样编译出来的 .class 文件已经织入了我们的代码,在 JVM 运行的时候其实就是加载了一个普通的被织入了代码的类。

1)aspject-maven插件:

采用 maven 进行管理,可以在 <build> 中加入以下的插件:

<build>
    <finalName>tftest</finalName>
    <plugins>
        <!-- 编译期织入 -->
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>aspectj-maven-plugin</artifactId>
            <version>1.11</version>
            <configuration>
                <complianceLevel>1.8</complianceLevel>
                <source>1.8</source>
                <target>1.8</target>
                <showWeaveInfo>true</showWeaveInfo>
                <verbose>true</verbose>
                <Xlint>ignore</Xlint>
                <encoding>UTF-8</encoding>
            </configuration>
            <executions>
                <execution>
                    <configuration>
                        <skip>false</skip>
                    </configuration>
                    <goals>
                        <goal>compile</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <!--打包插件-->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>2.4</version>
            <configuration>
                <archive>
                    <manifest>
                        <mainClass>a.b.c.tftest.Test</mainClass>
                    </manifest>
                </archive>
                <descriptors>
                    <descriptor>assembly/assembly.xml</descriptor>
                </descriptors>
                <descriptorRefs>  
                    <descriptorRef>jar-with-dependencies</descriptorRef>  
                </descriptorRefs>  
            </configuration>
            <executions>
                <execution>
                    <id>make-assembly</id>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
        </plugin> 
    </plugins>
    
    <pluginManagement>
    <plugins>
        <!--This plugin's configuration is used to store Eclipse 
            m2e settings only. It has no influence on the Maven build itself. -->
        <plugin>
            <groupId>org.eclipse.m2e</groupId>
            <artifactId>lifecycle-mapping</artifactId>
            <version>1.0.0</version>
            <configuration>
                <lifecycleMappingMetadata>
                    <pluginExecutions>
                        <pluginExecution>
                            <pluginExecutionFilter>
                                <groupId>org.codehaus.mojo</groupId>
                                <artifactId>aspectj-maven-plugin</artifactId>
                                <versionRange>[1.0,)</versionRange>
                                <goals>
                                    <goal>test-compile</goal>
                                    <goal>compile</goal>
                                </goals>
                            </pluginExecutionFilter>
                            <action>
                                <execute />
                            </action>
                        </pluginExecution>
                    </pluginExecutions>
                </lifecycleMappingMetadata>
            </configuration>
        </plugin>
    </plugins>
</pluginManagement>
</build>

说明:如果是eclipse,使用这个插件可能会报如下错误:Plugin execution not covered by lifecycle configuration: org.codehaus.mojo:aspectj-maven-plugin:1.11:compile (execution: default, phase: compile) ,解决方法就是按照上面方式添加一个<pluginManagement>

2)然后通过mvn package打包:

编译后,可以看到AccountAspect.aj已经被编译成了class,如下:

 此外,App代码也被修改了:

Account类也被修改了:

 执行App后,输出:

 2.3 【Post-Compile Weaving】示例:

Post-Compile Weaving 和 Compile-Time Weaving 非常类似,我们也是直接用场景来说。

假设上面的 Account 类在test.jar 包中,我们的工程 tftest.jar依赖了这个 jar 包。由于 Account 这个类已经被编译出来了,我们要对它的方法进行织入,就需要用到编译后织入。

为了方便测试,新建一个test工程,里面就一个类 User,代码和 Account 一样,mvn package打成test.jar包,里面就这一个User类。同时在tftest工程里引入test.jar,然后也复制 AccountAspect 一份出来,命名为 UserAspect,稍微修改修改就可以用来处理 User 类了。

1)test工程代码:

mvn信息如下:

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>cn.edu.nuc</groupId>
  <artifactId>test</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>test</name>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

  <dependencies>
  </dependencies>

  <build>
    <pluginManagement>
      <plugins>
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-jar-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

代码如下: 

package cn.edu.nuc.test;

public class User {
    public int balance = 20;

    public boolean pay(int amount) {
        if (balance < amount) {
            return false;
        }
        balance -= amount;
        return true;
    }
}

然后使用mvn install 将test.jar安装到本地仓库。

2)tftest工程:

首先引入test依赖

<dependency>
    	<groupId>cn.edu.nuc</groupId>
		<artifactId>test</artifactId>
		<version>0.0.1-SNAPSHOT</version>
</dependency>

然后,添加UserAspect类:

package a.b.c.tftest.aspectj;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class UserAspect {
    @Pointcut("execution(* cn.edu.nuc.test.*.*(..))")
    public void modelLayer() {
    }

    @Around("modelLayer()")
    public Object logProfile(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        Object result = joinPoint.proceed();
        System.out.println("[userAspect]方法: 【" + joinPoint.getSignature() + "】结束,用时: " + (System.currentTimeMillis() - start));

        return result;
    }
}

最后修改App主类:

public class App {
    public static void main(String[] args) {
        testCompileTime();
    }
    public static void testCompileTime() {
        User user = new User();
        user.pay(10);
    }
}

3)修改插件:

<build>
    <finalName>tftest</finalName>
    <plugins>
        <!--编译后织入-->
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>aspectj-maven-plugin</artifactId>
            <version>1.11</version>
            <configuration>
                <complianceLevel>1.8</complianceLevel>
                <weaveDependencies>
                    <weaveDependency>
                        <groupId>cn.edu.nuc</groupId>
                        <artifactId>test</artifactId>
                    </weaveDependency>
                </weaveDependencies>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>compile</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>2.4</version>
            <configuration>
                <archive>
                    <manifest>
                        <mainClass>a.b.c.tftest.Test</mainClass>
                    </manifest>
                </archive>
                <descriptors>
                    <descriptor>assembly/assembly.xml</descriptor>
                </descriptors>
                <descriptorRefs>  
                    <descriptorRef>jar-with-dependencies</descriptorRef>  
                </descriptorRefs>  
            </configuration>
            <executions>
                <execution>
                    <id>make-assembly</id>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
        </plugin> 
    </plugins>
    
    <pluginManagement>
    <plugins>
        <!--This plugin's configuration is used to store Eclipse 
            m2e settings only. It has no influence on the Maven build itself. -->
        <plugin>
            <groupId>org.eclipse.m2e</groupId>
            <artifactId>lifecycle-mapping</artifactId>
            <version>1.0.0</version>
            <configuration>
                <lifecycleMappingMetadata>
                    <pluginExecutions>
                        <pluginExecution>
                            <pluginExecutionFilter>
                                <groupId>org.codehaus.mojo</groupId>
                                <artifactId>aspectj-maven-plugin</artifactId>
                                <versionRange>[1.0,)</versionRange>
                                <goals>
                                    <goal>test-compile</goal>
                                    <goal>compile</goal>
                                </goals>
                            </pluginExecutionFilter>
                            <action>
                                <execute />
                            </action>
                        </pluginExecution>
                    </pluginExecutions>
                </lifecycleMappingMetadata>
            </configuration>
        </plugin>
    </plugins>
</pluginManagement>
</build>
</project>

然后执行,mvn clean package 最后,运行App主类,输出:

[userAspect]方法: 【boolean cn.edu.nuc.test.User.pay(int)】结束,用时: 1

从输出上看,UserAspect 对 User 进行了织入。而且是在User已经编译后进行的织入。

2.4 【Load-Time Weaving】示例:

最后,我们要介绍的是 LTW 织入,正如 Load-Time 的名字所示,它是在 JVM 加载类的时候做的织入。AspectJ 允许我们在启动的时候指定 agent 来实现这个功能。

这里还是用到了最初的tftest工程,首先,要注释掉之前在 pom.xml 中用于编译期和编译后织入使用的插件,免得影响我们的测试。(一旦我们去掉了 aspectj 的编译插件,那么 .aj 的文件是不会被编译的)

1)main/resource/META-INF下建立aop.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<aspectj>
  <aspects>
    <aspect name="a.b.c.tftest.aspectj.ProfilingAspect"/>
    <weaver options="-verbose -showWeaveInfo">
      <include within="a.b.c.tftest..*"/>
    </weaver>
  </aspects>
</aspectj>

定义了切面类和要织入的目标类范围。

2)切面类:

package a.b.c.tftest.aspectj;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class ProfilingAspect {
    @Pointcut("execution(* a.b.c.tftest.model.*.*(..))")
    public void modelLayer() {
    }

    @Around("modelLayer()")
    public Object logProfile(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        Object result = joinPoint.proceed();
        System.out.println("[ProfilingAspect]方法: 【" + joinPoint.getSignature() + "】结束,用时: " + (System.currentTimeMillis() - start));

        return result;
    }
}

目标类:Account.java 同上

 3)App主类:

package a.b.c.tftest;

import a.b.c.tftest.model.Account;

public class App {
    public static void main(String[] args) {
        testCompileTime();
    }
    public static void testCompileTime() {
        Account account = new Account();
        System.out.println("==================");
        account.pay(10);
        account.pay(50);
        System.out.println("==================");

    }
}

4)pom.xml文件:

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>a.b.c</groupId>
  <artifactId>tftest</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>tftest</name>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

  <dependencies>
    <!-- aspectj -->
    <dependency>
       <groupId>org.aspectj</groupId>
       <artifactId>aspectjrt</artifactId>
       <version>1.8.13</version>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.8.13</version>
    </dependency>
  </dependencies>

  <build>
        <finalName>tftest</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>2.4</version>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>a.b.c.tftest.App</mainClass>
                        </manifest>
                    </archive>
                    <descriptors>
                        <descriptor>assembly/assembly.xml</descriptor>
                    </descriptors>
                    <descriptorRefs>  
                        <descriptorRef>jar-with-dependencies</descriptorRef>  
                    </descriptorRefs>  
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin> 
        </plugins>
  </build>
</project>

5) 编译/打包:

代码结构如下,

 使用mvn package打包后,反编译结构如下:

可以看到,编译后没有进行织入。

然后执行:

java -jar ./target/tftest-jar-with-dependencies.jar

输出:

==================

==================

然后执行:

java -javaagent:/Users/knowliu/Documents/mvn_repo/org/aspectj/aspectjweaver/1.8.10/aspectjweaver-1.8.10.jar -jar ./target/tftest-jar-with-dependencies.jar

[AppClassLoader@18b4aac2] info AspectJ Weaver Version 1.8.13 built on Wednesday Nov 15, 2017 at 19:26:44 GMT

[AppClassLoader@18b4aac2] info register classloader sun.misc.Launcher$AppClassLoader@18b4aac2

[AppClassLoader@18b4aac2] info using configuration file:/Users/knowliu/Documents/workspace1/tftest/target/tftest-jar-with-dependencies.jar!/META-INF/aop.xml

[AppClassLoader@18b4aac2] info register aspect a.b.c.tftest.aspectj.ProfilingAspect

[AppClassLoader@18b4aac2] weaveinfo Join point 'method-execution(boolean a.b.c.tftest.model.Account.pay(int))' in Type 'a.b.c.tftest.model.Account' (Account.java:11) advised by around advice from 'a.b.c.tftest.aspectj.ProfilingAspect' (ProfilingAspect.java)

输出:

==================

[ProfilingAspect]方法: 【boolean a.b.c.tftest.model.Account.pay(int)】结束,用时: 1

[ProfilingAspect]方法: 【boolean a.b.c.tftest.model.Account.pay(int)】结束,用时: 0

==================

到这里,就要结束这一小节了,这里顺便再介绍下如果用 maven 跑测试的话怎么搞。

首先,我们往 surefire 插件中加上 javaagent:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.10</version>
    <configuration>
        <argLine>
            -javaagent:/xxx/aspectjweaver-1.8.13.jar
        </argLine>
        <useSystemClassLoader>true</useSystemClassLoader>
        <forkMode>always</forkMode>
    </configuration>
</plugin>

然后,我们就可以用 mvn test 看到织入效果了。还是那句话,不要用 IDE 进行测试,因为 IDE 太“智能”了。

参考:https://javadoop.com/post/aspectj 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

AspectJ使用 的相关文章

随机推荐

  • VMware-Ubuntu安装bochs

    我的运行环境是VMware的Ubuntu 首先大家可以按照CSDN上的教程按照符合自己需求的虚拟机 我在上午还在VMware和virtualBox之间做选择 但是由于已经安装过了VMware 所以我就直接用了VMware 当然了 一千人眼中
  • 功能实现题

    目录 32 如何利用linux的指令来查询一个文件的行数 33 linux下统计一个文件中每个id的出现次数 34 Linux 在多个文件中查找字符串 35 如何查看占用cpu最多进程 36 如何找到 Java 进程中哪个线程占用了大量 C
  • 安装XView库

    空间 MS Windows 95 98 ME NT 2000 XP The file xview 3 2p1 4 18c cygwin tar bz2 in the cygwin directory contains a set of XV
  • 解决django从脚本文件(或其他文件)中导入app中的model时报错xxx.models.DeviceModel doesn‘t declare an explicit app_label

    完整报错 RuntimeError Model class xxxx models DeviceModel doesn t declare an explicit app label and isn t in an application
  • SpringBoot中关闭Mybatis以及RocketMQ日志打印

    SpringBoot工程集成了Mybatis和RocketMQ 也集成了Log4j 项目中自己的日志都可以通过log4j来管理 日志打印通过通过日志级别可以管理 一直很正常 后来项目上线正常稳定运行一段时间后 要求只打印ERROR级别日志
  • mysql drop table 死锁

    1 场景 mysql出现大量的drop table阻塞操作 2 从会话表 processlist 里面和事务表INNODB TRX里面并找不到正在占用锁的会话和事务 3 分析锁信息 INNODB LOCKs 和INNODB LOCK wai
  • 使用 Oracle的存储过程实现数据加密和解密

    我们都知道 几乎所有的数据库都有存储过程 但在实际开发中 它有什么用途了 下面使用Oracle的存储过程 采用Oracle自带的dbms obfuscation toolkit desencrypt对数据进行加密 需要注意的是密码的长度必须
  • Linux网络安全-Zabbix入门(一)

    一 基本概念 1 监控目的 运行情况 提前发现问题 2 监控资源类别 公开 tcp udp 端口 私有 cpu 磁盘 监控一切需要监控的东西 只要能够想到 能够用命令实现的都能用来监控 如果想远程管理服务器就有远程管理卡 比如Dell id
  • springboot后端返回图片,vue前端接收并显示的解决方案

    后端图片数据返回 后端通过二进制流的形式 写入response中 controller层 获取签到二维码 GetMapping sign up pict public void signUpPict Long id Long semId H
  • 【树状数组该回炉重造了】Codeforces Round #813 (Div. 2) E2. LCM Sum (hard version)

    参考题解 题意 T T T 组数据 每组数据给定 l l l 和 r r
  • 一步步实现扫雷

    扫雷 首先去建立三个文件 头文件 game h 用于存放每个函数的声明 源文件1 game c 用于放置每个函数的定义 源文件2 test c 用于实现扫雷的整体逻辑 关于扫雷的实现 首先需要定义棋盘 这里我们实现9 9的棋盘 但是面对用户
  • Zabbix配置SNMP trap告警的例子

    官方文档 3 SNMP 陷阱 1 安装Trap组件包 yum install y net snmp utils net snmp perl net snmp 2 下载并复制接收Trap脚本 wget https sourceforge ne
  • doris-查询原理

    目录 一 查询简介 二 查询流程 1 Query 接收 2 Query Parse 3 Query Analyze 4 Query Rewrite 5 Plan 5 1 Query 单机Plan 5 2 Query 分布式Plan 6 Qu
  • 【bug】antd全局的主题色样式被覆盖,被修改为`antd`默认的主题色

    背景 项目本身修改了主题色 配置如下 umi配置文件 export default theme primary color 2F54EB 全局主色 需要对图片上传组件做封装 并在项目中统一引用 如下 import TdsUpload fro
  • mapengpeng1999@163.com 操作系统4~处理机调度

    处理机调度 1 三级调度体系 1 处理机调度主要是对处理机运行时间进行分配 即 按照一定算法或策略 将处理机运行时间分配给各个并发进程 同时尽量提高处理机的使用效率 2 现代操作系统中 按调度所实现的功能分3种类型 高级调度 中级调度和低级
  • python3 爬取36氪新闻网页

    一个做了反爬的36氪 返回数据恶心 感觉是一堆垃圾 这里只是记录一下爬取过程 一 爬取环境 win10 python3 scrapy 二 爬取过程 1 入口 搜索 2 动态js数据加载 查看下一页操作 3 返回数据 4 请求链接 http
  • Jmeter 数据库压力测试

    一 jmeter本地数据库压力测试 1 将JMeterPlugins Extras jar和JMeterPlugins Standard jar放到apache jmeter 3 0 lib ext目录下 2 在本地打开ServerAgen
  • 操作系统学习(九)进程通信

    一 知识总览 二 定义 进程通信是指进程之间的信息交换 每个进程都拥有自己的内存空间 是相互独立的 这样在每个进程执行时 才不会被其他进程所干扰 三 进程通信的方式 1 共享存储 1 两个进程对共享区的访问必须是互斥的 即在同一时间内 只允
  • C语言实现kafka多线程,【转】c++(11)使用librdkafka库实现kafka的消费实例

    版权声明 本文为博主原创文章 遵循 CC 4 0 by sa 版权协议 转载请附上原文出处链接和本声明 本文链接 https blog csdn net lijinqi1987 article details 76691170 librdk
  • AspectJ使用

    一 AOP介绍 AOP Aspect Oriented Programming 面向切面编程 是一种新的方法论 编程范式 是对传统 OOP Object Oriented Programming 面向对象编程 的补充 旨在通过允许横切关注点