Springboot自动装配的原理

Springboot自动装配

  • 1.前言
  • 2.@EnableAutoConfiguration
  • 3.AutoConfigurationImportSelector
  • 4.spring.factories
  • 5.总结

1.前言

为什么springboot能够开箱即用,就是由于Springboot的自动装配。我们知道项目启动的方法上面都有一个注解@SpringBootApplication,接下来将从这里揭开springboot自动装配的过程。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
		@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {}

在SpringBootApplication 方法上面有注解:@EnableAutoConfiguration,从英文意思我们也可以看出,自动装配和这个注解有关。

2.@EnableAutoConfiguration

@SuppressWarnings("deprecation")
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

	String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

	/**
	 * Exclude specific auto-configuration classes such that they will never be applied.
	 * @return the classes to exclude
	 */
	Class<?>[] exclude() default {};

	/**
	 * Exclude specific auto-configuration class names such that they will never be
	 * applied.
	 * @return the class names to exclude
	 * @since 1.3.0
	 */
	String[] excludeName() default {};

}

在看上面代码之前,我们先看一下注解@Import

@Import是Spring Framework提供的一个注解,它允许我们在一个配置类中导入其他的配置类或者普通的组件类。这样做的目的是为了将大的配置类分解为多个小的、更易于管理的配置类。

@Import注解有以下几个主要的用途:

(1)导入其他配置类:如果你有一个大的Spring配置类,你可以使用@Import注解将其分解为多个小的配置类。这样,每个配置类都可以专注于一个特定的方面,使得配置更加清晰和易于管理。


@Configuration
public class DatabaseConfig {
  // ...
}

@Configuration
@Import(DatabaseConfig.class)
public class AppConfig {
  // ...
}

(2)导入普通的组件类:你也可以使用@Import注解导入普通的组件类(比如服务类、仓库类等)。这样,这些类就会被Spring容器管理,你可以在其他地方通过依赖注入的方式使用它们。

@Import(MyService.class)
@Configuration
public class AppConfig {
  // ...
}

(3)导入ImportSelector或ImportBeanDefinitionRegistrar接口的实现类:这是一种高级用法,让你可以在运行时动态地添加bean定义。

@Import(MyImportSelector.class)
@Configuration
public class AppConfig {
  // ...
}

再看上面的EnableAutoConfiguration 方法我们看到使用了注解@Import(EnableAutoConfigurationImportSelector.class),我们进入这个方法

// 不建议使用
@Deprecated
public class EnableAutoConfigurationImportSelector extends AutoConfigurationImportSelector {
    public EnableAutoConfigurationImportSelector() {
    }

    protected boolean isEnabled(AnnotationMetadata metadata) {
        return this.getClass().equals(EnableAutoConfigurationImportSelector.class) ? (Boolean)this.getEnvironment().getProperty("spring.boot.enableautoconfiguration", Boolean.class, true) : true;
    }
}

可以看到它继承了AutoConfigurationImportSelector方法,然后我们进入AutoConfigurationImportSelector方法中

3.AutoConfigurationImportSelector

可以看到AutoConfigurationImportSelector实现了ImportSelector接口
在这里插入图片描述

public interface ImportSelector {

	/**
	 * Select and return the names of which class(es) should be imported based on
	 * the {@link AnnotationMetadata} of the importing @{@link Configuration} class.
	 */
	String[] selectImports(AnnotationMetadata importingClassMetadata);

}

并且覆盖了selectImports方法,该方法返回了一个String数组,从代码可以知道里面存储的是配置信息。

