Spring源码十:BeanPostProcess

上一篇Spring源码九:BeanFactoryPostProcessor,我们看到ApplicationContext容器通过refresh方法中的postProcessBeanFactory方法和BeanFactoryPostProcessor类提供预留扩展点,他可以在Spring容器的层面对BeanFactroy或其他属性进行修改,所以我们经常说BeanFactoryPost Processor是Spring容器层面的一个扩展点。

但是,我们除了在容器层面外我们有没有粒度更小一点的扩展处理呢?比我们能否直接修改我们的Bean呢?

接下来咱们进入Spring给我们预留另外一个比较重要的扩展点,也就是我们bean的后置处理器BeanPost Processor。

BeanPostProcessor初探

在Spring框架中,BeanPostProcessor是一个核心接口,它允许我们在Spring容器实例化、配置和初始化Bean之前或之后进行一些额外的处理。通过实现这个接口,我们可以在Bean的生命周期的特定点插入自定义逻辑,以增强或修改Bean的行为。本文将深入探讨BeanPostProcessor的定义、用途、使用实例、注册方式以及其在Spring应用中的重要性和应用场景。

1. BeanPostProcessor接口定义

BeanPostProcessor接口定义了两个主要方法:

public interface BeanPostProcessor {
    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
  • postProcessBeforeInitialization:在Bean初始化之前被调用。这通常指的是在Bean的init-method或者实现了InitializingBean接口的afterPropertiesSet方法之前。
  • postProcessAfterInitialization:在Bean初始化之后被调用。

这些方法的主要作用是允许开发者在Bean的初始化过程中进行定制化处理,这种处理可以是对Bean属性的修改、添加日志、检查标记接口或对Bean进行代理等操作。

2. BeanPostProcessor的目的与应用

BeanPostProcessor的主要目的是通过改进Bean的初始化过程,提高Spring容器中Bean的管理和使用效率。具体应用场景包括:

  • 属性修改:在Bean初始化之前或之后,对Bean的某些属性进行修改,以满足特定需求。
  • 日志记录:在Bean的初始化过程中,记录日志信息,以便于调试和监控。
  • 标记接口检查:检查Bean是否实现了特定的标记接口,并根据检查结果进行相应处理。
  • 代理增强:对Bean进行代理,以添加额外的功能,例如AOP(面向切面编程)中的增强功能。
3. BeanPostProcessor使用实例

下面是一个简单的使用实例,展示了如何在Bean初始化前后添加日志:

@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("Before Initialization: " + beanName);
        return bean;
    }
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("After Initialization: " + beanName);
        return bean;
    }
}

在这个例子中,我们实现了BeanPostProcessor接口,并在postProcessBeforeInitializationpostProcessAfterInitialization方法中分别添加了日志输出。这使得每当一个Bean在初始化之前或之后,这两个方法都会被调用,并输出相应的日志信息。

4. BeanPostProcessor的注册

要使BeanPostProcessor生效,必须将其注册到Spring容器中。注册方式有多种,包括注解配置、XML配置和Java配置。

  • 注解配置:如果使用@Component注解,Spring会自动检测并注册BeanPostProcessor:
@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {
    // 方法实现如上
}
  • XML配置:在XML文件中显式声明BeanPostProcessor:
<bean class="com.example.CustomBeanPostProcessor" />
  • Java配置:通过@Bean注解注册BeanPostProcessor:
@Configuration
public class AppConfig {
    @Bean
    public BeanPostProcessor customBeanPostProcessor() {
        return new CustomBeanPostProcessor();
    }
}
5. BeanPostProcessor的工程化应用

BeanPostProcessor在工程化应用中具有重要意义。通过在Bean的生命周期中插入定制化逻辑,开发者可以实现许多高级功能,例如:

  • AOP(面向切面编程):通过代理技术,在Bean的方法调用前后添加额外逻辑,例如日志记录、事务管理、安全检查等。
  • 依赖注入的增强:在Bean初始化前后对其依赖进行进一步的配置和优化,例如动态注入特定依赖。
  • Bean管理:在Bean的整个生命周期中,进行统一的管理和监控,例如资源的初始化和释放、性能监控等。
6. 深入理解BeanPostProcessor的工作机制

为了更好地理解BeanPostProcessor的工作机制,我们需要了解Spring容器的初始化过程。Spring容器在启动时,会进行以下几个主要步骤:

  1. 实例化Bean:Spring容器根据配置文件或注解,实例化所有的Bean。
  2. 属性注入:为每个Bean注入其依赖的属性,这些属性可以是其他Bean、基本类型、集合等。
  3. 调用BeanPostProcessor:在Bean初始化前后,调用所有注册的BeanPostProcessor的方法。
  4. 调用初始化方法:如果Bean实现了InitializingBean接口,调用其afterPropertiesSet方法;如果配置了init-method,则调用该方法。
  5. Bean就绪:Bean已经准备好,可以被应用程序使用。

