Spring框架 —— AOP面向切面编程

news2024/12/27 15:05:39

前言

        前面荔枝已经梳理了Spring框架中的IOC部分的知识,接下来荔枝继续梳理Spring框架的另一大重点:AOP面向切面编程。在这篇文章中,荔枝会着重弄清楚AOP的概念并对实现AOP的两种方式进行梳理,同时荔枝也会相应给出代码样例。毕竟荔枝始终觉得只有文字的描述是苍白无力的,有代码其实理解起来会更快哈哈哈。


文章目录

前言

一、代理模式和AOP概念

1.1 代理模式

1.2 AOP概念

二、基于注解方式实现AOP

2.1 动态代理分类和依赖引入

2.2 切入点表达式以及五种通知类型 

2.3 重用切入点表达式

2.4 切面的优先级 

三、基于XML方式实现AOP

总结


一、代理模式和AOP概念

在开发中我们常常考虑将不同功能的程序分离出来降低系统的耦合度,也就是解耦操作。也就是说,通常在针对一些附加功能的时候我们需要一种方法把子类中重复的代码注入到父类中。

1.1 代理模式

        代理模式是设计模式中的一种,属于结构型模式。它的作用就是通过提供一个代理类,让我们在调用目标方法的时候,不再是直接对目标方法进行调用,而是通过代理类间接调用。让不属于目标方法核心逻辑的代码从目标方法中剥离出来一一解耦。调用目标方法时先调用代理对象的方法,减少对目标方法的调用,同时让附加功能能够集中在一起也有利于统一维护。代理主要分为两种:静态代理和动态代理。

静态代理

静态代理解决了高耦合的问题,通过一个代理类构造方法获取执行类的对象并调用其add方法实现接口功能,并在前后加上附加功能比如日志文件。

package com.crj.aop;

public class CalculatorStaticProxy implements Calaulator{
    //将代理目标对象传递进来
    private Calaulator calaulator;
    public CalculatorStaticProxy(Calaulator calaulator) {
        this.calaulator = calaulator;
    }
    @Override
    public int add(int i, int j) {
        //输出日志
        System.out.println("[日志]add方法开始,参数是:i="+i+"、j="+j);
        calaulator.add(i,j);
        //输出日志
        System.out.println("[日志]add方法结束");
        return 0;
    }
}

静态代理确实实现了解耦,但是由于代码都写死了,完全不具备任何的灵活性。就拿日志功能来说,将来其他地方也需要附加日志,那还得声明多个静态代理类,那就产生了大量重复的代码,日志功能还是分散的,没有统一管理。

进一步的需求:将日志功能集中到一个代理类中,将来有任何日志需求,都通过这一个代理类来实现,这就需要使用动态代理技术了。

动态代理

Java种支持使用Proxy.newProxyInstance(classLoader,interfaces,invocationHandler)来实现接口的动态代理,需要三个参数:需代理类的类加载器、需代理类的实现接口数组和重写的代理方法。其中第三个参数实现目标的代理方法借助InvocationHandler类种的invoke方法来实现。

动态代理类

package com.crj.spring6.aop;

import java.lang.reflect.Array;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;

//实现动态代理
public class ProxyFactory {
    //目标对象
    private Object target;
    public ProxyFactory(Object target) {
        this.target = target;
    }

    //返回代理对象
    public Object getProxy(){
        /**
         * 参数说明
         * Proxy.newProxyInstance()方法
         * 1.类加载器ClassLoader loader 加载动态生成代理类的类加载器
         * 2.Class[] interfaces 目标对象实现的所有接口的class类型数组
         * 3.IncocationHandler 设置代理对象实现目标对象方法的过程
         */
        //类加载器
        ClassLoader classLoader = target.getClass().getClassLoader();
        //目标对象实现的所有接口的class类型数组
        Class<?>[] interfaces = target.getClass().getInterfaces();
        //使用匿名内部类来实现接口
        InvocationHandler invocationHandler = new InvocationHandler(){
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                /**
                 * 参数
                 * 第一个参数:代理对象
                 * 第二个参数:需要重写的目标对象的方法
                 * 第三个参数:method方法里面的参数
                 */
                //方法调用之前输出日志
                System.out.println("[动态代理日志]"+method.getName()+"参数:"+ Arrays.toString(args));
                //调用目标方法
                Object result = method.invoke(target, args);
                //方法调用之后输出日志
                System.out.println("[动态代理日志]"+method.getName()+"结果:"+ result);

                return result;
            }
        };
        return Proxy.newProxyInstance(classLoader,interfaces,invocationHandler);
    }

}

