详解SpringBean的作用域(Scopes)

news2025/1/17 15:19:02

文章目录

  • 一、SpringBean作用域总览
  • 二、"singleton" Bean作用域
  • 三、"prototype" Bean作用域
    • 1、验证singleton、prototype类型的Bean
    • 2、总结
  • 四、"request" Bean作用域
    • 1、配置
    • 2、简介
  • 五、"session" Bean作用域
    • 1、配置
    • 2、简介
    • 3、总结session、request作用域
  • 六、"application" Bean作用域
    • 1、配置
    • 2、总结session、request、application作用域
  • 七、自定义 Bean 作用域
    • 1、自定义Scope,实现Scope接口
    • 2、注册Scope
  • 八、Spring Cloud RefreshScope是如何控制Bean的动态刷新

一、SpringBean作用域总览

来源说明
singleton默认 Spring Bean 作用域,一个 BeanFactory 有且仅有一个实例
prototype原型作用域,每次依赖查找和依赖注入生成新 Bean 对象
request将 Spring Bean 存储在 ServletRequest 上下文中
session将 Spring Bean 存储在 HttpSession 中
application将 Spring Bean 存储在 ServletContext 中

我们这里说的SpringBean的作用域,并不是值全部的Spring的Bean,而是指Spring的BeanDefinition定义的Bean。

二、“singleton” Bean作用域

在这里插入图片描述
“singleton” Bean作用域,就是这个Bean是一个单例的。

// BeanDefinition 
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

	// 重点掌握这两个作用域
	String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON; // singleton
	String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE; // prototype
	...
	// 返回此bean的当前目标作用域的名称,如果还不知道,则返回null。
	String getScope();
	
	// 返回是否为单例,所有调用都返回一个共享实例。
	boolean isSingleton();

	// 返回是否为Prototype,并为每个调用返回一个独立的实例。
	boolean isPrototype();

	...
}

在获取bean时,经常会看到if(bd.isSingleton())这样的代码,就是singleton和prototype不一样的作用域,导致bean的行为不同。

但是注意一点,singleton和prototype原则上是互斥的,但是代码中并不是互斥的,是可以同时为true或false。
通常在 Bean 创建时,isSingleton 方法先判断,isPrototype 后判断,详情参考 org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean 方法:

// Create bean instance.
if (mbd.isSingleton()) { // 单例
	sharedInstance = getSingleton(beanName, () -> {
		try {
			return createBean(beanName, mbd, args);
		}
		catch (BeansException ex) {
			// Explicitly remove instance from singleton cache: It might have been put there
			// eagerly by the creation process, to allow for circular reference resolution.
			// Also remove any beans that received a temporary reference to the bean.
			destroySingleton(beanName);
			throw ex;
		}
	});
	beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

else if (mbd.isPrototype()) { // 非单例
	// It's a prototype -> create a new instance.
	Object prototypeInstance = null;
	try {
		beforePrototypeCreation(beanName);
		prototypeInstance = createBean(beanName, mbd, args);
	}
	finally {
		afterPrototypeCreation(beanName);
	}
	beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}

else { // 其他
	String scopeName = mbd.getScope();
	if (!StringUtils.hasLength(scopeName)) {
		throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
	}
	Scope scope = this.scopes.get(scopeName);
	if (scope == null) {
		throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
	}
	try {
		Object scopedInstance = scope.get(beanName, () -> {
			beforePrototypeCreation(beanName);
			try {
				return createBean(beanName, mbd, args);
			}
			finally {
				afterPrototypeCreation(beanName);
			}
		});
		beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
	}
	catch (IllegalStateException ex) {
		throw new ScopeNotActiveException(beanName, scopeName, ex);
	}
}

三、“prototype” Bean作用域

“prototype” Bean作用域,这个bean每次依赖查找或者依赖注入都是一个新的对象。

在这里插入图片描述

1、验证singleton、prototype类型的Bean

public class User implements BeanNameAware {

    private Long id;

    /**
     * 当前 Bean 的名称
     */
    private transient String beanName;

    public static User createUser() {
        User user = new User();
        user.setId(1L);
        user.setName("张三");
        return user;
    }

    @PostConstruct
    public void init() {
        System.out.println("User Bean [" + beanName + "] 初始化...");
    }

    @PreDestroy
    public void destroy() {
        System.out.println("User Bean [" + beanName + "] 销毁中...");
    }

    @Override
    public void setBeanName(String name) {
        this.beanName = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                '}';
    }
}
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;

import java.util.Map;

/**
 * Bean 的作用域示例
 */
public class BeanScopeDemo implements DisposableBean {

    @Bean
    // 默认 scope 就是 "singleton"
    public static User singletonUser() {
        return createUser();
    }

    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public static User prototypeUser() {
        return createUser();
    }

    private static User createUser() {
        User user = new User();
        user.setId(System.nanoTime());
        return user;
    }

    @Autowired
    @Qualifier("singletonUser")
    private User singletonUser;

    @Autowired
    @Qualifier("singletonUser")
    private User singletonUser1;

    @Autowired
    @Qualifier("prototypeUser")
    private User prototypeUser;

    @Autowired
    @Qualifier("prototypeUser")
    private User prototypeUser1;

    @Autowired
    @Qualifier("prototypeUser")
    private User prototypeUser2;

    @Autowired
    private Map<String, User> users;

    @Autowired
    private ConfigurableListableBeanFactory beanFactory; // Resolvable Dependency

    public static void main(String[] args) {

        // 创建 BeanFactory 容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        // 注册 Configuration Class(配置类) -> Spring Bean
        applicationContext.register(BeanScopeDemo.class);

        // 官方建议 可以利用 BeanPostProcessor 进行清扫工作 , 但是最好不要这么做。
        applicationContext.addBeanFactoryPostProcessor(beanFactory -> {
            beanFactory.addBeanPostProcessor(new BeanPostProcessor() {

                @Override
                public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
                    System.out.printf("%s Bean 名称:%s 在初始化后回调...%n", bean.getClass().getName(), beanName);
                    return bean;
                }
            });
        });

        // 启动 Spring 应用上下文
        applicationContext.refresh();

        // 结论一:
        // Singleton Bean 无论依赖查找还是依赖注入,均为同一个对象
        // Prototype Bean 无论依赖查找还是依赖注入,均为新生成的对象
        scopedBeansByLookup(applicationContext);

        // 结论二:
        // 如果依赖注入集合类型的对象,Singleton Bean 和 Prototype Bean 均会存在一个
        // Prototype Bean 有别于其他地方的依赖注入 Prototype Bean
        scopedBeansByInjection(applicationContext);

        // 结论三:
        // 无论是 Singleton 还是 Prototype Bean 均会执行初始化方法回调
        // 不过仅 Singleton Bean 会执行销毁方法回调
        // 这里显式地关闭 Spring 应用上下文
        applicationContext.close();
    }

    private static void scopedBeansByLookup(AnnotationConfigApplicationContext applicationContext) {

        for (int i = 0; i < 3; i++) {
            // singletonUser 是共享 Bean 对象
            User singletonUser = applicationContext.getBean("singletonUser", User.class);
            System.out.println("singletonUser = " + singletonUser);
            // prototypeUser 是每次依赖查找均生成了新的 Bean 对象
            User prototypeUser = applicationContext.getBean("prototypeUser", User.class);
            System.out.println("prototypeUser = " + prototypeUser);
        }
    }

    private static void scopedBeansByInjection(AnnotationConfigApplicationContext applicationContext) {
        BeanScopeDemo beanScopeDemo = applicationContext.getBean(BeanScopeDemo.class);

        System.out.println("beanScopeDemo.singletonUser = " + beanScopeDemo.singletonUser);
        System.out.println("beanScopeDemo.singletonUser1 = " + beanScopeDemo.singletonUser1);

        System.out.println("beanScopeDemo.prototypeUser = " + beanScopeDemo.prototypeUser);
        System.out.println("beanScopeDemo.prototypeUser1 = " + beanScopeDemo.prototypeUser1);
        System.out.println("beanScopeDemo.prototypeUser2 = " + beanScopeDemo.prototypeUser2);

        System.out.println("beanScopeDemo.users = " + beanScopeDemo.users);
    }

    /**
     * 手动销毁prototype的bean
     */
    @Override
    public void destroy() {

        System.out.println("当前 BeanScopeDemo Bean 正在销毁中...");

        this.prototypeUser.destroy();
        this.prototypeUser1.destroy();
        this.prototypeUser1.destroy();
        this.prototypeUser2.destroy();
        // 获取 BeanDefinition
        for (Map.Entry<String, User> entry : this.users.entrySet()) {
            String beanName = entry.getKey();
            BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
            if (beanDefinition.isPrototype()) { // 如果当前 Bean 是 prototype scope
                User user = entry.getValue();
                user.destroy();
            }
        }

        System.out.println("当前 BeanScopeDemo Bean 销毁完成");
    }
}

