【Spring源码分析】BeanFactory系列接口解读

news2025/1/11 17:44:03

认识Bean工厂

  • 一、认识Bean工厂
    • BeanFactory
    • ListableBeanFactory
    • HierarchicalBeanFactory
    • AutowireCapableBeanFactory
    • ConfigurableBeanFactory
    • ConfigurableListableBeanFactory
  • 二、总结

一、认识Bean工厂

Spring Bean 工厂是Spring框架提供的一种机制,用于创建和管理对象(或称为Bean)。它是Spring框架的核心部分,提供了一种灵活、可配置的方式来管理对象的生命周期和依赖关系

下面展示了整个 Bean 工厂的常见接口和类以及功能(其中 XmlBeanFactory 已经被弃用):

1671758309265

1、不同的接口展现了不同的能力,是对子类能力的抽象;

2、 抽象类构建通用方法的实现,是通用核心方法的具体实现;

3、 具体类完成特定功能的实现,是特定功能的具体实现;

BeanFactory

public interface BeanFactory {

	// 这个变量在获取一个 FactoryBean 的时候使用
	// 定义 FactoryBean 时的前缀
	String FACTORY_BEAN_PREFIX = "&";

	// 工厂的核心方法,提供了多种获取单个实例bean的能力
	// 有不同的获取方式:别名直接获取、别名+参数,根据对应构造获取、类型注入
	Object getBean(String name) throws BeansException;
	<T> T getBean(String name, Class<T> requiredType) throws BeansException;
	Object getBean(String name, Object... args) throws BeansException;
	<T> T getBean(Class<T> requiredType) throws BeansException;
	<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;


	// 返回对应的 ObjectProvider,这是一种可以延迟获取 bean 实例的模式
	// 比如基于 ObjectProvider#getIfUnique 方法获取实例(获取容器中的对象)
	<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);
	<T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);

	// 判断是否包含指定 name 的 bean Definition 或 单例
	// 此处返回 true 并不意味着 getBean 可以返回对应的实例
	boolean containsBean(String name);

	// 判断 name 对应的 bean 是否是单例
	boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
	// 判断 name 对应的 bean 是否是原型(prototype)
	boolean isPrototype(String name) throws NoSuchBeanDefinitionException;


	// 判断指定 name 的bean是否匹配对应的类型
	boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
	boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;

	// 获取 name 对应的 bean 的类型
	@Nullable
	Class<?> getType(String name) throws NoSuchBeanDefinitionException;
	@Nullable
	Class<?> getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException;

	// 返回指定 name 的所有别名
	String[] getAliases(String name);

}

在 Spring4.3 之前,我们的bean如果需要使用特定构造器进行构造时必须使用@Autowired注解:

@Service
public class UserService {
    
    private UserDao userDao;
	@Autowired
    public UserService(UserDao userDao) {
        this.userDao = userDao;
    }
}

在 Spring4.3 之后,如果没有其他构造器(有无参构造默认会使用无参构造,当然如果无参也没有,还有多个有参),会隐式为其注入:

@Service
public class UserService {

    UserDao userDao;
    
    public UserService(UserDao userDao) {
        this.userDao = userDao;
    }
}

但是当容器中没有 UserDao 这个 Bean 的时候,就会报以下异常:

在这里插入图片描述

此时 ObjectProvider 就提供了它的作用了:

@Service
public class UserService {

    UserDao userDao;

    public UserService(ObjectProvider<UserDao> objectProvider) {
        // 如果容器中存在就返回,不存在返回null
        this.userDao = objectProvider.getIfUnique();
    }

}

在这里插入图片描述

这样注入的好处很明显,就是如果容器中不存在 UserDao 或者存在多个 UserDao 时,可以从容处理。

ObjectProvider 接口如下,他继承自 ObjectFactory,这个接口后边也会常用:

public interface ObjectProvider<T> extends ObjectFactory<T>, Iterable<T> {

	T getObject(Object... args) throws BeansException;

    // 处理判断有可用的bean的时候我们怎么做,可以重写
	T getIfAvailable() throws BeansException;
	default T getIfAvailable(Supplier<T> defaultSupplier) throws BeansException {
		T dependency = getIfAvailable();
		return (dependency != null ? dependency : defaultSupplier.get());
	}
	default void ifAvailable(Consumer<T> dependencyConsumer) throws BeansException {
		T dependency = getIfAvailable();
		if (dependency != null) {
			dependencyConsumer.accept(dependency);
		}
	}