测试类

package com.crj.spring6.aop;

public class TestCal {
    public static void main(String[] args) {
        //创建代理对象
        ProxyFactory proxyFactory = new ProxyFactory(new CalculatorImpl());
        //获取代理对象
        Calaulator proxy = (Calaulator)proxyFactory.getProxy();
        proxy.add(1,2);
    }
}

1.2 AOP概念

        AOP(Aspect Oriented Programming)是一种设计思想,是软件设计领域中的面向切面编程,它是面向对象编程的一种补充和完善,它以预编译方式和运行期动态代理方式实现,在不修改源代码的情况下,给程序动态统一添加额外功能。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率,使程序是松耦合的。

相关术语

横切关注点

分散在各个模块中解决同一类问题的,或者说是从每个方法种抽取出来的同类非核心也无就乘坐横切关注点,比如:日志管理、用户验证等。换句话说,有几个附加功能就有几个横切关注点。

通知(增强)

每一个横切关注点上要做的事情都需要写一个方法来实现,这样的方法就叫通知方法,有五种通知类型:

  • 前置通知:在被代理的目标方法前执行
  • 返回通知:在被代理的目标方法成功结束后执行
  • 异常通知:在被代理的目标方法异常结束后执行
  • 后置通知:在被代理的目标方法最终结束后执行
  • 环绕通知:使用try..catch.finally结构围绕整个被代理的目标方法,包括上面四种通知对应的所有位置

切面

封装通知方法的类

目标

被代理的目标对象

代理

向目标对象应用通知之后创建的代理对象

连接点

允许使用通知的地方

切入点 

        定位连接点的方式。每个类的方法中都包含多个连接点,所以连接点是类中客观存在的事物(从逻辑上来说)。如果把连接点看作数据库中的记录,那么切入点就是查询记录的SQL语句。Spring的AOP技术可以通过切入点定位到特定的连接点。通俗说,要实际去增强的方法切点通过org.springframework.aop.Pointcut接口进行描述,它使用类和方法作为连接点的查询条件。


二、基于注解方式实现AOP

我们知晓,AOP面向切面编程的底层也是通过动态代理来实现的,所以对于动态代理我们除了了解基本的代理分类之外还需要明确AOP种如何使用动态代理的方式来实现AOP。

2.1 动态代理分类和依赖引入

        AOP动态代理有两种:JDK动态代理和CGlib动态代理,分别对应有接口和无接口的动态代理。JDK动态代理会生成接口实现类的代理对象,而CGlib动态代理是通过继承被代理对象并重写的方式实现的。 

pom.xml文件

项目的环境中即pom.xml文件中需要引入aop和aspects依赖。

<?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>com.crj</groupId>
    <artifactId>spring6</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <modules>
        <module>spring-first</module>
        <module>spring6-ioc-xml</module>
        <module>spring6-ioc-annotation</module>
        <module>spring6-aop</module>
    </modules>

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

    <!--    此处引入spring依赖-->
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>6.0.2</version>
        </dependency>
        <!--  引入junit依赖-->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.6.3</version>
        </dependency>
        <!--    引入log4j2的依赖-->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.19.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j2-impl</artifactId>
            <version>2.19.0</version>
        </dependency>
        <dependency>
            <groupId>jakarta.annotation</groupId>
            <artifactId>jakarta.annotation-api</artifactId>
            <version>2.1.1</version>
        </dependency>
        <!--spring aop依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>6.0.2</version>
        </dependency>
        <!--spring aspects依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>6.0.2</version>
        </dependency>

    </dependencies>