在这个过程中,BeanPostProcessor的两个方法分别在第3步和第4步之间被调用,允许开发者在Bean的生命周期的关键节点进行干预和自定义操作。

7. 实践中的BeanPostProcessor应用

在实际开发中,BeanPostProcessor的应用非常广泛,下面列举几个常见的使用场景:

  • 自定义初始化逻辑:通过在postProcessBeforeInitialization方法中添加逻辑,可以在Bean初始化之前执行一些自定义操作。例如,为Bean的某些属性设置默认值,或进行特定的初始化操作。
  • 动态代理:在postProcessAfterInitialization方法中,可以使用JDK动态代理或CGLIB代理,为Bean添加AOP增强。例如,为某些方法添加事务管理、日志记录或安全检查。
  • 注解处理:通过在Bean初始化前后扫描特定注解,可以实现注解驱动的配置。例如,自定义注解用于标记需要进行特定处理的Bean,并在BeanPostProcessor中实现相应的逻辑。
8. BeanPostProcessor与其他Spring机制的结合

BeanPostProcessor常常与Spring的其他机制结合使用,以实现更复杂和强大的功能。例如:

  • BeanFactoryPostProcessor结合BeanFactoryPostProcessor允许在Bean定义加载后、Bean实例化前进行配置修改。通过结合使用这两个接口,可以在Bean定义和实例化的不同阶段进行干预,提供更细粒度的控制。
  • ApplicationContextAware结合:实现ApplicationContextAware接口的Bean可以获取到ApplicationContext实例,通过在BeanPostProcessor中对这些Bean进行处理,可以实现对整个应用上下文的操作。
  • @PostConstruct@PreDestroy结合:在Bean的生命周期中,通过BeanPostProcessor和这两个注解,可以实现复杂的初始化和销毁逻辑。例如,在Bean初始化后,调用特定方法进行资源的分配或初始化。
9. 高级使用技巧

在高级使用场景中,BeanPostProcessor可以用于实现更复杂的功能,例如:

  • 多层次代理:通过在postProcessAfterInitialization方法中多次对Bean进行代理,可以实现多层次的功能增强。例如,先添加事务管理,再添加日志记录。
  • 条件处理:在BeanPostProcessor中,可以根据特定条件对Bean进行不同的处理。例如,根据Bean的类型或注解,选择性地进行某些操作。
  • 性能优化:通过在Bean初始化前后进行性能监控,可以识别出性能瓶颈,并采取相应的优化措施。例如,记录Bean初始化的时间,找出耗时较长的操作。

BeanPostProcessor源码跟踪

refresh方法中的registerBeanPostProcessors

@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing. 1、初始化上下文信息,替换占位符、必要参数的校验
			prepareRefresh();
			// Tell the subclass to refresh the internal bean factory. 2、解析类Xml、初始化BeanFactory
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 这一步主要是对初级容器的基础设计
			// Prepare the bean factory for use in this context. 	3、准备BeanFactory内容:
			prepareBeanFactory(beanFactory); // 对beanFactory容器的功能的扩展:
			try {
				// Allows post-processing of the bean factory in context subclasses. 4、扩展点加一:空实现,主要用于处理特殊Bean的后置处理器
				postProcessBeanFactory(beanFactory);
				// Invoke factory processors registered as beans in the context. 	5、spring bean容器的后置处理器
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation. 	6、注册bean的后置处理器
				//!!!!!!!!!!!!  这里 这里 今天看这里  !!!!!!!!!!!//
				registerBeanPostProcessors(beanFactory);
				//!!!!!!!!!!!!  这里 这里 今天看这里  !!!!!!!!!!!//

				// Initialize message source for this context.	7、初始化消息源
				initMessageSource();
				// Initialize event multicaster for this context.	8、初始化事件广播器
				initApplicationEventMulticaster();
				// Initialize other special beans in specific context subclasses. 9、扩展点加一:空实现;主要是在实例化之前做些bean初始化扩展
				onRefresh();
				// Check for listener beans and register them.	10、初始化监听器
				registerListeners();
				// Instantiate all remaining (non-lazy-init) singletons.	11、实例化:非兰加载Bean
				finishBeanFactoryInitialization(beanFactory);
				// Last step: publish corresponding event.	 12、发布相应的事件通知
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
			}
		}
	}


	/**
	 * Instantiate and register all BeanPostProcessor beans,
	 * respecting explicit order if given.
	 * <p>Must be called before any instantiation of application beans.
	 */
	protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
		PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
	}