    // 处理判断只有唯一的bean的时候我们怎么做,可以重写
	T getIfUnique() throws BeansException;
	default T getIfUnique(Supplier<T> defaultSupplier) throws BeansException {
		T dependency = getIfUnique();
		return (dependency != null ? dependency : defaultSupplier.get());
	}
	default void ifUnique(Consumer<T> dependencyConsumer) throws BeansException {
		T dependency = getIfUnique();
		if (dependency != null) {
			dependencyConsumer.accept(dependency);
		}
	}

    // 当匹配多个时,可以迭代处理
	@Override
	default Iterator<T> iterator() {
		return stream().iterator();
	}
}


ObjectFactory 作为一个对象工厂函数式接口更是简单:

@FunctionalInterface
public interface ObjectFactory<T> {

	/**
	 * Return an instance (possibly shared or independent)
	 * of the object managed by this factory.
	 * @return the resulting instance
	 * @throws BeansException in case of creation errors
	 */
	T getObject() throws BeansException;

}

ListableBeanFactory

该工厂继承自 BeanFactory,在含有Bean基础功能的基础上,提供了更强的枚举能力。ListableBeanFactory 为后续的实现类提供了更强的枚举能力,这些能力可能不对外公开,但是对于子类操作容器的操作bean十分重要,下面是他提供的方法:

public interface ListableBeanFactory extends BeanFactory {
	
    // 对BeanDefinition的一些细节操作
	boolean containsBeanDefinition(String beanName);
	int getBeanDefinitionCount();
    String[] getBeanDefinitionNames();
    
    // 对 BeanFactory 中获取ObjectProvider方法的拓展
    <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType, boolean allowEagerInit);
    <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType, boolean allowEagerInit);
    
    // 获取指定类型(子类)的bean names
    // boolean includeNonSingletons 参数决定是否考虑 singleotn 以外的bean
    // boolean allowEagerInit 是否初始化对应FactoryBean,如果false则类型直接匹配对应的FactoryBean
    String[] getBeanNamesForType(ResolvableType type);
    String[] getBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit);
    String[] getBeanNamesForType(@Nullable Class<?> type);
    String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit);
    
    /**
    	基本同上,返回的 Map 结构
    	k:beanName
    	v:beanInstance
    **/
    <T> Map<String, T> getBeansOfType(@Nullable Class<T> type) throws BeansException;
	<T> Map<String, T> getBeansOfType(@Nullable Class<T> type, boolean includeNonSingletons, boolean allowEagerInit)
			throws BeansException;

    // 返回指定注解的beanName数组
    String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType);
    
    // 返回指定注解的bean实例集合:beanName -> bean 实例
    Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) throws BeansException;
    
    // 获取指定 beanName 上的注解
    // 同样涉及 FactoryBean 初始化的问题,由参数 allowFactoryBeanInit 决定
    @Nullable
	<A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
			throws NoSuchBeanDefinitionException;
    @Nullable
	<A extends Annotation> A findAnnotationOnBean(
			String beanName, Class<A> annotationType, boolean allowFactoryBeanInit)
			throws NoSuchBeanDefinitionException;
    <A extends Annotation> Set<A> findAllAnnotationsOnBean(
			String beanName, Class<A> annotationType, boolean allowFactoryBeanInit)
			throws NoSuchBeanDefinitionException;
}    

BeanFactory 的子接口:

  • 拓展了枚举的能力,提供了多个枚举的方法;
  • 这些方法都仅限于当前层级的枚举,如果需要考虑到父级,可以借助 BeanFactoryUtils.
  • containsBeanDefinition、getBeanDefinitionCount、getBeanDefinitionNames 这几个方法是完全基于当前 BeanFactory 中的 BeanDefinition 的,换句话说,对于通过 registerSingleton 等方法注册的 bean 实例,它们是不感知的
  • getBeanNamesForType、getBeansOfType 方法是会感知自行注册 bean 实例的,当然大多数场景的 bean 实例都是基于 BeanDefinition 扫描的。

