【SpringBoot系列】SpringBoot中 @Configuration 和 @Component 的区别及原理分析

news2024/10/6 8:43:00

示例

//@Component
@Configuration
public class AppConfig {
    @Bean
    public Foo foo() {
        System.out.println("foo() invoked...");
        Foo foo = new Foo();
        System.out.println("foo() 方法的 foo hashcode: " + foo.hashCode());
        return foo;
    }

    @Bean
    public Eoo eoo() {
        System.out.println("eoo() invoked...");
        Foo foo = foo();
        System.out.println("eoo() 方法的 foo hashcode: " + foo.hashCode());
        return new Eoo();
    }

    public class Eoo {
    }

    public class Foo {
    }

}

使用Configuration,日志输出

foo() invoked...
foo() 方法的 foo hashcode: 1150480094
eoo() invoked...
eoo() 方法的 foo hashcode: 1150480094

使用@Component,日志输出

foo() invoked...
foo() 方法的 foo hashcode: 1472494238
eoo() invoked...
foo() invoked...
foo() 方法的 foo hashcode: 1680147911
eoo() 方法的 foo hashcode: 1680147911
  • 使用@Configuration,方法之间互相调用获取到的是代理方法,不会重新生成新的Bean,foo方法返回的值和eoo方法中调用foo获取到的Foo对象是同一个。
  • 使用@Component,方法之间互相调用获取的是实际的方法,foo方法返回的值和eoo方法中调用foo获取到的Foo对象不是同一个。
【SpringBoot系列】SpringBoot中 @Configuration 和 @Component 的区别及原理分析【SpringBoot系列】SpringBoot中 @Configuration 和 @Component 的区别及原理分析【SpringBoot系列】SpringBoot中 @Configuration 和 @Component 的区别及原理分析 【SpringBoot系列】SpringBoot中 @Configuration 和 @Component 的区别及原理分析 【SpringBoot系列】SpringBoot中 @Configuration 和 @Component 的区别及原理分析

在这里插入图片描述

【SpringBoot系列】SpringBoot中 @Configuration 和 @Component 的区别及原理分析【SpringBoot系列】SpringBoot中 @Configuration 和 @Component 的区别及原理分析【SpringBoot系列】SpringBoot中 @Configuration 和 @Component 的区别及原理分析
【SpringBoot系列】SpringBoot中 @Configuration 和 @Component 的区别及原理分析
【SpringBoot系列】SpringBoot中 @Configuration 和 @Component 的区别及原理分析
【SpringBoot系列】SpringBoot中 @Configuration 和 @Component 的区别及原理分析

原理解析

标注扫描类的代理模式

ConfigurationClassPostProcessor是做BeanDefinition扫描。扫描过程中,会执行ConfigurationClassUtils#checkConfigurationClassCandidate,获取BeanDefinition的类信息,判断是否存在Configuration,且注解上的属性proxyBeanMethods值不为false,设置属性CONFIGURATION_CLASS_FULL@Configuration(proxyBeanMethods = false)@Component一样效果,都是LITE模式。

	public static boolean checkConfigurationClassCandidate(
			BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {

		String className = beanDef.getBeanClassName();
		if (className == null || beanDef.getFactoryMethodName() != null) {
			return false;
		}

		AnnotationMetadata metadata;
		if (beanDef instanceof AnnotatedBeanDefinition &&
				className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {
			// Can reuse the pre-parsed metadata from the given BeanDefinition...
			metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata();
		}
		else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {
			// Check already loaded Class if present...
			// since we possibly can't even load the class file for this Class.
			Class<?> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass();
			if (BeanFactoryPostProcessor.class.isAssignableFrom(beanClass) ||
					BeanPostProcessor.class.isAssignableFrom(beanClass) ||
					AopInfrastructureBean.class.isAssignableFrom(beanClass) ||
					EventListenerFactory.class.isAssignableFrom(beanClass)) {
				return false;
			}
			metadata = AnnotationMetadata.introspect(beanClass);
		}
		else {
			try {
				MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className);
				metadata = metadataReader.getAnnotationMetadata();
			}
			catch (IOException ex) {
				if (logger.isDebugEnabled()) {
					logger.debug("Could not find class file for introspecting configuration annotations: " +
							className, ex);
				}
				return false;
			}
		}

		Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
		if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
			beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
		}
		else if (config != null || isConfigurationCandidate(metadata)) {
			beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
		}
		else {
			return false;
		}

		// It's a full or lite configuration candidate... Let's determine the order value, if any.
		Integer order = getOrder(metadata);
		if (order != null) {
			beanDef.setAttribute(ORDER_ATTRIBUTE, order);
		}

		return true;
	}