@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
    // 检查是否启用了自动配置功能,如果没有启用则直接返回空数组
    if (!isEnabled(annotationMetadata)) {
        return NO_IMPORTS;
    }
    try {
        // 从类路径中加载自动配置元数据
        AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
                .loadMetadata(this.beanClassLoader);
        // 获取注解的属性
        AnnotationAttributes attributes = getAttributes(annotationMetadata);
        // 获取候选的配置类
        List<String> configurations = getCandidateConfigurations(annotationMetadata,
                attributes);
        // 移除重复的配置类
        configurations = removeDuplicates(configurations);
        // 对配置类进行排序
        configurations = sort(configurations, autoConfigurationMetadata);
        // 获取需要排除的配置类
        Set<String> exclusions = getExclusions(annotationMetadata, attributes);
        // 检查排除的类是否存在
        checkExcludedClasses(configurations, exclusions);
        // 移除需要排除的配置类
        configurations.removeAll(exclusions);
        // 过滤配置类
        configurations = filter(configurations, autoConfigurationMetadata);
        // 触发自动配置导入事件
        fireAutoConfigurationImportEvents(configurations, exclusions);
        // 将配置类转换为数组并返回
        return configurations.toArray(new String[configurations.size()]);
    }
    catch (IOException ex) {
        throw new IllegalStateException(ex);
    }
}

从代码中可以看到配置信息通过getCandidateConfigurations方法获取:

	protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
			AnnotationAttributes attributes) {
		List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
				getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
		Assert.notEmpty(configurations,
				"No auto configuration classes found in META-INF/spring.factories. If you "
						+ "are using a custom packaging, make sure that file is correct.");
		return configurations;
	}

从代码中可以看到配置信息是从loadFactoryNames方法中获取:

public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
        String factoryClassName = factoryClass.getName();

        try {
        	// 加载所有名为"META-INF/spring.factories"的资源文件
            Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
            List<String> result = new ArrayList();
			// 遍历所有找到的资源文件,并加载其属性。然后,它获取与工厂类名相对应的属性值,这些值通常是一串以逗号分隔的类名。最后,它将这些类名添加到结果列表中。
            while(urls.hasMoreElements()) {
                URL url = (URL)urls.nextElement();
                Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
                String factoryClassNames = properties.getProperty(factoryClassName);
                result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
            }

            return result;
        } catch (IOException var8) {
            throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() + "] factories from location [" + "META-INF/spring.factories" + "]", var8);
        }
    }

4.spring.factories

这里随便贴一个配置文件

# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer

# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.autoconfigure.BackgroundPreinitializer

# Auto Configuration Import Listeners
org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\
org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener

# Auto Configuration Import Filters
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
org.springframework.boot.autoconfigure.condition.OnClassCondition

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\
org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\
org.springframework.boot.autoconfigure.mobile.DeviceResolverAutoConfiguration,\
org.springframework.boot.autoconfigure.mobile.DeviceDelegatingViewResolverAutoConfiguration,\
org.springframework.boot.autoconfigure.mobile.SitePreferenceAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.reactor.ReactorAutoConfiguration,\
org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.security.FallbackWebSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.OAuth2AutoConfiguration,\
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
org.springframework.boot.autoconfigure.social.SocialWebAutoConfiguration,\
org.springframework.boot.autoconfigure.social.FacebookAutoConfiguration,\
org.springframework.boot.autoconfigure.social.LinkedInAutoConfiguration,\
org.springframework.boot.autoconfigure.social.TwitterAutoConfiguration,\
org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\
org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\
org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration,\
org.springframework.boot.autoconfigure.web.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.web.WebClientAutoConfiguration,\
org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration

# Failure analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.autoconfigure.diagnostics.analyzer.NoSuchBeanDefinitionFailureAnalyzer,\
org.springframework.boot.autoconfigure.jdbc.DataSourceBeanCreationFailureAnalyzer,\
org.springframework.boot.autoconfigure.jdbc.HikariDriverConfigurationFailureAnalyzer

# Template availability providers
org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.mustache.MustacheTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.web.JspTemplateAvailabilityProvider

5.总结

自动配置的类的全路径存放在了一个spring.factories文件中,当Spring Boot启动时,它会自动扫描所有的自动配置类,并根据这些类中的配置信息来初始化Spring应用上下文。这个过程中,selectImports方法返回的配置类名会被用来创建对应的Bean定义,并注册到Spring应用上下文中。这样,当应用运行时,这些自动配置类就会被实例化,并根据它们的配置信息来配置Spring应用。

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

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

相关文章

武汉灰京文化:游戏市场推广与用户增长的成功典范