HierarchicalBeanFactory

HierarchicalBeanFactory 为 bean 工厂提供了灵活的分层能力,这在 web 工程里由典型的应用,spring 和 springmvc 会建立两个独立的上下文,分层之后各司其职,更易管理

public interface HierarchicalBeanFactory extends BeanFactory {
	
    // 返回 bean 工厂的父工厂
	@Nullable
	BeanFactory getParentBeanFactory();
	// 此方法忽略祖先上下文定义的bean,只会查询本地工厂
	boolean containsLocalBean(String name);

}

测试一手:

	@Test
    public void testHierarchicalBeanFactory() {
        // 创建一个核心工厂
        DefaultListableBeanFactory parent = new DefaultListableBeanFactory();
        parent.registerSingleton("person1", new Person("张三", 18));
        // 创建一个子工厂工厂,独自管理各个层次的内容
        DefaultListableBeanFactory child = new DefaultListableBeanFactory();
        // 设置父子关联关系
        child.setParentBeanFactory(parent);
        // 子工厂可以访问父工厂的bean
        log.info("{}", child.getBean("person1"));
        log.info("{}", child.containsBean("person1"));
        // containsLocalBean()方法判断当前工厂是否包含指定的bean,如果是,则返回true,否则返回false
        log.info("{}", child.containsLocalBean("person1"));
    }

BeanFactory 的 子接口:

  • 提供了层次关系维护,getParentBeanFactory 用于获取父 BeanFactory
  • containsLocalBean 不同于 BeanFactory#containsBean,只会在当前层级中判断是否存在指定 namebean实例.

AutowireCapableBeanFactory

这个接口提供了构建和自动装配的能力,主要是赋予子类自动装配的能力,是容器最核心的接口,这个接口定义了 bean 的创建以及装配能力,同时细粒度的控制了 bean 的生命周期

public interface AutowireCapableBeanFactory extends BeanFactory {
    // 表示不进行自动注入,默认情况下都是该状态
    // 真正的注入,一般都是基于 @Autowire 等注解驱动
    int AUTOWIRE_NO = 0;
    // 基于属性 name 的自动注入模式,一般不用
    int AUTOWIRE_BY_NAME = 1;
    // 基于属性 type 的自动注入模式,@Bean 方式就是这种模式
    int AUTOWIRE_BY_TYPE = 2;
    // 基于构造方法的自动注入,一般不用
    int AUTOWIRE_CONSTRUCTOR = 3;
    // 通过此后缀获取原始实例(比如 代理实例的 target)
    String ORIGINAL_INSTANCE_SUFFIX = ".ORIGINAL";
    
    // 创建实例的典型方法
    <T> T createBean(Class<T> beanClass) throws BeansException;
    
    // 自动填充指定 bean  实例属性,本质上是 after-instantiation 和 property post-processing 回调的执行
    void autowireBean(Object existingBean) throws BeansException;
    
    // 配置给定 bean 实例,本质是属性填充以及初始化回调的执行
    Object configureBean(Object existingBean, String beanName) throws BeansException;
    
    //--------------------------------------------------------------------
    // 用于对bean生命周期进行细粒度控制的专门方法
    // 主要是三块内容:创建(实例化) 属性填充(装配) 初始化
    //--------------------------------------------------------------------
    