ConfigurationClassPostProcessor#postProcessBeanFactory,扫描获取到所有的BeanDefinition,进行加强处理。

	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		int factoryId = System.identityHashCode(beanFactory);
		if (this.factoriesPostProcessed.contains(factoryId)) {
			throw new IllegalStateException(
					"postProcessBeanFactory already called on this post-processor against " + beanFactory);
		}
		this.factoriesPostProcessed.add(factoryId);
		if (!this.registriesPostProcessed.contains(factoryId)) {
			// BeanDefinitionRegistryPostProcessor hook apparently not supported...
			// Simply call processConfigurationClasses lazily at this point then.
			processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
		}

		enhanceConfigurationClasses(beanFactory);
		beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
	}

ConfigurationClassPostProcessor#enhanceConfigurationClasses,所有的BeanDefinition获取属性ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE,如果等于ConfigurationClassUtils.CONFIGURATION_CLASS_FULL,存放到configBeanDefs。使用Cglib代理对@Configuration注解标注的类的增强。

	public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
		StartupStep enhanceConfigClasses = this.applicationStartup.start("spring.context.config-classes.enhance");
		Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
		for (String beanName : beanFactory.getBeanDefinitionNames()) {
			BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
			Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE);
			AnnotationMetadata annotationMetadata = null;
			MethodMetadata methodMetadata = null;
			if (beanDef instanceof AnnotatedBeanDefinition) {
				AnnotatedBeanDefinition annotatedBeanDefinition = (AnnotatedBeanDefinition) beanDef;
				annotationMetadata = annotatedBeanDefinition.getMetadata();
				methodMetadata = annotatedBeanDefinition.getFactoryMethodMetadata();
			}
			if ((configClassAttr != null || methodMetadata != null) && beanDef instanceof AbstractBeanDefinition) {
				// Configuration class (full or lite) or a configuration-derived @Bean method
				// -> eagerly resolve bean class at this point, unless it's a 'lite' configuration
				// or component class without @Bean methods.
				AbstractBeanDefinition abd = (AbstractBeanDefinition) beanDef;
				if (!abd.hasBeanClass()) {
					boolean liteConfigurationCandidateWithoutBeanMethods =
							(ConfigurationClassUtils.CONFIGURATION_CLASS_LITE.equals(configClassAttr) &&
								annotationMetadata != null && !ConfigurationClassUtils.hasBeanMethods(annotationMetadata));
					if (!liteConfigurationCandidateWithoutBeanMethods) {
						try {
							abd.resolveBeanClass(this.beanClassLoader);
						}
						catch (Throwable ex) {
							throw new IllegalStateException(
									"Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
						}
					}
				}
			}
			if (ConfigurationClassUtils.CONFIGURATION_CLASS_FULL.equals(configClassAttr)) {
				if (!(beanDef instanceof AbstractBeanDefinition)) {
					throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" +
							beanName + "' since it is not stored in an AbstractBeanDefinition subclass");
				}
				else if (logger.isInfoEnabled() && beanFactory.containsSingleton(beanName)) {
					logger.info("Cannot enhance @Configuration bean definition '" + beanName +
							"' since its singleton instance has been created too early. The typical cause " +
							"is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor " +
							"return type: Consider declaring such methods as 'static'.");
				}
				configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
			}
		}
		if (configBeanDefs.isEmpty() || NativeDetector.inNativeImage()) {
			// nothing to enhance -> return immediately
			enhanceConfigClasses.end();
			return;
		}

		ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
		for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
			AbstractBeanDefinition beanDef = entry.getValue();
			// If a @Configuration class gets proxied, always proxy the target class
			beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
			// Set enhanced subclass of the user-specified bean class
			Class<?> configClass = beanDef.getBeanClass();
			Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
			if (configClass != enhancedClass) {
				if (logger.isTraceEnabled()) {
					logger.trace(String.format("Replacing bean definition '%s' existing class '%s' with " +
							"enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName()));
				}
				beanDef.setBeanClass(enhancedClass);
			}
		}
		enhanceConfigClasses.tag("classCount", () -> String.valueOf(configBeanDefs.keySet().size())).end();
	}