registerBeanPostProcessors详解

	/**
	 *
	 * @param beanFactory
	 * @param applicationContext
	 */
	public static void registerBeanPostProcessors(
			ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

		// 1、获取所有实现BeanPostProcessor接口的类
		String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

		// Register BeanPostProcessorChecker that logs an info message when a bean is created during BeanPostProcessor instantiation, i.e. when a bean is not eligible for getting processed by all BeanPostProcessors.
		// 记录下BeanPostProcessor的目标计数
		// +1是因为在此方法的最后会添加一个BeanPostProcessorChecker的类
		int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
		// 2、添加BeanPostProcessorChecker(主要用于记录信息)到beanFactory中
		beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

		// Separate between BeanPostProcessors that implement PriorityOrdered,
		// Ordered, and the rest.
		// 3、初始化根据BeanPostProcessor是否实现Priority、Order接口进行分类,初始化各种类型的集合,分类装这些对象
		List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		// Spring自己内部的Bean后置处理器
		List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
		List<String> orderedPostProcessorNames = new ArrayList<>();
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
		// 4、遍历步骤一中所有后置处理器的名称
		for (String ppName : postProcessorNames) {
			// 实现PriorityOrdered类型的Bean
			if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
				priorityOrderedPostProcessors.add(pp);
				//  实现PriorityOrdered同时也实现类MergedBeanDefinitionPostProcessor接口,
				//  那么对应的bean实例添加到internalPostProcessors中,与实例化相关注解如@Autowired @Bean等关系密切,需要注意
				if (pp instanceof MergedBeanDefinitionPostProcessor) {
					internalPostProcessors.add(pp);
				}
			}
			// 实现Ordered类型的Bean
			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			}
			else {
				nonOrderedPostProcessorNames.add(ppName);
			}
		}

		// First, register the BeanPostProcessors that implement PriorityOrdered.
		// 5、将实现类PriorityOrder接口类型的bean先注入到BeanFactory中
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

		// Next, register the BeanPostProcessors that implement Ordered.
		// 6、将实现类Order接口类型的bean先注入到BeanFactory中
		List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
		for (String ppName : orderedPostProcessorNames) {
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			orderedPostProcessors.add(pp);
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		// 6、将实现类Order接口类型的bean先注入到BeanFactory中
		sortPostProcessors(orderedPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, orderedPostProcessors);

		// Now, register all regular BeanPostProcessors.
		List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
		for (String ppName : nonOrderedPostProcessorNames) {
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			nonOrderedPostProcessors.add(pp);
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		// 7.将无序普通的bean后处理器,注册到容器beanFactory中
		registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

		// Finally, re-register all internal BeanPostProcessors.
		// 8、最后,将Spring容器内部的BeanPostProcessor注册到Bean后置处理器中
		sortPostProcessors(internalPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, internalPostProcessors);

		// Re-register post-processor for detecting inner beans as ApplicationListeners,
		// moving it to the end of the processor chain (for picking up proxies etc).
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
	}

代码解析与重点总结
1. 获取所有实现BeanPostProcessor接口的类
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

此步骤从BeanFactory中获取所有实现了BeanPostProcessor接口的Bean名称。这是为了后续将这些Bean按照不同的规则进行处理和注册。

2. 添加BeanPostProcessorChecker
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

BeanPostProcessorChecker的作用是记录信息,当在BeanPostProcessor实例化过程中创建一个Bean时,它会输出一条信息日志。这一步是为了确保在BeanPostProcessor注册过程中Bean创建的可追溯性。

3. 根据类型分类BeanPostProcessor
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();

for (String ppName : postProcessorNames) {
    if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        priorityOrderedPostProcessors.add(pp);
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
        }
    } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
        orderedPostProcessorNames.add(ppName);
    } else {
        nonOrderedPostProcessorNames.add(ppName);
    }
}

在这一步,所有的BeanPostProcessor根据是否实现了PriorityOrdered、Ordered接口进行分类,分别放入不同的列表中。这是为了后续按照优先级进行注册。

4. 按优先级顺序注册BeanPostProcessor
// 注册实现PriorityOrdered接口的BeanPostProcessor
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

// 注册实现Ordered接口的BeanPostProcessor
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String ppName : orderedPostProcessorNames) {
    BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
    orderedPostProcessors.add(pp);
    if (pp instanceof MergedBeanDefinitionPostProcessor) {
        internalPostProcessors.add(pp);
    }
}
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);

