Spring中经典的7种设计模式源码分析

一、工厂模式

  • Spring使用工厂模式来创建Bean对象,如BeanFactory、ApplicationContext等。
  • 工厂模式为bean的创建过程提供了一个框架,同时隔离了实例化细节,使得代码更加解耦。
  1. BeanFactory接口

BeanFactory接口仍然是Spring工厂模式的基础,它定义了获取Bean实例的基本方法。

public interface BeanFactory {Object getBean(String name) throws BeansException;// ...
}
  1. DefaultListableBeanFactory类

DefaultListableBeanFactory继承自AbstractAutowireCapableBeanFactory,实现了BeanDefinitionRegistry接口,用于存储和管理BeanDefinition。它是最常用的BeanFactory实现类。

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactoryimplements ConfigurableListableBeanFactory, BeanDefinitionRegistry {// ...
}
  1. AbstractBeanFactory类

AbstractBeanFactory作为抽象基类,定义了getBean()方法的模板实现。

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {@Overridepublic Object getBean(String name) throws BeansException {return doGetBean(name, null, null, false);}protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)throws BeansException {// 合并父BeanFactoryfinal String beanName = transformedBeanName(name);Object sharedInstance = getSingleton(beanName);// ...// 创建Bean实例RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);checkMergedBeanDefinition(mbd, beanName, args);Object instance = null;if (mbd.isSingleton()) {instance = resolveBeforeInstantiation(beanName, mbd);if (instance == null) {instance = createBean(beanName, mbd, args);}} else {instance = createBean(beanName, mbd, args);}// ...return instance;}
}
  1. 创建Bean实例

AbstractAutowireCapableBeanFactory提供了createBean()方法,用于创建Bean实例。该方法委托给了AbstractAutowireCapableBeanFactory的createBeanInstance()方法,来实现不同的实例化策略。

protected Object createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {// 决定使用哪种实例化策略Constructor<?> constructorToUse = null;// ...// 使用适当的实例化策略boolean resolved = false;boolean autowireNecessary = false;if (args == null) {synchronized (mbd.constructorArgumentLock) {// ...autowireNecessary = mbd.resolvedConstructorOrFactoryMethod != null;resolved = true;}}Object beanInstance = null;if (resolved) {// 使用工厂方法实例化beanInstance = getInstantiationStrategy().instantiate(mbd, null, this);}// ...return beanInstance;
}
  1. 实例化策略

Spring 5中提供了多种实例化策略,包括:

  • 简单实例化策略(SimpleInstantiationStrategy)
  • CGLIB实例化策略(CglibSubclassingInstantiationStrategy)
  • 通过工厂方法实例化(FactoryMethodInstantiationStrategy)
  • 通过静态工厂方法实例化

这些实例化策略均实现了InstantiationStrategy接口,并在AbstractAutowireCapableBeanFactory的createBeanInstance()方法中根据条件来选择合适的策略。

二、单例模式

  • Spring默认情况下将每个bean创建为单例模式,可以通过配置修改为原型模式。
  • 单例模式确保了在整个应用程序中只有一个bean实例,从而节省内存资源。
  1. 单例 Bean 缓存

DefaultSingletonBeanRegistry 使用 ConcurrentHashMap 来缓存单例 Bean 的实例:

/** Cache of singleton objects: bean name to bean instance */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
  1. getSingleton() 方法

在 AbstractBeanFactory 的 getBean() 方法中,首先会尝试从单例 Bean 缓存中获取 Bean 实例:

@Override
public Object getBean(String name) throws BeansException {return doGetBean(name, null, null, false);
}protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {// 获取"真实"的 beanName,考虑了 FactoryBeanfinal String beanName = transformedBeanName(name);Object sharedInstance = getSingleton(beanName);if (sharedInstance != null && args == null) {// ...}// ...
}

getSingleton() 方法定义在 DefaultSingletonBeanRegistry 中:

public Object getSingleton(String beanName) {return getSingleton(beanName, true);
}protected Object getSingleton(String beanName, boolean allowEarlyReference) {// 检查缓存中是否存在实例Object singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {// 如果当前 Bean 正在创建中,则需要处理循环依赖singletonObject = this.earlySingletonObjects.get(beanName);if (singletonObject == null && allowEarlyReference) {// ...}}return singletonObject;
}
  1. addSingleton() 方法