代理核心

ConfigurationClassEnhancer#enhance,增强类

	// The callbacks to use. Note that these callbacks must be stateless.
	private static final Callback[] CALLBACKS = new Callback[] {
			new BeanMethodInterceptor(),
			new BeanFactoryAwareMethodInterceptor(),
			NoOp.INSTANCE
	};

	private static final ConditionalCallbackFilter CALLBACK_FILTER = new ConditionalCallbackFilter(CALLBACKS);


	public Class<?> enhance(Class<?> configClass, @Nullable ClassLoader classLoader) {
		if (EnhancedConfiguration.class.isAssignableFrom(configClass)) {
			if (logger.isDebugEnabled()) {
				logger.debug(String.format("Ignoring request to enhance %s as it has " +
						"already been enhanced. This usually indicates that more than one " +
						"ConfigurationClassPostProcessor has been registered (e.g. via " +
						"<context:annotation-config>). This is harmless, but you may " +
						"want check your configuration and remove one CCPP if possible",
						configClass.getName()));
			}
			return configClass;
		}
		Class<?> enhancedClass = createClass(newEnhancer(configClass, classLoader));
		if (logger.isTraceEnabled()) {
			logger.trace(String.format("Successfully enhanced %s; enhanced class name is: %s",
					configClass.getName(), enhancedClass.getName()));
		}
		return enhancedClass;
	}

	private Enhancer newEnhancer(Class<?> configSuperClass, @Nullable ClassLoader classLoader) {
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(configSuperClass);
		enhancer.setInterfaces(new Class<?>[] {EnhancedConfiguration.class});
		enhancer.setUseFactory(false);
		enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
		enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));
		enhancer.setCallbackFilter(CALLBACK_FILTER);
		enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
		return enhancer;
	}

ConfigurationClassEnhancer.BeanMethodInterceptor#isMatchBeanMethodInterceptor拦截带有Bean注解的方法。

		@Override
		public boolean isMatch(Method candidateMethod) {
			return (candidateMethod.getDeclaringClass() != Object.class &&
					!BeanFactoryAwareMethodInterceptor.isSetBeanFactory(candidateMethod) &&
					BeanAnnotationHelper.isBeanAnnotated(candidateMethod));
		}

ConfigurationClassEnhancer.BeanMethodInterceptor#intercept,拦截方法,判断Bean是否正在创建,如果未创建,调用cglibMethodProxy.invokeSuper,否则调用resolveBeanReference

		@Override
		@Nullable
		public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
					MethodProxy cglibMethodProxy) throws Throwable {

			ConfigurableBeanFactory beanFactory = getBeanFactory(enhancedConfigInstance);
			String beanName = BeanAnnotationHelper.determineBeanNameFor(beanMethod);

			// Determine whether this bean is a scoped-proxy
			if (BeanAnnotationHelper.isScopedProxy(beanMethod)) {
				String scopedBeanName = ScopedProxyCreator.getTargetBeanName(beanName);
				if (beanFactory.isCurrentlyInCreation(scopedBeanName)) {
					beanName = scopedBeanName;
				}
			}

			if (factoryContainsBean(beanFactory, BeanFactory.FACTORY_BEAN_PREFIX + beanName) &&
					factoryContainsBean(beanFactory, beanName)) {
				Object factoryBean = beanFactory.getBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName);
				if (factoryBean instanceof ScopedProxyFactoryBean) {
					// Scoped proxy factory beans are a special case and should not be further proxied
				}
				else {
					// It is a candidate FactoryBean - go ahead with enhancement
					return enhanceFactoryBean(factoryBean, beanMethod.getReturnType(), beanFactory, beanName);
				}
			}

			if (isCurrentlyInvokedFactoryMethod(beanMethod)) {
				if (logger.isInfoEnabled() &&
						BeanFactoryPostProcessor.class.isAssignableFrom(beanMethod.getReturnType())) {
					logger.info(String.format("@Bean method %s.%s is non-static and returns an object " +
									"assignable to Spring's BeanFactoryPostProcessor interface. This will " +
									"result in a failure to process annotations such as @Autowired, " +
									"@Resource and @PostConstruct within the method's declaring " +
									"@Configuration class. Add the 'static' modifier to this method to avoid " +
									"these container lifecycle issues; see @Bean javadoc for complete details.",
							beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName()));
				}
				return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
			}

			return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
		}