作为游戏行业的明星企业&#xff0c;武汉灰京文化在市场推广和用户增长方面的成功经验备受瞩目。他们以创造性和独特性的市场营销策略&#xff0c;成功吸引了大量用户。这不仅提高了其游戏的知名度&#xff0c;还为公司带来了持续的增长。这一成功模式不仅对公司自身有益&#…

计算机中msvcp140.dll,丢失怎么修复与解决

一、msvcp140.dll20个软件环境 msvcp140.dll文件是许多软件运行环境的组成部分&#xff0c;通常与Microsoft Visual C Redistributable关联。以下是可能使用该文件的软件环境&#xff1a; 微软办公软件&#xff1a;如Microsoft Office套件&#xff0c;包括Word、Excel、Power…

仓库福音!三防工业手机:远程RFID和条形码扫描仪的优势

在仓库中&#xff0c;由于堆货量众多&#xff0c;仓库管理员想要细分货物的种类十分困难&#xff0c;因此保持准确的库存记录至关重要&#xff0c;这样公司就不会导致货物积压。资产跟踪也可能是繁琐的任务之一&#xff0c;会对公司产生重大影响。没有为特定部件记录准确或错误…

[Echart]图谱中的富文本标签

[Echart]图谱中的富文本标签 series-graph.links.label.rich option {title: {text: Basic Graph},tooltip: {},animationDurationUpdate: 1500,animationEasingUpdate: quinticInOut,series: [{type: graph,// layout: force,symbolSize: 50,roam: true,label: {show: tru…

C及C++每日练习(2)

1.选择&#xff1a; 1.使用printf函数打印一个double类型的数据&#xff0c;要求&#xff1a;输出为10进制&#xff0c;输出左对齐30个字符&#xff0c;4位精度。以下哪个选项是正确的&#xff1f; A.%-30.4e B.%4.30e C.%-30.4f D.%-4.30 在上一篇文章中&#xff0c;提到了…

社科院与杜兰大学金融管理硕士——精心准备,只为那一刻的刚刚好

我们每个人都是夜空中独一无二的那颗星&#xff0c;静静地照耀&#xff0c;期待着照亮自己的宇宙。我们的每一步前行&#xff0c;都像是星尘累积&#xff0c;汇聚成璀璨的光轨&#xff0c;照亮未来的道路。正如我们现在努力申请的社科院与杜兰大学金融管理硕士项目&#xff0c;…

深圳/广州/厦门/上海/宁波/义乌2024最新跨境电商展计划表发布!

全国各城市2024年跨境电商年度效果好的跨境展会排期表来了&#xff0c;具体展会活动议程根据组委会实际公示结果为准。 励佳展览(上海)有限公司是一家专业组织、代理国内跨境电商行业展会会展公司&#xff0c;励佳展览拥有高素质的员工队伍&#xff0c;广泛的客户资源&#xf…

香港媒体发稿:【超值1元港媒发稿套餐】推广技巧-华媒舍

在当今竞争激烈的市场中&#xff0c;品牌的推广是企业取得成功的关键。众多的宣传渠道中&#xff0c;香港媒体发稿无疑是一种高效的品牌推广方式。本文将为您介绍《超值1元港媒发稿套餐》的各个组成部分&#xff0c;以及它如何帮助您实现品牌的腾飞。 1. 1元套餐的优势 1元港媒…

田宏斌:以人为本的听力健康管理实践经验 | 演讲嘉宾公布

一、助辅听器材Ⅲ分论坛 助辅听器材Ⅲ分论坛将于3月28日同期举办&#xff01; 听力贯穿人的一生&#xff0c;听觉在生命的各个阶段都是至关重要的功能&#xff0c;听力问题一旦出现&#xff0c;会严重影响生活质量。助辅听器材能有效提高生活品质。在这里&#xff0c;我们将分享…

逆变器专题(15)-弱电网下的LCL逆变器控制以及谐振峰问题(2)

相应仿真原件请移步资源下载 LCL滤波器 LCL滤波器因其本身为一个二阶系统&#xff0c;其本身就会引发谐振&#xff0c;导致相应谐振频率处的增益得到放大&#xff0c;进而产生谐波等问题&#xff1b;另一方面&#xff0c;在弱电网下&#xff0c;逆变器会与电网阻抗发生耦合&am…

IP劫持的危害及应对策略

随着互联网的发展&#xff0c;网络安全问题日益凸显&#xff0c;其中IP劫持作为一种常见的网络攻击手段&#xff0c;对个人和企业的信息安全造成了严重的威胁。IP数据云将分析IP劫持的危害&#xff0c;并提出相应的应对策略。 IP地址查询&#xff1a;IP数据云 - 免费IP地址查询…

多张gif怎么拼接?三步教你在线拼接gif

GIF拼图常用于制作表情包、动态海报、广告宣传等场景。它可以将多个图像或动画元素组合在一起&#xff0c;形成一个有趣、生动的动画效果&#xff0c;吸引观众的注意力&#xff0c;并传达特定的信息或情感。要将多个GIF动图拼接在一张图像上&#xff0c;要使用适合的gif动画图片…

奥壹科技推出婚恋相亲系统免费软件,旨在扶持创业者降低行业入门门槛

(广州, 2024年3月6日星期三) - 随着婚恋市场的日益增长&#xff0c;奥壹科技宣布推出其旗下奥壹云相亲系统的全新免费版(OEyun Free V1.0)。该公司表示&#xff0c;该举措旨在通过降低创业门槛&#xff0c;为有意进入婚恋行业的创业者及小型企业提供支持&#xff0c;从而进一步…

Java继承与多态:深入理解继承、组合和多态的精髓!

Java继承与多态&#xff1a;深入理解继承、组合和多态的精髓&#xff01; 引言 欢迎来到这篇关于Java继承与多态的博客&#xff01;在Java编程中&#xff0c;继承与多态是两个非常重要的概念&#xff0c;它们为我们构建灵活而高效的代码提供了强大的支持。本文将深入探讨Java继…

2024年冲刺年薪40w,Android岗面试

一个程序员&#xff0c;如果不想35 岁被淘汰&#xff0c;请把它当成一种信仰&#xff01; 25岁&#xff0c;一个北漂程序员&#xff0c;入职三年&#xff0c;Android中级工程师&#xff0c;月薪15k&#xff0c;965的工作经常干成996&#xff0c;比起老家的同龄人&#xff0c;我…

校招中的“熟悉linux操作系统”一般是指达到什么程度?

校招中的“熟悉linux操作系统”一般是指达到什么程度&#xff1f; 在开始前我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「Linux的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&am…

鸿蒙Harmony应用开发—ArkTS声明式开发(基础手势:PanGesture)

拖动手势事件&#xff0c;当滑动的最小距离超过设定的最小值时触发拖动手势事件。 说明&#xff1a; 从API Version 7开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 接口 PanGesture(value?: { fingers?: number; direction?: PanDir…

three.js如何实现简易3D机房?(二)模型加载的过渡动画

接上一篇&#xff1a; three.js如何实现简易3D机房&#xff1f;&#xff08;一&#xff09;基础准备-下&#xff1a;http://t.csdnimg.cn/TTI1P 目录 六、自定义过渡动画 1.过渡动画组件 2.模型加载时使用 根据模型大小&#xff0c;可以自定义模型加载的过渡动画效果&am…

修改表中某个字段等于另一个字段减去 2 小时的 SQL

需求&#xff1a;将表中到达时间按照客户要求改为比赛时间的提前 N 小时&#xff0c;具体如下&#xff1a; 表结构 update contestSchedule SET mainRefereeArrivalTimeDATE_FORMAT(CONCAT(2024-03-04 ,gameTime)- INTERVAL 2 HOUR, %H:%i), assistantRefereeArrivalTimeDAT…

算法沉淀——贪心算法一(leetcode真题剖析)

算法沉淀——贪心算法一 01.柠檬水找零02.将数组和减半的最少操作次数03.最大数04.摆动序列 贪心算法&#xff08;Greedy Algorithm&#xff09;是一种基于贪心策略的优化算法&#xff0c;它通常用于求解最优化问题&#xff0c;每一步都选择当前状态下的最优解&#xff0c;以期…