// 注册普通的BeanPostProcessor
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String ppName : nonOrderedPostProcessorNames) {
    BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
    nonOrderedPostProcessors.add(pp);
    if (pp instanceof MergedBeanDefinitionPostProcessor) {
        internalPostProcessors.add(pp);
    }
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

按照实现PriorityOrdered、Ordered接口以及普通BeanPostProcessor的顺序,分别注册这些BeanPostProcessor。这确保了不同优先级的BeanPostProcessor按正确的顺序执行。

5. 注册内部BeanPostProcessor
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);

将Spring内部使用的BeanPostProcessor(实现MergedBeanDefinitionPostProcessor接口的)单独处理并注册。这些内部BeanPostProcessor与Bean的实例化相关注解(如@Autowired、@Bean)关系密切,需要特别注意。

6. 添加ApplicationListenerDetector
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));

最后,添加一个ApplicationListenerDetector,用于检测内部Bean是否作为ApplicationListeners(应用监听器),并将其移动到处理链的末尾,以便捕获代理等操作。

小结

BeanPostProcessor是Spring框架提供的一个强大工具,它允许我们开发者在Bean的生命周期中的特定点进行自定义操作。通过实现BeanPostProcessor接口,开发者可以插入自己的逻辑,以增强或修改Bean的行为。这个接口在AOP、依赖注入和Bean管理等方面都有着广泛的应用。正确地使用BeanPostProcessor可以极大地提高Spring应用的灵活性和可扩展性。

通过本文的详细介绍,相信大家对BeanPostProcessor有了更深入的理解。在实际开发中,合理地应用BeanPostProcessor,可以帮助我们更好地控制和管理Bean的生命周期,实现复杂的业务需求。

整体总结

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python图书信息管理系统(完整代码)

引言&#xff1a;&#xff08;假装也不是一个大学生课设&#xff09;在数字化和信息化快速发展的今天&#xff0c;图书管理系统成为了图书馆、学校及个人图书收藏管理中不可或缺的工具。这类系统不仅能有效地管理大量的图书资料&#xff0c;还能提高图书检索、借阅和归还的效率…

Centos Nginx SSL 配置

Nginx 配置 SSL 1.下载SSL证书 .crt 和 .key文件 2.创建和上传证书 mkdir -p /etc/nginx/cert 上传证书3.nginx.conf配置 # For more information on configuration, see: # * Official English Documentation: http://nginx.org/en/docs/ # * Official Russian Docum…

Java中子类继承和方法重写_java重写父类方法参数变了怎么改

public(非私有)private私有()构造方法不能继承不能继承成员变量能继承能继承成员方法能继承不能继承 1.也不能继承父类的有参构造方法,具体看构造函数继承特点 2.私有的成员变量相当于从父类拷贝一份拿过来用的,不能直接用,需要get/set方法 继承特点 继承中 成员变量访问特点:如…

Java-List集合堆内存溢出

Java-List集合堆内存溢出 情况一情况二对照分析对照规定堆内存 情况一 往List<Object>的集合中不断插入元素&#xff0c;集合底层的数组会不断扩容&#xff0c;从0 -> 10 -> 10 10>>1…。最终出现堆内存溢出&#xff0c;是在扩容数组大小的时候。这里的过程…

Next.js 实战 (一):项目搭建指南

前言 时间过得好快&#xff0c;一下就来到2024下半年了。 上半年我为了学习 Nuxt3&#xff0c;从 0 到 1 开发了一个导航网站&#xff1a;Dream Site&#xff0c;目前主要的功能都已完成了&#xff0c;后续有时间再慢慢添加有趣的功能。 下半年开始进攻 Next.js&#xff0c;…

MES系统如何进行数据采集?

在现代化制造业中&#xff0c;MES系统扮演着至关重要的角色。其中&#xff0c;对生产设备进行数据采集是MES系统不可或缺的一部分。数据采集不仅能够实时监控设备的运行状态&#xff0c;还能提供准确的生产数据&#xff0c;帮助企业实现精细化管理和优化生产流程。 通过实时采…

水利水电安全员C证考试题库资料,2024年全国考试通用!

1.安全生产民事责任&#xff0c;是指责任主体违反安全生产法律规定造成&#xff08;&#xff09;&#xff0c;由人民法院依照民事法律强制其行使民事赔偿的一种法律责任。民事责任追究的目的是为了最大限度的维护当事人受到民事损害时享有获得民事赔偿的权利。 A.民事损伤 B.…

如何检查购买的Facebook账号优劣?