ConfigurationClassEnhancer.BeanMethodInterceptor#resolveBeanReference,获取Bean.

		private Object resolveBeanReference(Method beanMethod, Object[] beanMethodArgs,
				ConfigurableBeanFactory beanFactory, String beanName) {

			boolean alreadyInCreation = beanFactory.isCurrentlyInCreation(beanName);
			try {
				if (alreadyInCreation) {
					beanFactory.setCurrentlyInCreation(beanName, false);
				}
				boolean useArgs = !ObjectUtils.isEmpty(beanMethodArgs);
				if (useArgs && beanFactory.isSingleton(beanName)) {
					
					for (Object arg : beanMethodArgs) {
						if (arg == null) {
							useArgs = false;
							break;
						}
					}
				}
				Object beanInstance = (useArgs ? beanFactory.getBean(beanName, beanMethodArgs) :
						beanFactory.getBean(beanName));
				if (!ClassUtils.isAssignableValue(beanMethod.getReturnType(), beanInstance)) {
					// Detect package-protected NullBean instance through equals(null) check
					if (beanInstance.equals(null)) {
						if (logger.isDebugEnabled()) {
							logger.debug(String.format("@Bean method %s.%s called as bean reference " +
									"for type [%s] returned null bean; resolving to null value.",
									beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName(),
									beanMethod.getReturnType().getName()));
						}
						beanInstance = null;
					}
					else {
						String msg = String.format("@Bean method %s.%s called as bean reference " +
								"for type [%s] but overridden by non-compatible bean instance of type [%s].",
								beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName(),
								beanMethod.getReturnType().getName(), beanInstance.getClass().getName());
						try {
							BeanDefinition beanDefinition = beanFactory.getMergedBeanDefinition(beanName);
							msg += " Overriding bean of same name declared in: " + beanDefinition.getResourceDescription();
						}
						catch (NoSuchBeanDefinitionException ex) {
							// Ignore - simply no detailed message then.
						}
						throw new IllegalStateException(msg);
					}
				}
				Method currentlyInvoked = SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod();
				if (currentlyInvoked != null) {
					String outerBeanName = BeanAnnotationHelper.determineBeanNameFor(currentlyInvoked);
					beanFactory.registerDependentBean(beanName, outerBeanName);
				}
				return beanInstance;
			}
			finally {
				if (alreadyInCreation) {
					beanFactory.setCurrentlyInCreation(beanName, true);
				}
			}
		}
【SpringBoot系列】SpringBoot中 @Configuration 和 @Component 的区别及原理分析【SpringBoot系列】SpringBoot中 @Configuration 和 @Component 的区别及原理分析【SpringBoot系列】SpringBoot中 @Configuration 和 @Component 的区别及原理分析【SpringBoot系列】SpringBoot中 @Configuration 和 @Component 的区别及原理分析【SpringBoot系列】SpringBoot中 @Configuration 和 @Component 的区别及原理分析【SpringBoot系列】SpringBoot中 @Configuration 和 @Component 的区别及原理分析【SpringBoot系列】SpringBoot中 @Configuration 和 @Component 的区别及原理分析 【SpringBoot系列】SpringBoot中 @Configuration 和 @Component 的区别及原理分析 【SpringBoot系列】SpringBoot中 @Configuration 和 @Component 的区别及原理分析 【SpringBoot系列】SpringBoot中 @Configuration 和 @Component 的区别及原理分析

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

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

相关文章

华为OD机试真题B卷 Java 实现【等差数列】,附详细解题思路