2、总结

Spring 容器没有办法管理 prototype Bean 的完整生命周期,也没有办法记录实例的存在。销毁回调方法将不会执行,官方建议利用 BeanPostProcessor 进行清扫工作,但实际最好不要这么做,刚初始化完就销毁,总感觉很奇怪。

由上面的例子也可以看出,单例bean Spring会维护bean的整个生命周期,原型bean Spring不会维护bean的完整生命周期,在使用原型的bean时,要注意原型bean的销毁工作,使用不当甚至会导致OOM。

四、“request” Bean作用域

1、配置

1、XML -

2、Java 注解 - @RequestScope 或 @Scope(WebApplicationContext.SCOPE_REQUEST)

3、API - RequestScope

@Bean
@RequestScope
public User user() {
    User user = new User();
    user.setId(1L);
    user.setName("张三");
    return user;
}

// 注入
@Autowired
private User user; // CGLIB 代理后对象(不变的)

@GetMapping("/index.html")
public String index(Model model) {
    model.addAttribute("userObject", user);
    return "index";
}

2、简介

当我们的bean设置为request的时候,我们每次http请求的时候会形成不同的对象,会经历该对象的初始化和销毁过程。

@RequestScope的实现原理是基于AbstractRequestAttributesScope来实现的。

// org.springframework.web.context.request.AbstractRequestAttributesScope#get
// 每次http请求都会调用
@Override
public Object get(String name, ObjectFactory<?> objectFactory) {
	RequestAttributes attributes = RequestContextHolder.currentRequestAttributes();
	// 每次返回给前端页面渲染时,都是一个不同的对象
	Object scopedObject = attributes.getAttribute(name, getScope());
	if (scopedObject == null) {
		scopedObject = objectFactory.getObject();
		attributes.setAttribute(name, scopedObject, getScope());
		// Retrieve object again, registering it for implicit session attribute updates.
		// As a bonus, we also allow for potential decoration at the getAttribute level.
		Object retrievedObject = attributes.getAttribute(name, getScope());
		if (retrievedObject != null) {
			// Only proceed with retrieved object if still present (the expected case).
			// If it disappeared concurrently, we return our locally created instance.
			scopedObject = retrievedObject;
		}
	}
	return scopedObject;
}

五、“session” Bean作用域

1、配置

1、XML -

2、Java 注解 - @SessionScope 或 @Scope(WebApplicationContext.SCOPE_SESSION)

3、API - SessionScope

@Bean
@SessionScope
public User user() {
    User user = new User();
    user.setId(1L);
    user.setName("张三");
    return user;
}

2、简介

@SessionScope的实现原理也是基于AbstractRequestAttributesScope来实现的。

session作用域的对象,同一会话返回的对象都是相同的,不同会话返回的对象都是不同的。

但是这个对象可不能,像session一样设置过期时间哦~

与request作用域的对象不同,request因为是每个线程有一个对象,session作用域的对象是有线程不安全问题的,假如说同一个用户打开了两个浏览器页面,相当于多线程同时访问,所以,在代码中加了把锁。

// org.springframework.web.context.request.SessionScope
@Override
public Object get(String name, ObjectFactory<?> objectFactory) {
	Object mutex = RequestContextHolder.currentRequestAttributes().getSessionMutex();
	synchronized (mutex) {
		return super.get(name, objectFactory);
	}
}

@Override
@Nullable
public Object remove(String name) {
	Object mutex = RequestContextHolder.currentRequestAttributes().getSessionMutex();
	synchronized (mutex) {
		return super.remove(name);
	}
}

3、总结session、request作用域

Spring 将 Bean 的作用域分为三种,singleton、prototype、自定义 Scope,在 AbstractBeanFactory#doGetBean 创建 bean 时根据三种情况分别创建对象。其中 singleton、prototype 是 Spring IoC 内置的,自定义 Scope 需要实现 Scope 接口,通过 get 方法创建对象。 request/session 这两种自定义 Scope 是为了解决 web 场景,RequestScope/SessionScope 会将创建的对象和 HttpRequest/HttpSession 绑定在一起。

六、“application” Bean作用域

1、配置

1、XML -

2、Java 注解 - @ApplicationScope 或 @Scope(WebApplicationContext.SCOPE_APPLICATION)

3、API - ServletContextScope

application的bean,直接和servletContext直接打交道。