如果缓存中不存在该 Bean 的实例,Spring 会调用相应的实例化策略创建 Bean 实例,并在创建完成后,将其缓存到单例缓存中:

protected void addSingleton(String beanName, Object singletonObject) {synchronized (this.singletonObjects) {this.singletonObjects.put(beanName, singletonObject);// 从 singletonFactories 中移除this.singletonFactories.remove(beanName);this.earlySingletonObjects.remove(beanName);this.registeredSingletons.add(beanName);}
}
  1. 单例作用域

在解析 Bean 定义时,Spring 会根据 scope 属性确定 Bean 的作用域,默认为 singleton,即单例模式。如果是单例作用域,Spring 会在获取 Bean 实例时从单例缓存中获取或创建一个实例并加入缓存。

public Object getBean(String name) throws BeansException {return doGetBean(name, null, null, false);
}protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly) {// ...// 创建或获取已经创建的实例if (mbd.isSingleton()) {sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {@Overridepublic Object getObject() throws BeansException {try {return createBean(beanName, mbd, args);} catch (BeansException ex) {// ...}}});// ...}// ...
}

在上面的代码中,如果 Bean 的作用域是单例,Spring 会调用 getSingleton() 方法尝试从单例缓存中获取 Bean 实例。如果缓存中不存在,则使用传入的 ObjectFactory 回调函数创建 Bean 实例,并将其加入单例缓存中。

  1. 循环依赖处理

Spring 还提供了处理单例 Bean 循环依赖的机制。在 getSingleton() 方法中,如果发现当前 Bean 正在创建中,会尝试从 earlySingletonObjects 缓存中获取提前曝光的 Bean 实例(ObjectFactory),从而解决循环依赖问题。

总结起来,Spring 5 中通过维护一个单例 Bean 缓存 (ConcurrentHashMap)、getSingleton() 方法从缓存中获取或创建 Bean 实例、以及 addSingleton() 方法将 Bean 实例加入缓存,实现了单例模式的管理。同时,Spring 还根据 Bean 定义的 scope 属性确定 Bean 的作用域,默认为单例模式。这种实现方式保证了在同一个 Spring IoC 容器中,单例 Bean 只会被实例化一次,提高了性能并节省了内存资源,

三、代理模式

  • Spring的AOP (Aspect Oriented Programming) 功能就是利用代理模式实现的。
  • 代理模式在不修改目标对象的情况下,通过代理对象来增强目标对象的功能。Spring AOP的实现主要依赖两个模块:Spring AOP和AspectJ
  1. AOP代理创建

在Spring AOP中,如果目标对象实现了接口,则默认使用JDK动态代理创建AOP代理。如果目标对象没有实现接口,则使用CGLIB创建代理对象。这种选择是由AopProxyFactory决定的:

public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {@Overridepublic AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {Class<?> targetClass = config.getTargetClass();if (targetClass == null) {throw new AopConfigException("TargetSource cannot determine target class: " +"Either an interface or a target is required for proxy creation.");}if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {return new JdkDynamicAopProxy(config);}return new ObjenesisCglibAopProxy(config);}else {return new JdkDynamicAopProxy(config);}}
}
  1. JDK动态代理

JDK动态代理通过实现InvocationHandler接口和使用Proxy类来创建代理对象,代码如下:

public class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {private final Class<?> proxiedInterface;public Object getProxy(ClassLoader classLoader) {// 使用Proxy创建代理对象return Proxy.newProxyInstance(classLoader, new Class<?>[] { this.proxiedInterface }, this);}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 调用拦截器链执行方法MethodInvocation invocation = new ReflectiveMethodInvocation(...);return invocation.proceed();}
}
  1. CGLIB代理

CGLIB代理通过继承目标对象的方式创建代理对象,代码如下:

public class ObjenesisCglibAopProxy extends CglibAopProxy {@Overridepublic Object getProxy(ClassLoader classLoader) {// 使用Enhancer创建代理对象Enhancer enhancer = new Enhancer();enhancer.setSuperclass(this.advised.getTargetClass());enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));Callback[] callbacks = getCallbacks(this.advised);Class<?>[] types = new Class<?>[callbacks.length];for (int x = 0; x < types.length; x++) {types[x] = callbacks[x].getClass();}// 设置过滤器enhancer.setCallbackFilter(new ProxyCallbackFilter(this.advised.getConfigurationOnlyCopy(), types));enhancer.setCallbackTypes(types);// 创建代理对象return createProtectedProxy(enhancer, callbacks, this.advised);}
}
  1. Advice链执行

无论是JDK动态代理还是CGLIB代理,在目标方法调用时都会执行相应的Advice链。Spring使用MethodInvocation类来执行Advice链:

public class ReflectiveMethodInvocation implements ProxyMethodInvocation {protected final Object[] arguments;public Object proceed() throws Throwable {// 获取适当的拦截器链List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);if (chain.isEmpty()) {// 直接执行目标方法retVal = invokeSingalTarget();}else {// 执行拦截器链retVal = new ReflectiveMethodInvocation(proxy, target, method, arguments, target.getClass(), chain).proceed();}return retVal;}
}

在执行Advice链的过程中,Spring会根据Advice的类型(前置、环绕、异常、最终返回)在适当的位置执行对应的Advice逻辑。

总的来说,Spring 5利用JDK动态代理和CGLIB两种方式创建AOP代理对象,并通过执行相应的Advice链来增强目标对象的功能。代理模式的使用使得Spring AOP能够在不修改目标对象的前提下,动态地为目标对象增加新的行为和职责。可以自定义Advice,从而灵活地扩展目标对象的功能。

四、模板方法模式

  • Spring中的 JDBCTemplate、HibernateTemplate等以模板方法模式为基础。
  • 模板方法模式定义了一个算法的骨架,并允许子类重写特定的步骤。
  1. JdbcTemplate

JdbcTemplate是Spring JDBC中的核心类,用于简化JDBC操作。它提供了一系列执行SQL语句的模板方法,如query()、update()等。这些模板方法都遵循相同的模式:

public <T> T query(String sql, ResultSetExtractor<T> rse) throws DataAccessException {// 创建语句PreparedStatement stmt = null;try {stmt = createPreparedStatement(sql);// 设置参数applyStatementSettings(stmt);// 执行查询ResultSet rs = null;try {rs = executeQuery(stmt);// 执行ResultSetExtractorreturn rse.extractData(rs);} finally {// ...}} finally {// ...}
}
  1. 模板方法骨架

在JdbcTemplate的模板方法中,有一些固定的步骤是不可变的,如创建语句、设置参数、执行查询等,这些步骤构成了模板方法的骨架。

  1. 钩子方法

在模板方法中,也会调用一些抽象方法或钩子方法,这些方法留给子类去实现。比如executeQuery()、applyStatementSettings()等。子类可以通过扩展JdbcTemplate并重写这些钩子方法来自定义相应的行为。

protected PreparedStatement createPreparedStatement(String sql, @Nullable List<Object> paramList) throws SQLException {PreparedStatement stmt = getPreparedStatementCreator().createPreparedStatement(sql, this.getRetrieveKeys(paramList));applyStatementSettings(stmt);return stmt;
}protected abstract PreparedStatementCreator getPreparedStatementCreator();protected void applyStatementSettings(PreparedStatement stmt) {// ...
}
  1. 回调接口

除了通过子类继承的方式来自定义行为,Spring还提供了一些回调接口,允许开发者在执行模板方法时注入自定义的逻辑。比如ResultSetExtractor、PreparedStatementSetter等。

public <T> T query(String sql, ResultSetExtractor<T> rse) throws DataAccessException {// ...return rse.extractData(rs);
}

总的来说,Spring 5中通过模板方法模式提供了一些可复用的模板类,如JdbcTemplate。这些模板类定义了一系列算法的骨架,并通过钩子方法和回调接口,允许开发者在不改变模板结构的情况下,自定义相应的行为。这种模式提高了代码的可重用性和可扩展性,同时也增强了代码的可维护性。Spring框架中还有许多其他模板类的实现,如RedisTemplate、RestTemplate等,都遵循了模板方法模式的设计思想。

五、观察者模式