一、题目描述 等差数列 2&#xff0c;5&#xff0c;8&#xff0c;11&#xff0c;14。。。。 从 2 开始的 3 为公差的等差数列。 输出求等差数列前n项和。 数据范围&#xff1a; 1≤n≤1000 。 二、输入描述 输入一个正整数n。 三、输出描述 输出一个相加后的整数。 四…

Dell电脑出现ac power adapter电压异常的解决办法

最近这段时间不知怎么的&#xff0c;dell笔记本电脑一开机就出现下面错误&#xff1a; The AC Power Adapter Wattage Cannot be Determined. 无法确定此交流电源的功率信息。 The Battery Maynot Charge. 电池将可能无法充电。 The System Will Adjust the Performance to Ma…

springboot+java农产品网上购物商城系统005

基于springboot技术的购物商城系统是属于JavaWeb项目&#xff0c;采用的开发框架为springboot框架&#xff0c;也就是Spring mvc、Spring、MyBatis这三个框架&#xff0c;页面设计用的是jsp技术作为动态页面文件设计&#xff0c;jsp文件里可以对实现html等界面布局的代码&#…

MySQL CAST 函数与 CONVERT 函数

文章目录 CAST 函数与 CONVERT 函数1. 数字和小数点组成的字符串转换为整型2. 非数值字符串转换为整型3. 把整型转换为二进制4. 数字和小数点组成的字符串转换为浮点型 CAST 函数与 CONVERT 函数 前面我们介绍的两个函数用于字符串和日期类型之间进行相互转换&#xff0c;有时我…

C.11医疗领域实体抽取:UIE Slim最新升级版含数据标注、serving部署、模型蒸馏等教学,助力工业应用场景快速落地

NLP专栏简介:数据增强、智能标注、意图识别算法|多分类算法、文本信息抽取、多模态信息抽取、可解释性分析、性能调优、模型压缩算法等 专栏详细介绍:NLP专栏简介:数据增强、智能标注、意图识别算法|多分类算法、文本信息抽取、多模态信息抽取、可解释性分析、性能调优、模型…

量子力学专题:产生算符与消灭算符

从粒子数表象探讨问题 线性谐振子在坐标表象中表示 哈密顿算符 定态薛定谔方程 渐近解 做代换使方程变为在\zeta \approx \pm \infty 时&#xff0c;有渐进解 两端条件要求阶段&#xff0c;因此有 则线性谐振子的定态波函数为&#xff1a; 粒子数表象中线性谐振子能级和波函…

chatgpt赋能python:Python中可以连等吗?

Python中可以连等吗&#xff1f; 在Python中&#xff0c;我们可以使用单个语句实现多个变量的赋值&#xff0c;这被称为连等&#xff08;也称为多重赋值或元组赋值&#xff09;。那么&#xff0c;Python中可以连等吗&#xff1f;让我们深入了解这个问题。 什么是连等&#xf…

Golang指针, 值类型,标识符,关键字,运算符初始

Golang指针, 值类型&#xff0c;标识符&#xff0c;关键字&#xff0c;标识符 采用文章 https://www.runoob.com/go/go-operators.html本章使用go练习工具 https://tour.go-zh.org/welcome/1指针 基本介绍 基本数据类型&#xff0c;变量存的就是值&#xff0c;也叫值类型获…

java基于ssm的的律师事务所预约管理系统的设计与实现

网站前台:关于我们、帮助信息、法律资讯、律师信息、服务信息、服务评价管理员功能 1、管理关于我们、帮助信息 2、管理资讯类型、添加法律资讯 3、添加律师信息(姓名、特长、照片、描述等等 ) 管理服务类型信息(讨薪、民事、刑事等等]、查看服务信息4 5、查看试题信息、查看试…

调用api key使用chatgpt,缓解chatgpt封控

前言&#xff1a; 现在国内的很多网页版的chatgpt网页随处可见 &#xff0c;但是很多都是3.5的接口&#xff0c;而且有些还有次数限制&#xff0c;毕竟现在4.0的api贵的离谱&#xff0c;在前期注册的chatgpt账号&#xff0c;其实官方是赠送有18美金的api额度供我们使用&#x…

Solaris Network:BSC上首个链上合成资产解决方案