// org.springframework.web.context.support.ServletContextScope#get
@Override
public Object get(String name, ObjectFactory<?> objectFactory) {
	Object scopedObject = this.servletContext.getAttribute(name);
	if (scopedObject == null) {
		scopedObject = objectFactory.getObject();
		this.servletContext.setAttribute(name, scopedObject);
	}
	return scopedObject;
}

我们可以看到以上源码,先从servletContext取,如果没有就从ioc容器取,然后放回servletContext。

@Bean
@ApplicationScope
public User user() {
    User user = new User();
    user.setId(1L);
    user.setName("张三");
    return user;
}

ApplicationScope的bean全局都存在,在jsp页面中这样获取值:

\${userObject.name} : ${userObject.name}
\${applicationScope['scopedTarget.user'].name} : ${applicationScope['scopedTarget.user'].name}

2、总结session、request、application作用域

application作用域用途并不广泛,并且很容易出问题。

其实,Bean的scope我们只需要掌握singleton、prototype就够了,session、request、application我们只需了解,其实这三个也有其他的解决方案,用途并不是很广泛。

七、自定义 Bean 作用域

我们这里自定义一个,基于线程的Scope。

1、自定义Scope,实现Scope接口

import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.Scope;
import org.springframework.core.NamedThreadLocal;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import java.util.HashMap;
import java.util.Map;

/**
 * ThreadLocal 级别 Scope
 * 自定义Scope
 */
public class ThreadLocalScope implements Scope {

    public static final String SCOPE_NAME = "thread-local";

    private final NamedThreadLocal<Map<String, Object>> threadLocal = new NamedThreadLocal("thread-local-scope") {

        public Map<String, Object> initialValue() { // 创建初始化数据
            return new HashMap<>();
        }
    };

    @Override
    public Object get(String name, ObjectFactory<?> objectFactory) {

        // 非空
        Map<String, Object> context = getContext();

        Object object = context.get(name);

        if (object == null) {
            object = objectFactory.getObject();
            context.put(name, object);
        }

        return object;
    }

    @NonNull
    private Map<String, Object> getContext() {
        return threadLocal.get();
    }

    @Override
    public Object remove(String name) {
        Map<String, Object> context = getContext();
        return context.remove(name);
    }

    @Override
    public void registerDestructionCallback(String name, Runnable callback) {
        // TODO
    }

    @Override
    public Object resolveContextualObject(String key) {
        Map<String, Object> context = getContext();
        return context.get(key);
    }

    @Override
    public String getConversationId() {
        Thread thread = Thread.currentThread();
        return String.valueOf(thread.getId());
    }
}

2、注册Scope

API - org.springframework.beans.factory.config.ConfigurableBeanFactory#registerScope

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;

/**
 * 自定义 Scope {@link ThreadLocalScope} 示例
 */
public class ThreadLocalScopeDemo {

    @Bean
    @Scope(ThreadLocalScope.SCOPE_NAME)
    public User user() {
        return createUser();
    }

    private static User createUser() {
        User user = new User();
        user.setId(System.nanoTime());
        return user;
    }

    public static void main(String[] args) {

        // 创建 BeanFactory 容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        // 注册 Configuration Class(配置类) -> Spring Bean
        applicationContext.register(ThreadLocalScopeDemo.class);

        applicationContext.addBeanFactoryPostProcessor(beanFactory -> {
            // 注册自定义 scope
            beanFactory.registerScope(ThreadLocalScope.SCOPE_NAME, new ThreadLocalScope());
        });

        // 启动 Spring 应用上下文
        applicationContext.refresh();

        scopedBeansByLookup(applicationContext);

        // 关闭 Spring 应用上下文
        applicationContext.close();
    }