  • Spring的事件机制就是基于观察者模式实现的。
  • 观察者模式定义了对象之间的一对多依赖关系,当一个对象改变状态时,它的所有依赖者都会得到通知。
    Spring 5中使用观察者模式来实现事件驱动机制,主要通过ApplicationEvent和ApplicationListener来实现。
  1. ApplicationEvent

ApplicationEvent是Spring中事件的基类,它继承自jdk的EventObject。所有的事件都需要继承ApplicationEvent。

public abstract class ApplicationEvent extends EventObject {private static final long serialVersionUID = 7099057708183571937L;private final long timestamp;public ApplicationEvent(Object source) {super(source);this.timestamp = System.currentTimeMillis();}// ...
}
  1. ApplicationListener

ApplicationListener是观察者接口,用于监听并处理ApplicationEvent事件。

@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {void onApplicationEvent(E event);
}
  1. ApplicationEventMulticaster

ApplicationEventMulticaster是观察者模式中的主题或发布者角色,它维护了一个ApplicationListener集合,用于发布事件并通知所有监听器。

public abstract class AbstractApplicationEventMulticaster implements ApplicationEventMulticaster {private final ListenerRetriever defaultRetriever = new DefListenerRetriever(false);private final ListenerRetriever retrieverWithSet = new DefListenerRetriever(true);// 添加监听器public void addApplicationListener(ApplicationListener<?> listener) {synchronized (this.retrieveListeners) {this.retrieveListeners.add(listener);this.singletonRetrievers.clear();}}// 发布事件并通知监听器public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {resolveListeners(event, retrieverCache.getListeners(eventType, this.defaultRetriever, this.applicationContext.getId()));}// 内部通知监听器处理事件protected void invokeListener(ApplicationListener listener, ApplicationEvent event) {listener.onApplicationEvent(event);}// ...
}
  1. 注册和发布事件

在Spring中,可以通过实现ApplicationListener接口并将其注册为Bean来监听事件。发布事件时,ApplicationEventMulticaster会遍历所有的监听器并调用其onApplicationEvent()方法。

// 定义事件
public class MyEvent extends ApplicationEvent {// ...
}// 定义监听器
@Component
public class MyListener implements ApplicationListener<MyEvent> {@Overridepublic void onApplicationEvent(MyEvent event) {// 处理事件}
}// 发布事件
@Component
public class EventPublisher {@Autowiredprivate ApplicationContext context;public void publish() {context.publishEvent(new MyEvent("Hello Event"));}
}

Spring 5中通过ApplicationEvent、ApplicationListener和ApplicationEventMulticaster实现了观察者模式。ApplicationEvent是事件对象,ApplicationListener是观察者接口,ApplicationEventMulticaster扮演发布者的角色,负责管理监听器并发布事件。开发者可以自定义事件和监听器,并通过ApplicationContext发布事件。这种实现方式使得Spring框架具有了良好的可扩展性和灵活性,能够很好地支持事件驱动编程。

六、策略模式

  • Spring的资源访问模块(Resource)中使用了策略模式。
  • 策略模式定义了一系列算法,并将每个算法封装成一个对象,从而使它们可以互相替换。
    Spring 5中使用了策略模式来实现一些功能,允许在运行时根据不同的条件选择不同的算法或策略。以Spring中的Resource接口为例,我们来分析一下策略模式在Spring 5中的实现。
  1. Resource接口

Resource接口定义了一组用于获取低级资源的操作方法。它是Spring资源访问策略的入口接口。

public interface Resource extends InputStreamSource {boolean exists();boolean isOpen();URL getURL() throws IOException;File getFile() throws IOException;// ...
}
  1. Resource实现类

Spring提供了多个Resource接口的具体实现类,每个实现类都对应一种资源访问策略。