Facebook 是全球最受欢迎的社交网络之一,为品牌广告提供了巨大的潜力。许多公司和营销人员使用 Facebook 来推广他们的产品和服务&#xff0c;经常会购买账号。当然也分出了很多账号&#xff0c;比如个人号&#xff0c;BM号&#xff0c;广告号&#xff0c;小黑号等等。 但是,有…

【Arduino】ESP8266开发环境配置(图文)

ESP8266与ESP32开发很类似&#xff0c;相当于是低配版本的ESP32&#xff0c;其同样具有无线网络连接能力&#xff0c;功能强大&#xff0c;而且价格比ESP32更具有优势。接下来我们就来设置一下ESP8266的开发环境。 使用Arduino开发平台软件&#xff0c;选择首选项进行设置。 h…

DVWA sql手注学习(巨详细不含sqlmap)

这篇文章主要记录学习sql注入的过程中遇到的问题已经一点学习感悟&#xff0c;过程图片会比较多&#xff0c;比较基础和详细&#xff0c;不存在看不懂哪一步的过程 文章目录 靶场介绍SQL注入 lowSQL注入 MediumSQL注入 HighSQL注入 Impossible 靶场介绍 DVWA&#xff08;Damn…

YUV 颜色编码详解

YUV 简介 YUV是被欧洲电视系统所采用的一种颜色编码方法&#xff08;属于PAL&#xff09;&#xff0c;是PAL和SECAM模拟彩色电视制式采用的颜色空间。在现代彩色电视系统中&#xff0c;通常采用三管彩色摄影机或彩色CCD摄影机进行取像&#xff0c;然后把取得的彩色图像信号经分…

硬件开发笔记(二十三):贴片电阻的类别、封装介绍,AD21导入贴片电阻原理图封装库3D模型

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/140110514 长沙红胖子Qt&#xff08;长沙创微智科&#xff09;博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV…

ConsiStory:无需训练的一致性文本到图像生成技术

随着大规模文本到图像&#xff08;T2I&#xff09;扩散模型的发展&#xff0c;用户可以更自由地通过文本指导图像生成过程。然而&#xff0c;要在不同的提示中保持同一主题的视觉一致性仍然是一个挑战。现有的方法通常需要对模型进行微调或预训练&#xff0c;以教授新词汇来描述…

arthas命令使用

dashboard(线程、内存等环境概览) jvm&#xff08;JVM相关信息概览&#xff09; 1、RUNTIME&#xff08;系统运行环境JVM相关信息&#xff0c;运行时长等&#xff09; 2、CLASS-LOADING&#xff08;类加载信息&#xff09; 3、 COMPILATION&#xff08;编译信息&#xff09; 4…

论文学习——基于类型检测的动态自适应多目标优化算法

论文题目&#xff1a;Dynamic adaptive multi-objective optimization algorithm based on type detection 基于类型检测的动态自适应多目标优化算法&#xff08;Xingjuan Cai a,b, Linjie Wu a,∗, Tianhao Zhao a, Di Wu c, Wensheng Zhang d, Jinjun Chen e&#xff09;Inf…

Spring启动时,将SpringContext设置到Util中(SpringContextUtil)

场景 在Spring应用开发中&#xff0c;为简化代码或者在静态方法中获取Spring应用的上下文&#xff0c;需要把SpringContext设置到类属性上。经过对源码的分析和实践&#xff0c;使用Spring的事件监听器监听ApplicationPreparedEvent事件是最佳的方式。 通过ApplicationPrepar…

深入理解 Git `git add -p` 命令中的交互选项

个人名片 &#x1f393;作者简介&#xff1a;java领域优质创作者 &#x1f310;个人主页&#xff1a;码农阿豪 &#x1f4de;工作室&#xff1a;新空间代码工作室&#xff08;提供各种软件服务&#xff09; &#x1f48c;个人邮箱&#xff1a;[2435024119qq.com] &#x1f4f1…

git使用遇到的问题记录

文章目录 1. 记录以下问题*error: RPC failed; HTTP 307 curl 22 The requested URL returned error: 307* 1. 记录以下问题 error: RPC failed; HTTP 307 curl 22 The requested URL returned error: 307 第一种&#xff1a;clone的仓库地址或者账户密码发生改变&#xff1b;…

Python学习篇:Python基础知识(三)

目录 1 Python保留字 2 注释 3 行与缩进 ​编辑4 多行语句 5 输入和输出 6 变量 7 数据类型 8 类型转换 9 表达式 10 运算符 1 Python保留字 Python保留字&#xff08;也称为关键字&#xff09;是Python编程语言中预定义的、具有特殊含义的标识符。这些保留字不能用作…