Solaris Network 是一个开创性的项目&#xff0c;为 Binance Smart Chain&#xff08;BSC&#xff09;提供链上合成资产解决方案。Solaris 通过在区块链和实际金融领域之间搭建一座独特的桥梁&#xff0c;为多链 Web 3.0 金融衍生品市场奠定了全面基础设施。 本技术分析探讨了 …

MySQL 日期时间函数

文章目录 日期时间函数1. now()2. curdate()3. curtime()4. week(date)5. year(date)、month(date)、day(date)6. datediff(date1,date2)7. adddate(date,n) 日期时间函数 日期操作是 MySQL 中的常用操作&#xff0c;掌握常用的日期时间函数并熟练组合运用&#xff0c;能够帮助…

web的基本漏洞--弱口令漏洞

目录 一、弱口令漏洞介绍 1.弱口令漏洞的原理 2.漏洞识别 3.攻击方式 4.漏洞的危害 5.漏洞防御 二、弱口令漏洞的攻击方式-暴力破解 1.暴力破解的一般流程 2.token并不能有效的防范暴力破解漏洞 3.防范暴力破解常见方法 一、弱口令漏洞介绍 弱口令漏洞是指系统登录口…

港联证券|散户为什么会追涨杀跌?如何避免?

股市是一个充满机会的地方&#xff0c;每天都有大量投资者在里面寻求财富。然而股市中很多散户都是亏损的&#xff0c;一个重要原因就是喜欢追涨杀跌。那么散户为什么会追涨杀跌&#xff1f;如何避免&#xff1f;港联证券也为大家准备了相关内容&#xff0c;以供参考。 散户为什…

【深度学习】李宏毅2021/2022春深度学习课程笔记 - 机器学习的可解释性

文章目录 一、为什么我们需要可解释性的机器学习二、可解释性的 vs 强大的&#xff08;Powerful&#xff09;三、可解释性机器学习的目标四、可解释性的机器学习4.1 Local Explanation 局部的解释4.1.1 特征重要性4.1.2 模型怎么处理数据的&#xff1f;4.1.2.1 可视化4.1.2.2 P…

分割回文串

1题目 给你一个字符串 s&#xff0c;请你将 s 分割成一些子串&#xff0c;使每个子串都是 回文串 。返回 s 所有可能的分割方案。 回文串 是正着读和反着读都一样的字符串。 示例 1&#xff1a; 输入&#xff1a;s "aab" 输出&#xff1a;[["a","…

糖化学试剂2199491-27-3,L-Glutamamide,激肽释放酶抑制剂肽,信息说明

试剂基团反应特点&#xff08;Reagent group reaction characteristics&#xff09;&#xff1a; L-Glutamamide&#xff08;糖化学试剂&#xff09;激肽释放酶抑制剂肽&#xff0c;陕西新研博美生物科技有限公司提供多肽合成、多肽定制、同位素标记肽、生物素标记肽、荧光标记…

【七】设计模式~~~结构型模式~~~桥接模式(Java)

【学习难度&#xff1a;★★★☆☆&#xff0c;使用频率&#xff1a;★★★☆☆】 2.1. 模式动机 在正式介绍桥接模式之前&#xff0c;我先跟大家谈谈两种常见文具的区别&#xff0c;它们是毛笔和蜡笔。假如我们需要大中小3种型号的画笔&#xff0c;能够绘制12种不同的颜色&am…

Android 应用快捷(shortcut)功能的详解(一)

一、介绍 在现如今的应用中&#xff0c;一些开发者为了把核心的业务尽快的方便让使用者触摸到&#xff0c;想尽各种办法。比如前期的桌面插件&#xff0c;点击直接拉起核心业务。现在我们在主流的APP中&#xff0c;只要你长按桌面快捷键&#xff0c;发现弹出来的是不是单一的卸…

MapReduce实战案例(2)

案例二: MR实战之数据分类输出(自定义outputFormat) 2.1 项目准备 需求 现有一些原始日志需要做增强解析处理&#xff0c;流程&#xff1a; a) 从原始日志文件中读取数据b) 根据日志中的一个URL字段到外部知识库中获取信息增强到原始日志c) 如果成功增强&#xff0c;则输出…