    private static void scopedBeansByLookup(AnnotationConfigApplicationContext applicationContext) {

        for (int i = 0; i < 3; i++) {
            Thread thread = new Thread(() -> {
                // user 是共享 Bean 对象
                User user = applicationContext.getBean("user", User.class);
                System.out.printf("[Thread id :%d] user = %s%n", Thread.currentThread().getId(), user);
            });

            // 启动线程
            thread.start();
            // 强制线程执行完成
            try {
                thread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private static void scopedBeansByInjection(AnnotationConfigApplicationContext applicationContext) {
    }
}

八、Spring Cloud RefreshScope是如何控制Bean的动态刷新

1、我们发现,RefreshScope 注解是由@Scope(“refresh”)标注。

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Scope("refresh")
@Documented
public @interface RefreshScope {

	/**
	 * @see Scope#proxyMode()
	 * @return proxy mode
	 */
	ScopedProxyMode proxyMode() default ScopedProxyMode.TARGET_CLASS;

}

2、这里会发送一个监听

// org.springframework.cloud.context.scope.refresh.RefreshScope#refreshAll
@ManagedOperation(description = "Dispose of the current instance of all beans "
		+ "in this scope and force a refresh on next method execution.")
public void refreshAll() {
	super.destroy();
	this.context.publishEvent(new RefreshScopeRefreshedEvent());
}

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

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

相关文章

《哈希表》

【一】哈希概念 顺序结构以及平衡树中&#xff0c;元素关键码与其存储位置之间没有对应的关系&#xff0c;因此在查找一个元素时&#xff0c;必须要经过关键码的多次比较&#xff0c;顺序查找时间的复杂度为O(N),平衡树中为树的高度&#xff0c;即O(log2N),搜索的效率取决于搜…

JavaWeb技术栈概述

1.1 Web概述 Web是全球广域网&#xff0c;也称为万维网&#xff08;www&#xff09;&#xff0c;能够通过浏览器访问的网站。 在我们日常的生活中&#xff0c;经常会使用浏览器去访问百度、京东、传智官网等这些网站&#xff0c;这些网站统称为Web网站。如下就是通过浏览器访问…

实验三 第四章 MongoDB 副本集

一、实验目的&#xff1a; 了解MongoDB副本集 熟悉MongoDB副本集成员 掌握MongoDB副本集部署 掌握MongoDB副本集操作 理解副本集机制 二、实验环境&#xff1a; 一台win10系统的笔记本电脑 三、实验内容&#xff1a; 4.3部署副本集 4.3.1环境准备 创建的三台虚拟机配置如下&a…

python中的split()、rsplit()、splitlines()用法比较

1 split() 从左向右切割2 rsplit() 从右向左分割3 splitlines() 根据换行符切割4 rsplit()妙用split(分隔符&#xff0c;分割几次)从左向右寻找&#xff0c;分割元素并放入列表中&#xff0c;该分隔符丢弃&#xff1b; rsplit(分隔符&#xff0c;分割几次)从右向左寻找&#x…

算法的复杂性分析

算法的复杂性分析 文章目录算法的复杂性分析0、 算法评价的基本原则1、影响程序运行时间的因素2、算法复杂度2.1 算法的时间复杂度2.2 渐进表示法2.2.1 运行时间的上界2.2. 运行时间的下界2.2.3 运行时间的准确界3、总结4、参考0、 算法评价的基本原则 评价一个算法的好坏实际就…

第二证券|市场短期盘整 不改中期向好格局

12月初以来A股商场全体走势偏弱&#xff0c;上星期首要指数更是五连跌&#xff0c;上证指数重回3100点下方。关于商场近期的再度调整&#xff0c;本周组织观念显现&#xff0c;疫情带来的扰动或是首要原因。 不过&#xff0c;大都组织以为&#xff0c;心情面要素对商场的影响仅…

面试官:ui组件可以自动加载,那么业务组件可以吗?

大厂面试题分享 面试题库 前端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★ 地址&#xff1a;前端面试题库 背景 笔者在最近在公司接手了一个老的对内使用的项目&#xff0c;接手后体验了下 发现首屏加载比较慢。分析了下大概的原因是main.js挂…

算法进阶:双指针(一)c++leetcode例题

82. 删除排序链表的重复元素 力扣传送&#xff1a; https://leetcode.cn/problems/remove-duplicates-from-sorted-list-ii/description/ 给一个排好序的链表&#xff0c;删除把链表中出现的所有的重复的项&#xff1a; 1 2 2 3 3 3 4 5 -----> 1 4 5 这道题有很多种解法&a…

Unity3D——第一人称FPS生存游戏(resident zombies)

游戏源文件和游戏试玩程序:链接&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1Ln2tFizqEO_uEoQhuxvgrQ?pwdl6w0 提取码&#xff1a;l6w0 游戏思路前身搭建: 用一些正方体和胶囊做出来的基础场景&#xff0c; 人物设计:红色的胶囊体是敌人&#xff0c;手持枪械是…

一文说透BIO以及非阻塞IO

目录1. 一次I/O到底经历了什么2. 什么是Socket3. 阻塞I/O&#xff08;Blocking I/O&#xff0c;BIO&#xff09;3.1. 客户端的socket流程3.1.1. 何为socket&#xff1f;3.1.2. 何为连接&#xff1f;3.2. 服务端的socket流程3.2.1. 创建socket3.2.2. 绑定端口号3.2.3. listen()的…

项目实战之旅游网(六)认证与授权

一.编写相关页面 在本项目中&#xff0c;我们使用Spring Security 进行认证和授权&#xff0c;首先我们先编写相关页面。 1.编写登录页面admin_ login.html 2.编写登录失败页面admin_ fail.html 3.编写权限不足页面no_ permission.html 略过。知道其功能即可。 二.编写配置…

数字孪生城市可视化大屏设计,智慧楼宇开源项目

纵观城市发展历史&#xff0c;技术的革命必然会带动城市内部的变革。当前&#xff0c;以数字孪生为代表的前言信息技术飞速发展&#xff0c;必然会使社会对数字城市的深度和广度有着更为清晰的认知。加快构建数字孪生城市管理平台&#xff0c;通过三维可视化大屏直观展示&#…

图表控件LightningChart.NET 系列教程(六):许可证管理介绍(中)

LightningChart.NET SDK 是一款高性能数据可视化插件工具&#xff0c;由数据可视化软件组件和工具类组成&#xff0c;可支持基于 Windows 的用户界面框架&#xff08;Windows Presentation Foundation&#xff09;、Windows 通用应用平台&#xff08;Universal Windows Platfor…

Apache ShardingSphere-Proxy <5.3.0 存在身份认证绕过漏洞

漏洞描述 Apache ShardingSphere 是一款分布式的数据库生态系统&#xff0c;ShardingSphere-Proxy 是支持 MySQL、PostgreSQL 和 openGauss 协议的数据库代理模块。 ShardingSphere-Proxy 5.3.0 之前的版本中在使用 MySQL 作为后端数据库时&#xff0c;在客户端认证失败后没有…

Linux进程状态与优先级

Ⅰ. OS进程状态的概念 进程状态反映进程执行过程的变化。这些状态随着进程的执行和外界条件的变化而转换。 在三态模型中&#xff0c;进程状态分为 运行态&#xff0c;就绪态&#xff0c;阻塞态。 在五态模型中&#xff0c;进程状态分为 新建态、终止态&#xff0c;运行态&a…

服务雪崩预防Sentinel

服务雪崩效应 在分布式系统中,由于网络原因或自身的原因,服务一般无法保证 100% 可用。如果一个服务出现了 问题&#xff0c;调用这个服务就会出现线程阻塞的情况&#xff0c;此时若有大量的请求涌入&#xff0c;就会出现多条线程阻塞等 待&#xff0c;进而导致服务瘫痪。 由于…

【HTML+CSS+JavaScript】实现鼠标点击烟花效果

文章目录【HTMLCSSJavaScript】实现鼠标点击烟花效果&#xff08;爆炸型、心型、圆形&#xff09;一. 效果图二. 鼠标点击烟花效果 - 心型实现代码(1) HTML部分代码(2) CSS部分代码(3) 内部的JavaScript部分代码三. 鼠标点击烟花效果 - 圆型实现代码(1) HTML部分代码(2) CSS部分…

【mysql】优化系列文章之一-索引

mysql优化系列 不是教程&#xff0c;不是官方文档&#xff0c;而是自己实战的点滴记录&#xff0c;不一定适合新手和系统学习者 第一章 mysql索引 文章目录mysql优化系列前言1、Mysql索引2、B Tree2.1.特点2.2. 结构分解2.3. 例题分析2.4. 验证索引2.5.索引插入耗时3. MySQL 中…

Oracle数据库同步复制工具Beedup产品功能(一)

1、全量复制 Beedup全量复制功能通过遍历比对主从库用户模式及其下包含的各类对象来保证主从库的相关对象一致性。 支持角色、用户、架构、登录用户、表 (列定义 主外键 索引)、视图存储过程、函数、触发器、类型、类型体、包、包体、序列、同义词、数据库链接等对象复制全量…

技术干货 | 人大金仓KFS基于分区索引的分片入库技术解析

在之前的文章《技术干货&#xff1a;人大金仓KFS精准过滤和分片并行入库技术解析》中&#xff0c;KFS利用分片并行入库技术&#xff0c;解决了某金融POC数据同步项目中数据入库持续积压问题。经过优化后&#xff0c;在200并发的压测场景中&#xff0c;整体同步性能指标从压测30…