  • ClassPathResource: 用于访问类路径下的资源
  • FileSystemResource: 用于访问文件系统中的资源
  • UrlResource: 用于访问URL资源
  • ByteArrayResource: 用于访问字节数组资源
  • InputStreamResource: 用于访问输入流资源
public class ClassPathResource extends AbstractResource {// ...
}public class FileSystemResource extends AbstractResource implements ResourceLoaderAware {// ...  
}public class UrlResource extends AbstractFileResolvingResource {// ...
}
  1. Resource加载器

Spring提供了ResourceLoader接口及其实现类DefaultResourceLoader,用于根据不同的前缀来选择合适的Resource实现类。

public interface ResourceLoader {Resource getResource(String location);
}public class DefaultResourceLoader implements ResourceLoader {@Overridepublic Resource getResource(String location) {if (location.startsWith("/")) {return getResourceByPath(location);} else if (location.startsWith("classpath:")) {return new ClassPathResource(location.substring("classpath:".length()), getClassLoader());} else {try {// Try URLURL url = new URL(location);return new UrlResource(url);} catch (MalformedURLException ex) {// No URL -> resolve as resource path.return getResourceByPath(location);}}}// ...
}
  1. 使用示例

在应用程序中,可以通过ResourceLoader或ApplicationContext来获取不同类型的Resource实例。

@Component
public class MyService {@Autowiredprivate ResourceLoader resourceLoader;public void loadResource(String location) {Resource resource = resourceLoader.getResource(location);// 使用Resource执行相关操作}
}

Spring 5通过Resource接口及其多个具体实现类,以及ResourceLoader加载器,实现了策略模式。不同的Resource实现类对应不同的资源访问策略,而ResourceLoader则根据资源位置的前缀来选择合适的Resource实现类。

七、装饰器模式

  • Spring中的 HttpServletRequestDecorator和 HttpServletResponseDecorator 使用了装饰器模式。
  • 装饰器模式可以在不修改原有对象结构的情况下,动态地给该对象增加新的行为和职责。

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

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

相关文章

LAMP网站部署(Discuz论坛网站部署)

目录 mysql命令 语法 选项 参数 实例 安装php 安装Mariadb 关掉防火墙和selinux 启动HTTP服务 初始化数据库 查看数据库是否创建成功 修改HTTP的配置文件 浏览器打开 将以下所有目录都加上权限 最后首页效果 mysql命令 是MySQL数据库服务器的客户端工具&#xff0c;它工作在命…

【点云】激光点云建图评测

处理工具 Pcap合并软件 sudo apt install wireshark-common合并Pcap文件&#xff0c;路径为数据文件夹下&#xff0c; #mergecap -w <输出的新Pcap> <输入的Pcap> mergecap -w lidar_output.pcap slice2099-06-01/LIDAR/lidar.pcap slice2099-06-02/LIDAR/lidar…

Java错误:JDBC错误,如何解决和避免

随着Java的广泛应用&#xff0c;Java程序在连接数据库时经常会出现JDBC错误。JDBC&#xff08;Java Database Connectivity&#xff09;是Java中用于连接数据库的编程接口&#xff0c;因此&#xff0c;JDBC错误是在Java程序与数据库交互时遇到的一种错误。下面将介绍一些最常见…

从根到叶:深度理解哈希表

​​​​​​​ 一.哈希表的概念 关于查找元素时&#xff1a; 在顺序结构以及平衡树 中&#xff0c;元素关键码与其存储位置之间没有对应的关系&#xff0c;因此在 查找一个元素时&#xff0c;必须要经过关键 码的多次比较 。 顺序查找时间复杂度为 O(N) &#xff0c;平衡树中…

什么是云计算?应用场景有哪些?

云计算是通过互联网提供计算资源和服务的计算模式&#xff0c;是一种新型的计算模式&#xff0c;能够通过互联网将计算和存储资源进行集中和共享&#xff0c;云计算主要就是把有形的产品&#xff0c;如网络硬件设备、服务器、存储服务器和各种软件等转化成服务产品&#xff0c;…

Acwing-基础算法课笔记之动态规划(背包问题)

Acwing-基础算法课笔记之动态规划&#xff08;背包问题&#xff09; 一、01背包问题1、概述2、过程模拟 二、完全背包问题1、概述2、闫氏dp分析完全背包问题3、过程模拟代码模板 三、多重背包问题1、概述2、过程模拟3、多重背包问题的优化版本 分组背包问题1、概述2、过程模拟3…

postgresql 批量添加数据,存在则更新,不存在则插入

语句介绍: DO NOTHING&#xff1a;当记录存在时&#xff0c;什么都不做 DO UPDATE SET column_1 value_1, … WHERE condition&#xff1a;当记录存在时&#xff0c;更新表中的一些字段 实例语句&#xff1a; name默认为主键 存在则更新&#xff0c;不存在则插入 INSERT I…

Rockchip android7.1.2 强制第三方apk横屏显示

Rockchip android7.1.2 强制第三方apk横屏显示 问题描述解决方法 郑重声明:本人原创博文&#xff0c;都是实战&#xff0c;均经过实际项目验证出货的 转载请标明出处:攻城狮2015 Platform: Rockchip OS:Android 7.1.2 Kernel: 3.10 问题描述 目前市面上&#xff0c;apk有三种形…

修改vscode的相对路径计算逻辑

vscode的相对路径计算逻辑是&#xff0c;"./"表示当前项目的文件夹&#xff0c;而不是当前文件所在的文件夹 做出如下修改&#xff1a; File-->Preferences-->settings 搜索Execute in File Dir , 然后取消勾选

粒子群算法对pi控制器进行参数优化,随时优化pi参数以控制直流无刷电机转速。

粒子群算法对pi控制器进行参数优化&#xff0c;随时优化pi参数以取得设定直流无刷电机转速。 PSO优化PID&#xff0c;用于BLDC速度控制 仿真平台为&#xff1a;MATLAB 采用的是Simulinkm程序相配合 仿真结果以及程序示例&#xff1a;

如何配置Apache的反向代理

目录 前言 一、反向代理的工作原理 二、Apache反向代理的配置 1. 安装Apache和相关模块 2. 配置反向代理规则 3. 重启Apache服务器 三、常见的使用案例 1. 负载均衡 2. 缓存 3. SSL加密 总结 前言 随着Web应用程序的不断发展和扩展&#xff0c;需要处理大量的请求和…

Excel第26享:模糊查找之Hlookup函数与通配符的嵌套

1、需求描述 如下图所示&#xff0c;现第一行有三个参考值&#xff1a;人S、羊E、猪3&#xff0c;在第三行有5个字&#xff1a;马、牛、人、羊、猪&#xff0c;每个字如果出现在第一行的三个参考值中&#xff0c;就返回该单元格的数值。如&#xff0c;人&#xff0c;就返回“人…

Lucene查询语法,适用于 ELk Kibana 查询

Lucene查询语法&#xff0c;适用于 ELk Kibana 查询 Elasticsearch 构建在 Lucene 之上&#xff0c;过滤器语法和 Lucene 相同。本语法可用于 Kibana 界面的检索和 Grafana 看板对接 ES 的检索规则。 Kibana 上的检索语法Grafana 上的检索语法 全文搜索 在搜索栏输入login&…

【SpringCloud微服务实战08】RabbitMQ 消息队列

MQ异步通信优缺点: 优点: 吞吐量提升:无需等待订阅者处理完成,响应更快速 故障隔离:服务没有直接调用,不存在级联失败问题 调用间没有阻塞,不会造成无效的资源占用 耦合度极低,每个服务都可以灵活插拔,可替换 流量削峰:不管发布事件的流量波动多大,都由Broker接收,…

Redis-复制功能

0 序言 复制功能是Redis提供的多机功能中最基础的一个&#xff0c;这个功能是通过主从复制&#xff08;master-slave replication&#xff09;模式实现的&#xff0c;它允许用户为存储着目标数据库的服务器创建出多个拥有相同数据库副本的服务器&#xff0c;其中存储目标数据库…

数据流的中位数

优质博文IT-BLOG-CN 一、题目 中位数是有序整数列表中的中间值。如果列表的大小是偶数&#xff0c;则没有中间值&#xff0c;中位数是两个中间值的平均值。 【1】 例如arr [2,3,4]的中位数是3。 【2】例如arr [2,3]的中位数是(2 3) / 2 2.5。 实现MedianFinder类: 【1】M…

GPT如何做角色扮演,prompt示例大放送

文末有完整版角色扮演提示词。 角色扮演在AI提示词中有着至关重要的作用。 无论结构化指令,还是文本格式指令,角色扮演都是很实用也是比较容易上手的提示词的重要组成部分。 我们可以通过让ChatGPT扮演特定的角色,来获得更加贴合需求的、具有特定视角和专业知识背景的答案…

​LLM之新手入门:大预言模型的概念介绍与应用

最近&#xff0c;我在系统地学习大型语言模型&#xff08;LLM&#xff09;的相关知识。在这个学习过程中&#xff0c;我努力将所学的内容整理成博客文章。在这篇博客中&#xff0c;我首先简要介绍了人工智能的发展历史&#xff0c;然后探讨了大型模型的基本原理、训练方法、微调…

Linux系列

安装系列 1.MySQL安装 我们要通过rpm&#xff0c;进行MySQL数据库的安装&#xff0c;主要的步骤如下&#xff1a; rpm -qa 查询当前系统中安装的所有软件 rpm -qa | grep mysql 查询当前系统中安装的名称带mysql的软件 rpm -…

uniapp微信小程序_拍照从相册选择

userImg() {let that thisuni.chooseMedia({count: 1,mediaType: [image, video],sourceType: [album, camera],maxDuration: 30,camera: back,success(res) {console.log(res.tempFiles[0].tempFilePath)that.imagUrl res.tempFiles[0].tempFilePath}})}, 直接调用api即可,注…