</project>

除了环境总配置之外,还需要在项目中resources目录下的xml文件中配置开启组件扫描和aspectj自动代理。

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

    <!--开启组件扫描-->
    <context:component-scan base-package="com.crj.spring6.aop.annotationAop"></context:component-scan>
    <!--开启aspectj自动代理,为目标对象生成代理-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

2.2 切入点表达式以及五种通知类型 

在配置完环境依赖后,我们需要在切面类中定义通知的类型并设置切入点,Java中同个定义了几个注解来实现设置通知类型:

  • 前置通知 @Before(value = “切入点表达式”)
  • 返回通知 @AfterReturning
  • 异常通知 @AfterThrowing
  • 后置通知 @After()
  • 环绕通知 @Around()

需要注意切入点表达式的结构:execution(权限修饰符 方法返回值类型 切入点方法的全类名.方法名(方法参数列表)) 

前置通知 

package com.crj.spring6.aop.annotationAop;

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

import java.util.Arrays;

//切面类
@Aspect  //切面类
@Component  //IOC容器
public class LogAspect {

    //设置切入点和通知类型
    //通知类型:
    //    前置通知 @Before(value = “切入点表达式”)
    //    返回通知 @AfterReturning
    //    异常通知 @AfterThrowing
    //    后置通知 @After()
    //    环绕通知 @Around()

    //前置通知
    @Before(value = "execution(public int com.crj.spring6.aop.annotationAop.CalculatorImpl.add(..))")
    public void beforeMethod(JoinPoint joinPoint){
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        System.out.println("Logger-.->前置通知,方法名:"+methodName+",参数:"+ Arrays.toString(args));
    }
}

返回通知

返回通知中我们在注解中可以通过returning属性获取执行目标增强方法后的返回值。

package com.crj.spring6.aop.annotationAop;

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

import java.util.Arrays;

//切面类
@Aspect  //切面类
@Component  //IOC容器
public class LogAspect {

    //返回通知
    @AfterReturning(value = "execution(* com.crj.spring6.aop.annotationAop.CalculatorImpl.*(..))",returning = "result")
    public void afterReturnMethods(JoinPoint joinPoint,Object result){
        //增强方法的名字
        String methodName = joinPoint.getSignature().getName();
        //增强方法的参数
        Object[] args = joinPoint.getArgs();
        //增强方法的返回值 result
        System.out.println("Logger-.->返回通知,方法名:"+methodName+",参数:"+ Arrays.toString(args)+",目标方法的返回值:"+result);
    }
    
}

异常通知

 在异常通知中可以通过throwing属性获得目标增强方法执行异常抛出的信息。

package com.crj.spring6.aop.annotationAop;

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

import java.util.Arrays;

//切面类
@Aspect  //切面类
@Component  //IOC容器
public class LogAspect {

    //异常通知
    @AfterThrowing(value = "execution(* com.crj.spring6.aop.annotationAop.CalculatorImpl.*(..))",throwing = "ex")
    public void afterThrowingMethod(JoinPoint joinPoint,Throwable ex){
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        System.out.println("Logger-.->异常通知,方法名:"+methodName+",参数:"+ Arrays.toString(args)+",异常方法的信息:"+ex);
    }
}

环绕通知 

环绕通知需要注意的是@Around注解下的方法参数类型选择的是ProceedingJoinPoint,借助该类型对象的proceed的方法来调用目标函数。

package com.crj.spring6.aop.annotationAop;

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

import java.util.Arrays;

//切面类
@Aspect  //切面类
@Component  //IOC容器
public class LogAspect {

