Printemps 5 (v) - AOP

Craftsman - l 2021-09-15 09:59:08
printemps aop


Un.、AOP

1、Introduction

AOP(Aspect Oriented Programming),Programmation orientée tangente.Il utilise une sorte de"Coupe transversale"De la technologie,Disséquer l'intérieur de l'objet déballé,Et encapsuler les comportements communs qui affectent plusieurs classes dans un module réutilisable,Et l'appeler"Aspect",Tangente.Ce qu'on appelle"Tangente",En termes simples, ceux qui n'ont rien à voir avec les affaires,La logique ou la responsabilité qui est invoquée conjointement par les modules d'affaires est encapsulée,Faciliter la réduction des codes dupliqués dans le système,Réduire le couplage entre les modules,Et pour l'opérabilité et la maintenabilité futures.
AOPEst de programmer tous les objets ou une classe d'objets,Le noyau est sans ajouter de code,Ajout de nouvelles fonctionnalités.En fait, il est beaucoup plus utilisé pour développer le cadre lui - même,Dans le projet réel,Pas grand - chose..

Tangente(aspect):Fonctions croisées à réaliser,Est une section ou un champ de modularisation du système.Comme la journalisation.
Point de connexion:L'endroit où la tangente est insérée pendant l'exécution de l'application,Ça pourrait être un appel de méthode,Exception lancée,Ou le champ à modifier.
Notification(Amélioration):Réalisation pratique de la section,Il a informé le système d'un nouveau comportement.Si la notification log contient un code pour mettre en œuvre la Fonction Log,Comme écrire un journal dans un fichier journal. La notification est insérée dans le système d'application au point de connexion .
Point d'entrée: Définit les points de connexion auxquels la notification doit s'appliquer , La notification peut être appliquée à AOP Tout point de connexion supporté par le cadre .Point de connexion(Statique)-->Point d'entrée(Dynamique).
Introduction: Ajouter de nouvelles méthodes et propriétés à la classe .
Objet (s) cible (s):Objet notifié(Objet délégué). Il peut s'agir d'une classe que vous écrivez ou d'une classe tierce .
Objet Proxy: Objet créé après application de la notification à l'objet cible , Le reste du système d'application n'a pas besoin d'être modifié pour supporter les objets proxy .
Tissage: Le processus d'application de la tangente à l'objet cible pour créer un nouvel objet proxy . Le tissage se produit à plusieurs points du cycle de vie de l'objet cible :
①Période de compilation: Les tangentes sont tissées lorsque l'objet cible est compilé , Cela nécessite un compilateur spécial .
② Période de chargement de la classe : La tangente est chargée sur l'objet cible JVM Tricoter quand , Cela nécessite un chargeur de classe spécial .
③Période de fonctionnement: La coupe est tissée pendant que le système d'application fonctionne .

Principes:AOP L'idée centrale du modèle de conception Mode proxy dynamique.

2、CAS

Attention!: Les cas suivants ,C'est plutôtAOP Mise en œuvre de l'agent statique pour ,Compréhension personnelle.
Définir l'objet cible (Objet délégué)

 1 // Définir une interface
 2 public interface ITeacher {
 3 void teach();
 4 int add(int i, int j);
 5 }
 6
 7 // Définir l'objet cible 
 8 public class Teacher implements ITeacher {
 9  @Override
10 public void teach() {
11 System.out.println(" Le professeur est en classe ");
12  }
13
14  @Override
15 public int add(int i, int j) {
16 int add = i + j;
17 System.out.println("Mise en œuvre de l'approche ciblée: Le professeur fait l'addition ,Les résultats sont les suivants::" + add);
18 // int throwable = 10 / 0; Notification des anomalies d'essai 
19 return add;
20  }
21
22 // Méthode propre à l'objet cible , Cette méthode n'est pas une interface et ne peut donc pas être proxy 
23 public void sayHello() {
24 System.out.println(" Le professeur dira hello");
25  }
26
27 }

Écrivez un avis (Pré - notification)

 1 // Pré - notification
 2 public class MyMethodBeforeAdvice implements MethodBeforeAdvice {
 3
 4 // method:Par Objet Proxy Méthode appelée(Approche ciblée)
 5 // objects:Par Objet Proxy Paramètres d'entrée de la méthode appelée (Paramètres)
 6 // target:Objet (s) cible (s)
 7  @Override
 8 public void before(Method method, Object[] objects, Object target) throws Throwable {
 9 System.out.println("Pré - notification=====1======Nom de la fonction:" + method.getName());
10 System.out.println("Pré - notification=====2======Valeur du paramètre:" + JSON.toJSONString(objects));
11 System.out.println("Pré - notification=====3====== Valeur de l'objet :" + JSON.toJSONString(target));
12  }
13
14 }