    /**
    	生命周期第一步(创建)
    	按照指定的装配策略根据class生成一个完整的bean的实例
    	执行bean的完全初始化,包括所有适用的beanpostprocessors
    	@param dependencyCheck 是否对对象执行依赖项检查(不适用于自动装配构造函数,因此忽略)
	 	@return 新的bean的实例
    **/
    Object createBean(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;
    
    
    /**
    	生命周期第二步(装配)
    	基于 autowireMode 创建 bean 实例并自动填充
    	通过应用 after-instantiation 和 property post-processing(例如注解驱动的注入)
    	来填充给定的bean实例
    **/
    Object autowire(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;
    
    
    /**
	 * 基于 autowireMode 自动填充已经存在的 bean 实例
	 * 已经存在的实例不支持 AUTOWIRE_CONSTRUCTOR 
	 */
    void autowireBeanProperties(Object existingBean, int autowireMode, boolean dependencyCheck)
			throws BeansException;
    
    /**
	 * 基于 BeanDefinition 的属性填充已存在的 bean 实例
	 */
	void applyBeanPropertyValues(Object existingBean, String beanName) throws BeansException;
    
    // 初始化前的回调
    // 将 BeanPostProcessors 应用到给定的现有bean实例
    // 调用它们的postprocessBeforeInitialization方法
    Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
			throws BeansException;
    
    // 初始化给定的原始 bean,应用工厂回调,如setBeanName和setBeanFactory
    // 当然也包括应用所有的bean postprocessors
    Object initializeBean(Object existingBean, String beanName) throws BeansException;
    
    // 初始化后置处理
    Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
			throws BeansException;
    
    // 销毁给定的bean实例
    // 使用DisposableBean接口定义的销毁方法
    void destroyBean(Object existingBean);
    
    //-------------------------------------------------------------------------
	// 解决匹配注入点的方法
    // 在注入的时候通过以下的方法匹配属性与之对应的bean
	//-------------------------------------------------------------------------

	/**
	 * 解析唯一匹配给定对象类型(如果有的话)的bean实例,包括它的bean名称。
	 * 比如我们调用getBean(User.class) 会匹配一个或多个bean,需要该方法进行选择
	 * 这实际上是getBean(Class)的一个变体。
	 */
	<T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType) throws BeansException;

	/**
	 * 解析给定bean名称的bean实例, 向目标工厂方法公开提供依赖描述符。
	 * 这实际上是getBean(String, Class)的一个变体,
	 */
	Object resolveBeanByName(String name, DependencyDescriptor descriptor) throws BeansException;

	/**
	 * 针对此工厂中定义的bean解析指定的依赖项,注入的时候很有用。
	 * 通过一个依赖的描述(对方法,字段,构造器的抽象),获得一个bean
	 */
	@Nullable
	Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName) throws BeansException;

}
    

BeanFactory 的 子接口:

  • 拓展了 自动注入 等相关能力
  • 它的能力被单独拎出来,因此允许非 Spring 组件的实例也借助它来实现自动装配;
  • 它的功能没有暴露给 ApplicationContext,但是在 ApplicationContext 上下文中,可以通过 ApplicationContext#getAutowireCapableBeanFactory 获取该实例,当然也可以直接获取 BeanFactory 进行类型转换。
  • 它定义了不同的粒度生命周期的相关方法,基于主要的几个里程碑比如 实例的创建 属性的填充 初始化回调 来划分,一般 Spring 内部自然是对 bean 实例执行全过程的生命周期。

ConfigurableBeanFactory

它是 HierarchicalBeanFactory 的子接口,在基础能力和分层能力之上拓展了配置能力,这是 Spring 常用的类设计模式,这一层抽象了所有 BeanFactory 类相关组件的维护,比如:

  • BeanExpressionResolverSpEL 解析器
  • ConversionService:转换服务
  • TypeConverter:类型转换的顶层接口,相当于整合了 ConversionServicePropertyEditorRegistry
  • BeanPostProcessor:支持添加 BeanPostProcessorbean实例 进行后处理
  • 等等