    //环绕通知
    @Around(value = "execution(* com.crj.spring6.aop.annotationAop.CalculatorImpl.*(..))")
    public Object aroundMethod(ProceedingJoinPoint joinPoint){
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        String argString = Arrays.toString(args);
        Object result = null;
        try{
            System.out.println("环绕通知——>目标方法之前执行");
            //调用目标方法
            result = joinPoint.proceed();
            System.out.println("环绕通知——>目标方法返回值之后执行");

        }catch (Throwable throwable){
            System.out.println("环绕通知——>目标方法出现异常之后执行");

        }finally {
            System.out.println("环绕通知——>后置通知");
        }
        return result;
    }
}

2.3 重用切入点表达式

通过上述的四个通知例子我们发现,切入点表达式除了在一些特殊的场景需求下,其余的情况总是一样的,为了避免代码的冗余,我们可以通过重用切入点表达式来提高程序的可复用性。

//前置通知
@Before(value = "Pointcut()")
public void beforeMethod(JoinPoint joinPoint){
    String methodName = joinPoint.getSignature().getName();
    Object[] args = joinPoint.getArgs();
    System.out.println("Logger-.->前置通知,方法名:"+methodName+",参数:"+ Arrays.toString(args));
} 

@Pointcut(value = "execution(* com.crj.spring6.aop.annotationAop.CalculatorImpl.*(..))")
public void pointCut(){}

注意:上述是在同一个切面中的定义,在不同的切面中的话需要在通知的切入点表达式加上重用函数的全类名 

2.4 切面的优先级 

相同目标方法上同时存在多个切面时,可以通过切面的优先级控制切面的内外嵌套顺序:

  • 优先级高的切面:外面
  • 优先级低的切面:里面

主要是通过使用@Order注解来设定切面的优先级:

  • @Order(较小的数):优先级高
  • @Order(较大的数):优先级低 

三、基于XML方式实现AOP

这里只需要将前面的注解部分去掉,并通过一个xml文件来配置好切面类的设置即可。

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

    <!--开启组件扫描-->
    <context:component-scan base-package="com.crj.spring6.aop.xmlaop"></context:component-scan>

    <!--配置AOP的五种通知类型-->
    <aop:config>
        <!--配置切面类-->
        <aop:aspect ref="logAspect">
            <!--配置切入点-->
            <aop:pointcut id="pointcut" expression="execution(* com.crj.spring6.aop.annotationAop.CalculatorImpl.*(..))"/>
            <!--配置五种通知类型-->
            <!--前置-->
            <aop:before method="beforeMethod" pointcut-ref="pointcut"></aop:before>
            <!--后置-->
            <aop:after method="aroundMethod" pointcut-ref="pointcut"></aop:after>
            <!--返回-->
            <aop:after-returning method="afterReturnMethods" returning="result" pointcut-ref="pointcut"></aop:after-returning>
            <!--异常-->
            <aop:after-throwing method="afterThrowingMethod" throwing="ex" pointcut-ref="pointcut"></aop:after-throwing>
            <!--环绕-->
            <aop:around method="aroundMethod" pointcut-ref="pointcut"></aop:around>
        </aop:aspect>
    </aop:config>
</beans>

总结

        哈哈,学到这里荔枝总算把最最重要的部分学完了,马上就可以上手项目实操了,真实有点迫不及待呢哈哈哈哈哈哈~~~希望荔枝梳理的会对有需要的小伙伴有帮助,接下来荔枝可能会继续学习和梳理并总结产出,在暑假结束后荔枝也会对项目进行总结和复盘,希望那时的荔枝会离大佬更进一步哈哈哈哈哈哈。

今朝已然成为过去,明日依然向往未来!我是小荔枝,在技术成长的路上与你相伴,码文不易,麻烦举起小爪爪点个赞吧哈哈哈~~~ 比心心♥~~~

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

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

相关文章

Java面向对象的三大特征

Java面向对象的三大特征 java面向对象的三大特征&#xff1a;“封装、继承、多态”。更多Java技术知识&#xff0c;请登陆疯狂软件教育官网。微信搜索微信号&#xff1a;疯狂软件&#xff0c;参加2015年优惠活动&#xff0c;有机会获得优惠劵和代金劵。 以本文为例&#xff0c…