Configuration application.xml

 1 <!-- Configurer l'objet cible -->
 2 <bean id="teacher" class="com.lx.spring.day1.Teacher"/>
 3
 4 <!-- Configurer les notifications préalables -->
 5 <bean id="myMethodBeforeAdvice" class="com.lx.spring.day1.MyMethodBeforeAdvice"/>
 6
 7 <!-- Configurer les objets proxy -->
 8 <bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
 9 <!-- 1. Spécifiez l'objet cible à représenter -->
10 <property name="target" ref="teacher"/>
11
12 <!-- 2. Spécifiez l'ensemble d'interface à proxy -->
13 <property name="proxyInterfaces">
14 <list>
15 <value>com.lx.spring.day1.ITeacher</value>
16 </list>
17 </property>
18
19 <!-- 3. Spécifiez les notifications à tisser -->
20 <property name="interceptorNames">
21 <list>
22 <value>myMethodBeforeAdvice</value>
23 </list>
24 </property>
25 </bean>
 1 // Catégorie d'essai
 2 public class Main {
 3 public static void main(String[] args) {
 4 ApplicationContext app = new ClassPathXmlApplicationContext("app1.xml");
 5 // Obtenir l'objet proxy
 6 ITeacher iTeacher = (ITeacher) app.getBean("proxyFactoryBean");
 7 // Méthode d'exécution de l'objet cible par l'intermédiaire de l'objet proxy 
 8 int add = iTeacher.add(1, 2);
 9  }
10 }
11
12 // Pré - notification=====1======Nom de la fonction:add
13 // Pré - notification=====2======Valeur du paramètre:[1,2]
14 // Pré - notification=====3====== Valeur de l'objet :{}
15 // Mise en œuvre de l'approche ciblée: Le professeur fait l'addition ,Les résultats sont les suivants::3