public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry {
    
    // 标准单例作用域的范围标识符:"singleton".自定义作用域可以通过 registerScope 添加
    String SCOPE_SINGLETON = "singleton";
    String SCOPE_PROTOTYPE = "prototype";
    
    // 设置此 bean 工厂的父级
    void setParentBeanFactory(BeanFactory parentBeanFactory) throws IllegalStateException;
    
    // 将 classLoader 设置为加载中的 bean 类,默认是线程上下文类装入器
    void setBeanClassLoader(@Nullable ClassLoader beanClassLoader);
    
    // 返回这个工厂的classLoader,用于加载bean类
    @Nullable
	ClassLoader getBeanClassLoader();
    
    /**
	 * 指定一个临时ClassLoader用于类型匹配,默认为none。
	 * 如果涉及到加载时织入,则通常只指定临时ClassLoader,以确保实际的bean类尽可能延迟地加载。
	 * 一旦BeanFactory完成引导阶段,临时加载器就会被移除。
	 */
	void setTempClassLoader(@Nullable ClassLoader tempClassLoader);

	// 返回用于类型匹配的临时ClassLoader,
	ClassLoader getTempClassLoader();
    
    /**
    	设置是否缓存bean元数据,例如给定的bean定义(以合并的方式)和 resolved bean classes
    	关闭此标志可启动 bean Definition 和 特定bean类的热刷新
    	如果该标志关闭,则任何bean实例的创建都将重新查询 bean class Loader 以获得新解析的类。
    **/
    void setCacheBeanMetadata(boolean cacheBeanMetadata);
    boolean isCacheBeanMetadata();
    
    // 设置和获取SpEL表达式解析器
    void setBeanExpressionResolver(@Nullable BeanExpressionResolver resolver);
    @Nullable
	BeanExpressionResolver getBeanExpressionResolver();
    
    // 设置和获取转化服务
    void setConversionService(@Nullable ConversionService conversionService);
    @Nullable
	ConversionService getConversionService();
    
    // 添加属性编辑器
    void addPropertyEditorRegistrar(PropertyEditorRegistrar registrar);
    void registerCustomEditor(Class<?> requiredType, Class<? extends PropertyEditor> propertyEditorClass);
    void copyRegisteredEditorsTo(PropertyEditorRegistry registry);
    
    // 配置和获取类型转化器,相当于整合了 ConversationService 和 PropertyEditorRegister
    void setTypeConverter(TypeConverter typeConverter);
    TypeConverter getTypeConverter();
    
    // 为注入的值添加一个String解析器,如“aa${bb}cc”。
    void addEmbeddedValueResolver(StringValueResolver valueResolver);
    boolean hasEmbeddedValueResolver();
	String resolveEmbeddedValue(String value);
    
    // 添加和获取bean的后置处理器
    void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);
    int getBeanPostProcessorCount();
    
    // 注册自定义的作用范围
    void registerScope(String scopeName, Scope scope);
    String[] getRegisteredScopeNames();
    @Nullable
	Scope getRegisteredScope(String scopeName);
    
    // 为这个bean工厂设置{ApplicationStartup} 用来记录启动步骤
    void setApplicationStartup(ApplicationStartup applicationStartup);
    ApplicationStartup getApplicationStartup();
    
    // 从一个bean工厂进行拷贝配置
    void copyConfigurationFrom(ConfigurableBeanFactory otherFactory);
    
    // 注册别名
    void registerAlias(String beanName, String alias) throws BeanDefinitionStoreException;
    
    // 获取合并的bean的定义(RootBeanDefinition)
    BeanDefinition getMergedBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
    
    // 是否是工厂bean
    boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException;
    
    // 控制指定bean当前的创建状态,仅供容器内部使用
    void setCurrentlyInCreation(String beanName, boolean inCreation);
    // 判断该bean是否在创建中
    boolean isCurrentlyInCreation(String beanName);
    
    // 为给定的bean注册一个依赖bean,在给定的bean被销毁之前销毁它
    void registerDependentBean(String beanName, String dependentBeanName);
    
    // 如果有的话,返回指定bean的所有bean的名称
    String[] getDependentBeans(String beanName);
    // 如果有的话,返回指定bean所依赖的所有bean的名称
    String[] getDependenciesForBean(String beanName);
    
    // 根据 bean 名称销毁给定的bean实例(通常是从该工厂获得的原型实例)
    void destroyBean(String beanName, Object beanInstance);
    
    // 销毁指定的【作用域bean】
    void destroyScopedBean(String beanName);
    
    // 销毁此工厂中的所有单例 Bean
    // 包括已注册一次性的内部bean。
    void destroySingletons();

ConfigurableListableBeanFactory

ConfigurableListableBeanFactory 把以上功能都整合在了一起,且拓展了核心方法 preInstantiateSingletons.

该方法用于在实例化 Bean 之前提前实例化单例Bean的,它首先迭代所有单例 Bean 的定义并检查是否是非延迟初始化的,并且如果是工厂 Bean,则还会检查是否需要提前初始化。然后,它会触发所有适用的Bean的后期初始化回调,并执行。

二、总结

  • BeanFactory:顶层接口,提供了最基础的方法,譬如:getBean、containBean
  • HierarchicalBeanFactory,子接口,拓展了 层次关系
  • ListableBeanFactory,子接口,拓展了 枚举 能力
  • AutowireCapableBeanFactory,子接口,拓展了 自动装配 能力
  • ConfigurableBeanFactory,子接口,拓展了相关组件 可配置化 的能力
  • ConfigurableListableBeanFactory,集大成者,直接实现类是 DefaultListableBeanFactory。