【腾讯云 Cloud studio 实战训练营】搭建Next框架博客——抛开电脑性能在云端编程(沉浸式体验)

文章目录 ⭐前言⭐进入cloud studio工作区指引&#x1f496; 注册coding账号&#x1f496; 选择cloud studio&#x1f496; cloud studio选择next.js&#x1f496; 安装react的ui框架&#xff08;tDesign&#xff09;&#x1f496; 安装axios&#x1f496; 代理请求跨域&#x…

价格管控有哪些有效的方法

品牌在面对线上店铺的低价、窜货时&#xff0c;需要及时进行干预治理&#xff0c;否则低价效应会蔓延&#xff0c;会有越来越多的店铺跟价&#xff0c;导致渠道更加混乱&#xff0c;但是管控价格也非一时之事&#xff0c;需要品牌按流程治理。 力维网络有多年价格管控经验&…

OpenLayers入门,OpenLayers如何加载TMS瓦片服务,以腾讯地图TMS图层为例

专栏目录: OpenLayers入门教程汇总目录 前言 本章讲解OpenLayers如何加载TMS图层服务到地图上,TMS图层介绍请参考《Gis开发入门,OpenLayers、Leaflet、Maplibre-gl和Cesiumjs地图引擎介绍以及几种地图服务vms、vmts、TMS和XYZ介绍》,下面介绍一下TMS图层和XYZ图层的区别。…

Halcon GPU算法加速测试

Halcon GPU算法加速测试 基本流程 官方加速程序&#xff1a;compute_devices.hdev 1.获取显示本机显卡信息 2.打开、激活设备、准备测试数据 3.GPU 循环测试执行 (affine_trans_image) 4.GPU 循环测试执行(affine_trans_image) 数据传入传出 5.CPU 循环测试执行(affine_…

mysql主从配置及搭建(gtid方式)

一、搭建主从-gtid方式 搭建步骤查看第一篇。bin-log方式。可以进行搭建1.1 gtid和二进制的优缺点 使用 GTID 的主从复制优点&#xff1a; 1、简化配置&#xff1a;使用 GTID 可以简化主从配置&#xff0c;不需要手动配置每个服务器的二进制日志文件和位置。 2、自动故障转移…

【Docker】Docker中安装MySQL数据库

文章目录 1. 前言2. Docker中安装MySQL服务2.1. 查看可用的MySQL版本2.2. 拉取MySQL镜像2.3. 查看本地镜像2.4. 运行容器2.5. 查看正在运行的容器2.6. 查看容器内部2.7. 授权root远程登录2.8. 在宿主机连接到容器的MySQL2.9. 用Navicat连接容器的MySQL 3. 如果是MySQL8.0可能需…

vue项目开发常用工具类

防止重复造轮子&#xff0c;将经常用的函数进行记录&#xff0c;也参考网上的并一起进行记录&#xff0c;后续会持续更新常用到的函数工具类方法&#x1f609;&#x1f609; /** 验证手机号是否合格* true--说明合格*/ export function isPhone(phoneStr) {let myreg /^[1][3,…

VMware vCenter Server Appliance VCSA 备份还原

vCenter是VMware管理员的常备工具&#xff0c;要保护它的安全&#xff0c;我们可以借助vCenter备份还原方式来达成目的。 怎么备份vCenter 7.0&#xff1f; vCenter备份包括vCenter Server核心配置、资源清册和历史数据&#xff0c;如统计信息、事件和任务。接下来&#xff0…

【LeetCode每日一题】——1572.矩阵对角线元素的和

文章目录 一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目示例】六【题目提示】七【解题思路】八【时间频度】九【代码实现】十【提交结果】 一【题目类别】 矩阵 二【题目难度】 简单 三【题目编号】 1572.矩阵对角线元素的和 四【题目描述】 给你一…

HTTP之Session、Cookie 与 Application