Analyse des principes:Dans le cas, Le but est de comprendre ProxyFactoryBeanC'estBeanCe qui s'est passé? Il y a un préavis , Appelé avant la méthode cible ( Les résultats de l'impression montrent également que ).
Alors,AvecMode agent statiquePas difficile à comprendre., Comprendre brièvement l'implémentation ci - dessus comme suit , Voir le code source pour plus de détails .

 1 // Objet Proxy,Agent statique
 2 public class ProxyFactoryBean implements ITeacher { // 2. Spécifiez l'ensemble d'interface à proxy , Les interfaces à implémenter
 3 // Objet (s) cible (s), Agrégation par interface 
 4 private Teacher target;
 5 // Pré - notification
 6 private MethodBeforeAdvice methodBeforeAdvice;
 7
 8 // 3. Spécifiez les notifications à tisser , C'est - à - dire le code à exécuter lors de l'exécution de la méthode objet cible 
 9 public void setMethodBeforeAdvice(MethodBeforeAdvice methodBeforeAdvice) {
10 this.methodBeforeAdvice = methodBeforeAdvice;
11  }
12
13 public ProxyFactoryBean(Teacher teacher) { // 1. Spécifiez l'objet cible à représenter 
14 this.target = teacher;
15  }
16
17  @Override
18 public void teach() {
19
20  }
21
22 // Rédaction de la méthode de substitution 
23  @Override
24 public int add(int i, int j) {
25 try {
26 // 1. Si la notification préalable est définie , Exécuter la notification préalable 
27 if (methodBeforeAdvice != null) {
28 Method method = ITeacher.class.getMethod("add", int.class, int.class);
29 List<Object> objectList = new ArrayList<>();
30  objectList.add(i);
31  objectList.add(j);
32 Object[] objects = objectList.toArray();
33
34  methodBeforeAdvice.before(method, objects, target);
35  }
36
37 // 2.Mise en œuvre de l'approche ciblée
38 return target.add(i, j);
39
40 // 3. Si un post - avis est défini , Effectuer une notification post érieure 
41 } catch (Throwable e) {
42  e.printStackTrace();
43  }
44 return 0;
45  }
46 }
 1 // Catégorie d'essai
 2 public class Main {
 3 public static void main(String[] args) {
 4 // Créer un objet Proxy, Passer également l'objet cible créé comme paramètre , Qui représente .
 5 ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean(new Teacher());
 6 // Définir une notification préalable 
 7 proxyFactoryBean.setMethodBeforeAdvice(new MyMethodBeforeAdvice());
 8 // Méthode d'exécution de l'objet cible par l'intermédiaire de l'objet proxy .
 9 proxyFactoryBean.add(1, 4);
10  }
11 }
12
13 // Pré - notification=====1======Nom de la fonction:add
14 // Pré - notification=====2======Valeur du paramètre:[1,3]
15 // Pré - notification=====3====== Valeur de l'objet :{}
16 // Mise en œuvre de l'approche ciblée: Le professeur fait l'addition ,Les résultats sont les suivants::4

3、 Catégorie de notification

À l'exception des notifications préalables utilisées dans les cas ,Spring Les avis suivants sont également fournis :

Type de notification
Interface
Description
Pré - notification
org.springframework.aop.MethodBeforeAdvice
Appelé avant la méthode cible
Post - notification
org.springframework.aop.AfterReturningAdvice
Appelé après la méthode cible
Notification surround
org.aopalliance.intercept.MethodInterceptor
Intercepter l'appel à la méthode cible
Avis d'exception
org.springframework.aop.ThrowsAdvice
Appelé lorsque la méthode cible lance une exception
Avis d'introduction
org.springframework.aop.support.NameMatchMethodPointcutAdvisor
Vous pouvez spécifier un point d'entrée

Pré - notification: L'interface permet d'obtenir Approche ciblée, Paramètres et objets cibles Une chance. La seule façon pour cette interface d'empêcher l'invocation de la méthode cible est de lancer une exception ou (System.exit()).
Post - notification: Similaire à la notification préalable .
Notification surround: Cette notification contrôle si la méthode cible est réellement appelée .Adoptioninvocation.proceed()Méthode d'appel. Cette notification peut contrôler l'objet retourné . Peut renvoyer un avec proceed() La méthode renvoie un objet complètement différent . Mais utilisez - le avec prudence .Faites attention à: Lors de la configuration des notifications , Spécifiez les notifications à tisser , L'ordre de rotation est différent , Affecte la séquence d'exécution .
Avis d'exception: L'interface est identitaire (tag)Interface,Il n'y a aucun moyen., Mais la classe qui implémente cette interface doit avoir la forme suivante :

void afterThrowing(Throwable throwable);
void afterThrowing(Method m,Object[] os,Object target,Exception e);
La première méthode n'accepte qu'un seul paramètre : Exception à lancer .
La deuxième méthode accepte l'exception 、La méthode appelée、 Paramètres et objets cibles

Avis d'introduction : Le type de notification précédemment défini est tissé autour de la méthode de l'objet cible appelée . Introduire des notifications pour ajouter de nouvelles méthodes et propriétés à l'objet cible .

Plusieurs avis :

 1 // Pré - notification( Comme indiqué ci - dessus )
 2 public class MyMethodBeforeAdvice implements MethodBeforeAdvice {
 3 // Approche ciblée、Paramètres、Objet (s) cible (s)
 4  @Override
 5 public void before(Method method, Object[] objects, Object target) throws Throwable {
 6 System.out.println("Pré - notification=====1======Nom de la fonction:" + method.getName());
 7 System.out.println("Pré - notification=====2======Valeur du paramètre:" + JSON.toJSONString(objects));
 8 System.out.println("Pré - notification=====3====== Valeur de l'objet :" + JSON.toJSONString(target));
 9  }
10 }
11
12 // Post - notification
13 public class MyAfterReturningAdvice implements AfterReturningAdvice {
14 // object:Valeur de retour de la méthode
15 // method:Approche ciblée
16 // objects:Paramètres
17 // target:Objet (s) cible (s).Note:: L'objet est entré par une notification préalable target
18  @Override
19 public void afterReturning(Object object, Method method, Object[] objects, Object target) throws Throwable {
20 System.out.println("Post - notification=====0======Valeur de retour:" + object);
21 System.out.println("Post - notification=====1======Nom de la fonction:" + method.getName());
22 System.out.println("Post - notification=====2======Valeur du paramètre:" + JSON.toJSONString(objects));
23 System.out.println("Post - notification=====3====== Valeur de l'objet :" + JSON.toJSONString(target));
24  }
25 }
26
27 // Notification surround
28 public class MyMethodInterceptor implements MethodInterceptor {
29 // object: Valeur de retour de la méthode cible 
30  @Override
31 public Object invoke(MethodInvocation invocation) throws Throwable {
32 System.out.println("============Orbite vers l'avant==============");
33 Object object = invocation.proceed(); // Voici la méthode de ciblage 
34 System.out.println("============Surround back==============");
35 return object;
36  }
37 }
38
39 // Avis d'exception
40 public class MyThrowsAdvice implements ThrowsAdvice {
41
42 public void afterThrowing(Method method, Object[] objects, Object target, Exception e) {
43 System.out.println("Avis d'exception=====1======Nom de la fonction:" + method.getName());
44 System.out.println("Avis d'exception=====2======Valeur du paramètre:" + JSON.toJSONString(objects));
45 System.out.println("Avis d'exception=====3====== Valeur de l'objet :" + JSON.toJSONString(target));
46 System.out.println("Avis d'exception=====4======Valeurs aberrantes:" + JSON.toJSONString(e.getMessage()));
47  }
48 }

Après l'exemple ci - dessus et la description des quatre avis ,Je vois.,ProxyFactoryBeanC'est unBeanFactory Créer explicitement la classe centrale de l'objet proxy dans , On peut lui donner Un objet cible à représenter 、 Un ensemble d'interfaces à proxy 、 Un avis à tisser , Il va créer un nouvel objet proxy .

Avis d'introduction (Tangente): Les quatre premières notifications indiquent déjà qu'avant la méthode ciblée , Ou après , Ou l'appel surround . S'il n'est pas possible d'indiquer où la notification doit être appliquée , La notification sera inutile , C'est à ça que servent les points d'entrée .
Les points d'entrée déterminent si une méthode particulière d'une classe particulière satisfait à certaines règles .Si oui, La notification s'applique à cette méthode . La notification d'introduction peut spécifier un point d'entrée ( C'est - à - dire préciser les méthodes d'organisation des notifications ).
Note:: L'introduction de la notification n'est pas comme avant 4 C'est une annonce comme celle - ci . Et l'idée principale est :①Où est - il?(Tangente, Ou comment )Introduction?② Quel type de notification introduire ?
Les règles sont les suivantes::

Symbole
Description
Exemple
Ça correspond
Ne correspond pas
.
Correspond à n'importe quel caractère individuel
setFoo.
setFooB
setFooBar setFooB
+
Correspond une ou plusieurs fois au caractère précédent
setFoo.+
setFooBar setFooB
setFoo
*
Correspond au caractère précédent 0Une ou plusieurs fois
setFoo.*
setFoosetFooB, setFooBar
 
\
Correspond à n'importe quel symbole d'expression régulière
\.setFoo.
bar.setFoo
setFoo

Voici un profil complet application.xml

 1 <!-- Configurer l'objet cible -->
 2 <bean id="teacher" class="com.lx.test.Teacher"/>
 3
 4 <!-- Configurer les notifications préalables -->
 5 <bean id="myMethodBeforeAdvice" class="com.lx.advice.MyMethodBeforeAdvice"/>
 6 <!-- Configurer les notifications post -->
 7 <bean id="myAfterReturningAdvice" class="com.lx.advice.MyAfterReturningAdvice"/>
 8 <!-- Configurer les notifications surround -->
 9 <bean id="myMethodInterceptor" class="com.lx.advice.MyMethodInterceptor"/>
10 <!-- Configurer les notifications d'exception -->
11 <bean id="myThrowsAdvice" class="com.lx.advice.MyThrowsAdvice"/>
12
13 <!-- Configurer les notifications d'importation -->
14 <bean id="pointcutAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
15 <property name="advice" ref="myMethodBeforeAdvice"/>
16 <property name="mappedNames">
17 <list>
18 <value>add*</value> <!-- Oui. add La fonction au début est tissée dans la notification préalable -->
19 <value>del*</value>
20 <value>teach*</value>
21 </list>
22 </property>
23 </bean>
24
25 <!-- Configurer les objets proxy -->
26 <bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
27 <!-- Spécifiez l'objet cible à représenter -->
28 <property name="target" ref="teacher"/>
29
30 <!-- Spécifiez l'ensemble d'interface à proxy -->
31 <property name="proxyInterfaces">
32 <list>
33 <value>com.lx.test.ITeacher</value>
34 </list>
35 </property>
36
37 <!-- Spécifiez les notifications à tisser -->
38 <property name="interceptorNames">
39 <list>
40 <value>myMethodBeforeAdvice</value>
41 <value>myAfterReturningAdvice</value>
42 <value>myMethodInterceptor</value>
43 <value>myThrowsAdvice</value>
44
45 <value>pointcutAdvisor</value>
46 </list>
47 </property>
48 </bean>
 1 // Catégorie d'essai
 2 public class Main {
 3 public static void main(String[] args) {
 4 ApplicationContext app = new ClassPathXmlApplicationContext("beans.xml");
 5 ITeacher iTeacher = (ITeacher) app.getBean("proxyFactoryBean");
 6 int add = iTeacher.add(11, 22);
 7  }
 8 }
 9
10 // Pré - notification=====1======Nom de la fonction:add
11 // Pré - notification=====2======Valeur du paramètre:[11,22]
12 // Pré - notification=====3====== Valeur de l'objet :{}
13 // ============Orbite vers l'avant==============
14 // Pré - notification=====1======Nom de la fonction:add
15 // Pré - notification=====2======Valeur du paramètre:[11,22]
16 // Pré - notification=====3====== Valeur de l'objet :{}
17 // Mise en œuvre de l'approche ciblée: Le professeur fait l'addition ,Les résultats sont les suivants::33
18 // ============Surround back==============
19 // Post - notification=====0======Valeur de retour:33
20 // Post - notification=====1======Nom de la fonction:add
21 // Post - notification=====2======Valeur du paramètre:[11,22]
22 // Post - notification=====3====== Valeur de l'objet :{}
23
24 // row14、15、16 C'est parce que la notification d'importation a été configurée et qu'une autre notification préalable a été exécutée 

4、Résumé

SpringAviser les objets au moment de l'exécution, Créer un agent pendant l'exécution , Aucun compilateur spécial n'est nécessaire .Spring Il y a deux façons de représenter :
Si l'objet cible implémente plusieurs interfaces :SpringUtiliserJDKDejava.lang.reflect.ProxyAgent de classe. Ce genre de Spring Générer dynamiquement une nouvelle classe , Il implémente l'interface requise , Toutes les demandes de notification et d'agent pour l'objet cible sont tissées .
Si l'objet cible n'implémente aucune interface :SpringUtiliserCGLIB La Bibliothèque génère une sous - classe de l'objet cible . Attention à l'utilisation de cette méthode :
① Créer un proxy pour une interface est préférable à créer un proxy pour une classe , Parce qu'il en résulte un système de couplage plus lâche . Les agents de classe sont des bibliothèques de classe tierces qui permettent aux systèmes existants ou qui ne peuvent pas implémenter d'interfaces d'être informés de la même façon , Cette approche devrait être alternative .
②Marqué commefinal La méthode ne peut pas être notifiée .Spring Est de générer une sous - classe pour la classe cible , Toute méthode nécessitant une notification doit être réécrite , Tissez l'avis dans .final La méthode n'est pas autorisée à passer outre .
SpringC'est fait.aop Interface Union .SpringSeuls les points de connexion de la méthode sont pris en charge, Aucun point d'accès à la propriété n'est fourni .Spring L'idée est que l'interception des attributs a brisé l'encapsulation . Le concept orienté objet est que l'objet gère le travail lui - même , D'autres objets ne peuvent obtenir des résultats que par des appels de méthode .
Demande.:Dis - le.SpringDeaopMoyenne, Quand vous passez par l'objet proxy aopQuand,AcquisProxyFactoryBeanQuel genre??
Réponse: Renvoie un objet proxy ,Si L'objet cible implémente l'interface ,EtSpringUtiliserjdkAgent dynamiqueTechnique;Si L'objet cible n'implémente pas l'interface ,EtSpringUtiliserCGLIBTechnique.

 

版权声明
本文为[Craftsman - l]所创,转载请带上原文链接,感谢
https://javamana.com/2021/09/20210915095656844G.html

  1. L'arrivée de marchandises sèches, l'entretien d'emploi Java 12 grandes usines ont réussi à changer d'emploi,
  2. Multiple postures for handling container time in k8s environment
  3. Echarts remove left Gap, Blank
  4. Hotspot Weekly | zoom $100 million, docker fees, $38 billion Data bricks
  5. JsonMappingException: No serializer found for class org.apache.ibatis.executor.loader.javassist.JavassistProxyFactory...
  6. Java. Security. Securerandom source code analysis Java. Security. EGD = file: / dev /. / urandom
  7. When using IntelliJ idea, jump directly and quickly from the mapper interface to mapper.xml
  8. When idea writes SQL in mybatis XML, the solution to the problems of table name, field and red reporting
  9. Spring cloud integrates Nacos
  10. 应届毕业生Java笔试题目,2021大厂Java社招最全面试题,
  11. Liver explosion! Take you to understand Hadoop serialization
  12. linux系列之:告诉他,他根本不懂kill
  13. java版gRPC实战之三:服务端流
  14. RabbitMQ核心知识总结!
  15. linux系列之:告诉他,他根本不懂kill
  16. java版gRPC实战之三:服务端流
  17. RabbitMQ核心知识总结!
  18. 10天拿到字节跳动Java岗位offer,学习Java开发的步骤
  19. 10天拿到字节跳动Java岗位offer,Java知识点思维导图
  20. Résumé des connaissances de base de rabbitmq!
  21. 10天拿到字節跳動Java崗比特offer,Java知識點思維導圖
  22. 10 jours pour obtenir un Byte Jump Java post offer, Java Knowledge point Mind Map
  23. 10 jours pour obtenir l'octet Jump Java post offer, apprendre les étapes du développement Java
  24. Java version of gppc Reality Three: server side stream
  25. Linux Series: Dites - lui qu'il ne connaît pas kill du tout
  26. "Data structure and algorithm" of front end -- binary search
  27. 2020-2021京东Java面试真题解析,如何才能通过一线互联网公司面试
  28. 13 SpringBoot整合RocketMQ实现过滤消息-根据SQL表达式过滤消息
  29. 12 SpringBoot整合RocketMQ实现过滤消息-根据TAG方式过滤消息
  30. 11 SpringBoot整合RocketMQ实现事务消息
  31. 11 springboot Consolidated rocketmq Implementation transaction message
  32. 12 springboot Consolidated rocketmq Implements Filtering messages - Filtering messages according to tag method
  33. 13 springboot Consolidated rocketmq Implementation Filtering messages - Filtering messages according to SQL expressions
  34. linux系列之:告诉他,他根本不懂kill
  35. (1)java Spring Cloud+Spring boot企业快速开发架构之微服务是什么?它的优缺点有哪些?
  36. Oracle 检查 DATE 列 RANGE 分区表已有分区的最大日期时间
  37. ConcurrentHashMap--原理
  38. 2020 - 2021 JD Java interview Real question Analysis, How can interview through First - Line Internet Company
  39. Concurrenthashmap - - Principes
  40. Oracle vérifie l'heure de date maximale d'une partition existante dans la colonne date
  41. Docker Compose 实践及梳理
  42. Qu'est - ce qu'un microservice pour Java Spring Cloud + Spring Boot Enterprise Quick Development architecture?Quels sont ses avantages et ses inconvénients?
  43. Plus sign interview knowledge points in Java
  44. Pratique et organisation de la composition des dockers
  45. Linux Series: Dites - lui qu'il ne connaît pas kill du tout
  46. Convenient CSS and jQuery drop-down menu solution
  47. Linux analog packet loss rate
  48. Redis:我是如何与客户端进行通信的
  49. 15 useful cron work examples commonly used by Senior Linux system administrators
  50. 24个 JavaScript 循环遍历方法,你都知道吗?
  51. Reading notes of JavaScript advanced programming (3rd Edition) 4
  52. 30分钟学会Docker里面开启k8s(Kubernetes)登录仪表盘(图文讲解)
  53. 24 méthodes de traversée de boucle Javascript, vous savez?
  54. 30 minutes pour apprendre à ouvrir le tableau de bord k8s (kubernets) dans le docker (explication graphique)
  55. Redis: comment je communique avec les clients
  56. Wsl2: Windows native Linux subsystem
  57. 30分钟学会Docker里面开启k8s(Kubernetes)登录仪表盘(图文讲解)
  58. Python高级用法总结(8)-函数式编程
  59. 261页前端面试题宝典,JavaScript变量声明提升
  60. The performance of JVM and Java applications of the same version differs by 30% on X86 and aarch64 platforms. Why?