参考文献:

【源码】Spring —— BeanFactory 解读 1 BeanFactory 系列接口

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

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

相关文章

艺术的维度:洞察AI诈骗,优雅防范之艺术

当前&#xff0c;AI技术的广泛应用为社会公众提供了个性化智能化的信息服务&#xff0c;也给网络诈骗带来可乘之机&#xff0c;如不法分子通过面部替换语音合成等方式制作虚假图像、音频、视频仿冒他人身份实施诈骗、侵害消费者合法权益。 以下是一些常见的AI诈骗例子&#xf…

SurfaceFlinger的硬件Vsync深入分析-千里马android framework车机手机系统开发

背景&#xff1a; 学过或者你看过surfaceflinger相关文章同学都知道&#xff0c;vsync其实都是由surfaceflinger软件层面进行模拟的&#xff0c;但是软件模拟有可能会有误差或偏差&#xff0c;这个时候就需要有个硬件vsync帮忙校准。 故才会在surfaceflinger的systrace出现如下…

MFC串口通信(SerialPort)

目录 1、SerialPort类的介绍和使用&#xff1a; &#xff08;1&#xff09;、SerialPort类的功能介绍 &#xff08;2&#xff09;、SerialPort类提供接口函数的介绍 1&#xff09;、InitPort函数 2&#xff09;、控制串口监视线程函数 3&#xff09;、获取事件&#xff0c…

一文读懂从 CPU 多级缓存 缓存一致性协议(MESI)到 Java 内存模型

文章目录 CPU 多级缓存 & 缓存一致性协议&#xff08;MESI&#xff09;CPU 多级缓存缓存一致性协议&#xff08;MESI&#xff09;缓存行&#xff08;Cache line&#xff09;四种缓存状态缓存行状态转换多核协同示例网站体验 MESI优化和引入的问题Store Bufferes & Inva…

笔记软件 Keep It mac v2.3.3中文版新增功能

Keep It mac是一款专为 Mac、iPad 和 iPhone 设计的笔记和信息管理应用程序。它允许用户在一个地方组织和管理他们的笔记、网络链接、PDF、图像和其他类型的内容。Keep It 还具有标记、搜索、突出显示、编辑和跨设备同步功能。 Keep It for mac更新日志 修复了更改注释或富文本…

Technology Strategy Pattern 学习笔记5 -Creating the Strategy-Department Context

Creating the Strategy-Department Context 1 situations This pattern helps you organize your thoughts, and consider the department holistically in the following situations 1.1 •Aligning teams around a vision, especially a new direction 1.2 •Setting up a …

图像置乱加密的破解方法