目录 简介cookiecookie生命周期 sessionsession生命周期 HTTP cookies示例application 简介 cookie、seesion、application三个都会缓存我们用户状态的数据&#xff0c;使得我们在浏览器访问网站时可以更快速的获取到信息。 主要原因在于HTTP协议是无状态的&#xff0c;我们每…

IO流(4)- 序列化流与反序列化流

目录 1. 序列化流与反序列化流的基本介绍 2. 序列化流的基本用法&#xff1f; 3. 序列化流的作用&#xff1f; 4. 反序列化流的基本用法&#xff1f; 5. 反序列化流的作用 6. 序列化流与反序列化流使用时需要注意的细节&#xff08;非常重要&#xff09; 6.1 被序列化的…

90%的测试工程师是这样使用Postman做接口测试的

一&#xff1a;接口测试前准备 接口测试是基于协议的功能黑盒测试&#xff0c;在进行接口测试之前&#xff0c;我们要了解接口的信息&#xff0c;然后才知道怎么来测试一个接口&#xff0c;如何完整的校验接口的响应值。 那么问题来了&#xff0c;那接口信息从哪里获取呢&…

中国AI大模型峰会“封神之作”!开发者不容错过这场夏季盛会

年度最强大模型顶会来袭&#xff01;喊话中国数百万AI开发者&#xff0c;速来&#xff01; 硬核来袭&#xff01;中国AI大模型峰会“封神之作”&#xff0c;开发者们不容错过! 前瞻大模型发展趋势&#xff0c;紧跟这场大会&#xff01; 中国科技超级碗&#xff0c;大模型最新前…

SpringCloud Alibaba分布式集群要点

1、可通过nginxkeepalived实现nginx高可用集群。 2、nacos集群&#xff0c;在nacos/conf/cluster.conf配置IP:8848,nginx中配置nacos负载均衡&#xff0c;yml文件使用其对应域名即可。 注&#xff1a;服务器之间内网不通 举例&#xff1a;腾讯服务器之间就存在内网不通的现象…

关于bigemap在土地行业的一些应用

选择Bigemap的原因&#xff1a; 由于我们是国营企业单位&#xff0c;管理六万多亩的国有土地&#xff0c;必须要有这样的软件套图 客户之前用的谷歌&#xff0c;后来不能访问了&#xff0c;通过百度搜索到这款软件 使用场景&#xff1a; 使用软件一般都用于套坐标以及空间规…

未来将有可能是元宇宙发展的数字化时代

近年来&#xff0c;元宇宙环境的概念近年来引起了广泛关注&#xff0c;并引发了巨大的舆论浪潮。然而&#xff0c;经济形式的放缓和行业向人工智能的转变所带来的挫折引发了人们对这一 " 雄心勃勃 " 的概念的可行性和时机的质疑。 很明显&#xff0c;一些挑战阻碍了…

Python元编程-装饰器介绍、使用

目录 一、Python元编程装饰器介绍 二、装饰器使用 1. 实现认证和授权功能 2.实现缓存功能 3.实现日志输出功能 三、附录 1. logging.basicConfig介绍 2. 精确到毫秒&#xff0c;打印时间 方法一&#xff1a;使用datetime 方法二&#xff1a;使用time 一、Python元编程…

Eureka 学习笔记4:EurekaClient

版本 awsVersion ‘1.11.277’ EurekaClient 接口实现了 LookupService 接口&#xff0c;拥有唯一的实现类 DiscoveryClient 类。 LookupService 接口提供以下功能&#xff1a; 获取注册表根据应用名称获取应用根据实例 id 获取实例信息 public interface LookupService<…

【MySQL】数据库基本使用

文章目录 一、数据库介绍二、数据库使用2.1 登录MySQL2.2 基本使用2.2.1 显示当前 MySQL 实例中所有的数据库列表2.2.2 创建数据库2.2.3 创建数据库表2.2.4 在表中插入数据2.2.5 在表中查询数据 三、服务器、数据库、表之间的关系四、SQL语句分类五、存储引擎 一、数据库介绍 …