仅仅通过置乱的方式,是无法对图像进行安全加密的。 针对采用置乱方式加密,可以采用多对(明文、密文)推导出加密时所使用的置乱盒。 step1 :初始化 1、使用I表示明文,E表示密文,彼此间关系如下: 2、为了处理上的方便,把二维转换为一维(这里为了说明方便,实际上,大…

2023年金融科技建模大赛(初赛)开箱点评-基于四川新网银行数据集

各位同学大家好&#xff0c;我是Toby老师。2023年金融科技建模大赛&#xff08;初赛&#xff09;从今年10月14日开始&#xff0c;11月11日结束。 比赛背景 发展数字经济是“十四五”时期的重大战略规划。2023年&#xff0c;中共中央、国务院印发了《数字中国建设整体布局规划》…

Tomcat免安装版修改标题名称和进程

tomcat免安装版启动后闪退问题 问题描述 在官网下载的tomcat免安装版的你安装完环境后发现启动闪退&#xff0c;tomcat启动依赖环境是JDK&#xff0c;所以需要tomcat对应版本的JDK支持。 tomcat8官网下载地址&#xff1a;https://tomcat.apache.org/ JDK环境官网下载地址&…

【python 深拷贝与浅拷贝】

python 深拷贝与浅拷贝 问题&#xff1a; 在用影刀编写流程的时候发现&#xff0c;明明只修改人名为“小张”对应的字典里面的值&#xff0c;但是所有的人名对应的值都被修改了。 原因&#xff1a; 第14行&#xff0c;设置键值对&#xff0c;值对应的变量“初始打卡类型字…

Java 多线程的三大特性

在JAVA中&#xff0c;线程有原子性、可见性和有序性三大特性。 1.原子性 1.1 定义 对于涉及共享变量的操作&#xff0c;若该操作从其执行线程以外的任意线程来看都是不可分割的&#xff0c;那么我们就说该操作具有原子性。它包含以下两层含义&#xff1a; 访问&#xff08;读、…

基于8086的出租车计价器系统设计

**单片机设计介绍&#xff0c;1665基于8051单片机与1601LCD的计算器设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 一个基于8086的出租车计价器系统可以分为硬件和软件两部分。 硬件部分包括输入设备&#xff08;例如计价器…

LangChain+LLM实战---Midjourney高级技巧的极简教程

原文&#xff1a;An advanced guide to writing prompts for Midjourney ( text-to-image) 作者&#xff1a;Lars Nielsen Midjourney生成的图像&#xff0c;文本Prompt&#xff1a;beautiful, fantasy city unreal engine 一句话介绍midjourney ? 对于那些还没有听说过Mid…

【教3妹学编程-java基础5】java多态详解

3妹&#xff1a;“太阳当空照&#xff0c;花儿对我笑&#xff0c;小鸟说早早早&#xff0c;你为什么背上炸药包” 2哥 :3妹&#xff0c;什么事呀这么开心呀。 3妹&#xff1a;2哥你看今天的天气多好啊&#xff0c;阳光明媚、万里无云、秋高气爽&#xff0c;适合秋游。 2哥&…

Zinx框架-游戏服务器开发003:架构搭建-需求分析及TCP通信方式的实现

文章目录 1 项目总体架构2 项目需求2.1 服务器职责2.2 消息的格式和定义 3 基于Tcp连接的通信方式3.1 通道层实现GameChannel类3.1.1 TcpChannel类3.1.2 Tcp工厂类3.1.3 创建主函数&#xff0c;添加Tcp的监听套接字3.1.4 代码测试 3.2 消息类的结构设计和实现3.2.1 消息的定义3…

【Agent模型1】MemGPT: Towards LLMs as Operating Systems

论文标题&#xff1a;MemGPT: Towards LLMs as Operating Systems 论文作者&#xff1a;Charles Packer, Vivian Fang, Shishir G. Patil, Kevin Lin, Sarah Wooders, Joseph E. Gonzalez (UC Berkeley) 论文原文&#xff1a;https://arxiv.org/abs/2310.08560 论文出处&#x…

分享86个工作总结PPT,总有一款适合您

分享86个工作总结PPT&#xff0c;总有一款适合您 PPT下载链接&#xff1a;https://pan.baidu.com/s/12aRTr5NKG5YTnMnwNbqOrQ?pwd8888 提取码&#xff1a;8888 Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 学习知识费力气&#xff0c;收集整理更不易。知…

delphi 监测某音新增评论以及解决x-bogus签名验证(2023-11-5)

一、工作原理及流程&#xff1a; 1、从aweme接口取得aweme评论总数量&#xff1b; 2、与之前的数量比较&#xff0c;如果有新增评论&#xff1b; 3、从comment评论接口统计评论以及评论回复数量&#xff0c;得出新增评论数量&#xff1b; 4、按时间排序评论&#x…

Oracle(13)Maintaining Data Integrity

目录 一、基础知识 1、Data Integrity 数据库的完整性 2、Types of Constraints 约束类型 3、Constraint States 约束状态 4、Guidelines for Constraints 约束准则 二、基础操作 1、Enabling Constraints 启用约束 2、命令方式创建约束 3、修改表创建的约束 4、删除约…

【移远QuecPython】EC800M物联网开发板调用网络API(使用SIM卡联网并调用高德地图API的定位坐标转换)

【移远QuecPython】EC800M物联网开发板调用网络API&#xff08;使用SIM卡联网并调用高德地图API的定位坐标转换&#xff09; 高德API使用方法&#xff1a; 文章目录 API相关配置SIM卡联网网络操作API调用 高德地图API产品介绍适用场景使用限制使用说明坐标转换 附录&#xff…