0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Spring Boot的注解原理是什么

5jek_harmonyos ? 來(lái)源:博客園 ? 作者:kosamino ? 2021-08-27 09:24 ? 次閱讀

首先,先看SpringBoot的主配置類:

@SpringBootApplicationpublic class StartEurekaApplication

{

public static void main(String[] args)

{

SpringApplication.run(StartEurekaApplication.class, args);

}

}

點(diǎn)進(jìn)@SpringBootApplication來(lái)看,發(fā)現(xiàn)@SpringBootApplication是一個(gè)組合注解。

@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 {

}

首先我們先來(lái)看 @SpringBootConfiguration:

@Target({ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Documented@Configurationpublic @interface SpringBootConfiguration {

}

可以看到這個(gè)注解除了元注解以外,就只有一個(gè)@Configuration,那也就是說(shuō)這個(gè)注解相當(dāng)于@Configuration,所以這兩個(gè)注解作用是一樣的,它讓我們能夠去注冊(cè)一些額外的Bean,并且導(dǎo)入一些額外的配置。

那@Configuration還有一個(gè)作用就是把該類變成一個(gè)配置類,不需要額外的XML進(jìn)行配置。所以@SpringBootConfiguration就相當(dāng)于@Configuration。進(jìn)入@Configuration,發(fā)現(xiàn)@Configuration核心是@Component,說(shuō)明Spring的配置類也是Spring的一個(gè)組件。

@Target({ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Documented@Componentpublic @interface Configuration {

@AliasFor(

annotation = Component.class

String value() default “”;

}

繼續(xù)來(lái)看下一個(gè)@EnableAutoConfiguration,這個(gè)注解是開(kāi)啟自動(dòng)配置的功能。

@Target({ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Documented@Inherited@AutoConfigurationPackage@Import({AutoConfigurationImportSelector.class})

public @interface EnableAutoConfiguration {

String ENABLED_OVERRIDE_PROPERTY = “spring.boot.enableautoconfiguration”;

Class《?》[] exclude() default {};

String[] excludeName() default {};

}

可以看到它是由 @AutoConfigurationPackage,@Import(EnableAutoConfigurationImportSelector.class)這兩個(gè)而組成的,我們先說(shuō)@AutoConfigurationPackage,他是說(shuō):讓包中的類以及子包中的類能夠被自動(dòng)掃描到spring容器中。

@Target({ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Documented@Inherited@Import({Registrar.class})

public @interface AutoConfigurationPackage {

}

使用@Import來(lái)給Spring容器中導(dǎo)入一個(gè)組件 ,這里導(dǎo)入的是Registrar.class。來(lái)看下這個(gè)Registrar:

static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {

Registrar() {

}

public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {

AutoConfigurationPackages.register(registry, (new AutoConfigurationPackages.PackageImport(metadata)).getPackageName());

}

public Set《Object》 determineImports(AnnotationMetadata metadata) {

return Collections.singleton(new AutoConfigurationPackages.PackageImport(metadata));

}

}

就是通過(guò)以上這個(gè)方法獲取掃描的包路徑,可以debug查看具體的值:

那metadata是什么呢,可以看到是標(biāo)注在@SpringBootApplication注解上的DemosbApplication,也就是我們的主配置類Application:

其實(shí)就是將主配置類(即@SpringBootApplication標(biāo)注的類)的所在包及子包里面所有組件掃描加載到Spring容器。因此我們要把DemoApplication放在項(xiàng)目的最高級(jí)中(最外層目錄)。

看看注解@Import(AutoConfigurationImportSelector.class),@Import注解就是給Spring容器中導(dǎo)入一些組件,這里傳入了一個(gè)組件的選擇器:AutoConfigurationImportSelector。

可以從圖中看出AutoConfigurationImportSelector 繼承了 DeferredImportSelector 繼承了 ImportSelector,ImportSelector有一個(gè)方法為:selectImports。將所有需要導(dǎo)入的組件以全類名的方式返回,這些組件就會(huì)被添加到容器中。

public String[] selectImports(AnnotationMetadata annotationMetadata) {

if (!this.isEnabled(annotationMetadata)) {

return NO_IMPORTS;

} else {

AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);

AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry =

this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);

return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());

}

}

會(huì)給容器中導(dǎo)入非常多的自動(dòng)配置類(xxxAutoConfiguration);就是給容器中導(dǎo)入這個(gè)場(chǎng)景需要的所有組件,并配置好這些組件。

有了自動(dòng)配置類,免去了我們手動(dòng)編寫(xiě)配置注入功能組件等的工作。那是如何獲取到這些配置類的呢,看看下面這個(gè)方法:

protected AutoConfigurationImportSelector.AutoConfigurationEntry

getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) {

if (!this.isEnabled(annotationMetadata)) {

return EMPTY_ENTRY;

} else {

AnnotationAttributes attributes = this.getAttributes(annotationMetadata);

List《String》 configurations = this.getCandidateConfigurations(annotationMetadata, attributes);

configurations = this.removeDuplicates(configurations);

Set《String》 exclusions = this.getExclusions(annotationMetadata, attributes);

this.checkExcludedClasses(configurations, exclusions);

configurations.removeAll(exclusions);

configurations = this.filter(configurations, autoConfigurationMetadata);

this.fireAutoConfigurationImportEvents(configurations, exclusions);

return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);

}

}

我們可以看到getCandidateConfigurations()這個(gè)方法,他的作用就是引入系統(tǒng)已經(jīng)加載好的一些類,到底是那些類呢:

protected List《String》 getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {

List《String》 configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.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;

}

public static List《String》 loadFactoryNames(Class《?》 factoryClass, @Nullable ClassLoader classLoader) {

String factoryClassName = factoryClass.getName();

return (List)loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());

}

會(huì)從META-INF/spring.factories中獲取資源,然后通過(guò)Properties加載資源:

private static Map《String, List《String》》 loadSpringFactories(@Nullable ClassLoader classLoader) {

MultiValueMap《String, String》 result = (MultiValueMap)cache.get(classLoader);

if (result != null) {

return result;

} else {

try {

Enumeration《URL》 urls = classLoader !=

null ? classLoader.getResources(“META-INF/spring.factories”) : ClassLoader.getSystemResources(“META-INF/spring.factories”);

LinkedMultiValueMap result = new LinkedMultiValueMap();

while(urls.hasMoreElements()) {

URL url = (URL)urls.nextElement();

UrlResource resource = new UrlResource(url);

Properties properties = PropertiesLoaderUtils.loadProperties(resource);

Iterator var6 = properties.entrySet().iterator();

while(var6.hasNext()) {

Map.Entry《?, ?》 entry = (Map.Entry)var6.next();

String factoryClassName = ((String)entry.getKey()).trim();

String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());

int var10 = var9.length;

for(int var11 = 0; var11 《 var10; ++var11) {

String factoryName = var9[var11];

result.add(factoryClassName, factoryName.trim());

}

}

}

cache.put(classLoader, result);

return result;

} catch (IOException var13) {

throw new IllegalArgumentException(“Unable to load factories from location [META-INF/spring.factories]”, var13);

}

}

}

可以知道SpringBoot在啟動(dòng)的時(shí)候從類路徑下的META-INF/spring.factories中獲取EnableAutoConfiguration指定的值,將這些值作為自動(dòng)配置類導(dǎo)入到容器中,自動(dòng)配置類就生效,幫我們進(jìn)行自動(dòng)配置工作。以前我們需要自己配置的東西,自動(dòng)配置類都幫我們完成了。如下圖可以發(fā)現(xiàn)Spring常見(jiàn)的一些類已經(jīng)自動(dòng)導(dǎo)入。

接下來(lái)看@ComponentScan注解,@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }),這個(gè)注解就是掃描包,然后放入spring容器。

@ComponentScan(excludeFilters = {

@Filter(type = FilterType.CUSTOM,classes = {TypeExcludeFilter.class}),

@Filter(type = FilterType.CUSTOM,classes = {AutoConfigurationExcludeFilter.class})})

public @interface SpringBootApplication {}

總結(jié)下@SpringbootApplication:就是說(shuō),他已經(jīng)把很多東西準(zhǔn)備好,具體是否使用取決于我們的程序或者說(shuō)配置。

接下來(lái)繼續(xù)看run方法:

public static void main(String[] args) {

SpringApplication.run(Application.class, args);

}

來(lái)看下在執(zhí)行run方法到底有沒(méi)有用到哪些自動(dòng)配置的東西,我們點(diǎn)進(jìn)run:

public ConfigurableApplicationContext run(String.。. args) {

//計(jì)時(shí)器

StopWatch stopWatch = new StopWatch();

stopWatch.start();

ConfigurableApplicationContext context = null;

Collection《SpringBootExceptionReporter》 exceptionReporters = new ArrayList();

this.configureHeadlessProperty();

//監(jiān)聽(tīng)器

SpringApplicationRunListeners listeners = this.getRunListeners(args);

listeners.starting();

Collection exceptionReporters;

try {

ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);

ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);

this.configureIgnoreBeanInfo(environment);

Banner printedBanner = this.printBanner(environment);

//準(zhǔn)備上下文

context = this.createApplicationContext();

exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);

//預(yù)刷新context

this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);

//刷新context

this.refreshContext(context);

//刷新之后的context

this.afterRefresh(context, applicationArguments);

stopWatch.stop();

if (this.logStartupInfo) {

(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);

}

listeners.started(context);

this.callRunners(context, applicationArguments);

} catch (Throwable var10) {

this.handleRunFailure(context, var10, exceptionReporters, listeners);

throw new IllegalStateException(var10);

}

try {

listeners.running(context);

return context;

} catch (Throwable var9) {

this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);

throw new IllegalStateException(var9);

}

}

那我們關(guān)注的就是 refreshContext(context); 刷新context,我們點(diǎn)進(jìn)來(lái)看。

private void refreshContext(ConfigurableApplicationContext context) {

refresh(context);

if (this.registerShutdownHook) {

try {

context.registerShutdownHook();

}

catch (AccessControlException ex) {

// Not allowed in some environments.

}

}

}

我們繼續(xù)點(diǎn)進(jìn)refresh(context);

protected void refresh(ApplicationContext applicationContext) {

Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);

((AbstractApplicationContext) applicationContext).refresh();

}

他會(huì)調(diào)用 ((AbstractApplicationContext) applicationContext).refresh();方法,我們點(diǎn)進(jìn)來(lái)看:

public void refresh() throws BeansException, IllegalStateException {

synchronized (this.startupShutdownMonitor) {

// Prepare this context for refreshing.

prepareRefresh();

// Tell the subclass to refresh the internal bean factory.

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

// Prepare the bean factory for use in this context.

prepareBeanFactory(beanFactory);

try {

// Allows post-processing of the bean factory in context subclasses.

postProcessBeanFactory(beanFactory);

// Invoke factory processors registered as beans in the context.

invokeBeanFactoryPostProcessors(beanFactory);

// Register bean processors that intercept bean creation.

registerBeanPostProcessors(beanFactory);

// Initialize message source for this context.

initMessageSource();

// Initialize event multicaster for this context.

initApplicationEventMulticaster();

// Initialize other special beans in specific context subclasses.

onRefresh();

// Check for listener beans and register them.

registerListeners();

// Instantiate all remaining (non-lazy-init) singletons.

finishBeanFactoryInitialization(beanFactory);

// Last step: publish corresponding event.

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 ‘a(chǎn)ctive’ 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();

}

}

}

由此可知,就是一個(gè)spring的bean的加載過(guò)程。繼續(xù)來(lái)看一個(gè)方法叫做 onRefresh():

protected void onRefresh() throws BeansException {

// For subclasses: do nothing by default.

}

他在這里并沒(méi)有直接實(shí)現(xiàn),但是我們找他的具體實(shí)現(xiàn):

比如Tomcat跟web有關(guān),我們可以看到有個(gè)ServletWebServerApplicationContext:

@Overrideprotected void onRefresh() {

super.onRefresh();

try {

createWebServer();

}

catch (Throwable ex) {

throw new ApplicationContextException(“Unable to start web server”, ex);

}

}

可以看到有一個(gè)createWebServer();方法他是創(chuàng)建web容器的,而Tomcat不就是web容器,那是如何創(chuàng)建的呢,我們繼續(xù)看:

private void createWebServer() {

WebServer webServer = this.webServer;

ServletContext servletContext = getServletContext();

if (webServer == null && servletContext == null) {

ServletWebServerFactory factory = getWebServerFactory();

this.webServer = factory.getWebServer(getSelfInitializer());

}

else if (servletContext != null) {

try {

getSelfInitializer().onStartup(servletContext);

}

catch (ServletException ex) {

throw new ApplicationContextException(“Cannot initialize servlet context”,

ex);

}

}

initPropertySources();

}

factory.getWebServer(getSelfInitializer());他是通過(guò)工廠的方式創(chuàng)建的。

public interface ServletWebServerFactory {

WebServer getWebServer(ServletContextInitializer.。. initializers);

}

可以看到 它是一個(gè)接口,為什么會(huì)是接口。因?yàn)槲覀儾恢故荰omcat一種web容器。

我們看到還有Jetty,那我們來(lái)看TomcatServletWebServerFactory:

@Overridepublic WebServer getWebServer(ServletContextInitializer.。. initializers) {

Tomcat tomcat = new Tomcat();

File baseDir = (this.baseDirectory != null) ? this.baseDirectory

: createTempDir(“tomcat”);

tomcat.setBaseDir(baseDir.getAbsolutePath());

Connector connector = new Connector(this.protocol);

tomcat.getService().addConnector(connector);

customizeConnector(connector);

tomcat.setConnector(connector);

tomcat.getHost().setAutoDeploy(false);

configureEngine(tomcat.getEngine());

for (Connector additionalConnector : this.additionalTomcatConnectors) {

tomcat.getService().addConnector(additionalConnector);

}

prepareContext(tomcat.getHost(), initializers);

return getTomcatWebServer(tomcat);

}

那這塊代碼,就是我們要尋找的內(nèi)置Tomcat,在這個(gè)過(guò)程當(dāng)中,我們可以看到創(chuàng)建Tomcat的一個(gè)流程。

如果不明白的話, 我們?cè)谟昧硪环N方式來(lái)理解下,大家要應(yīng)該都知道stater舉點(diǎn)例子。

《dependency》

《groupId》org.springframework.boot《/groupId》

《artifactId》spring-boot-starter-data-redis《/artifactId》《/dependency》《dependency》

《groupId》org.springframework.boot《/groupId》

《artifactId》spring-boot-starter-freemarker《/artifactId》《/dependency》

首先自定義一個(gè)stater。

《parent》

《groupId》org.springframework.boot《/groupId》

《artifactId》spring-boot-starter-parent《/artifactId》

《version》2.1.4.RELEASE《/version》

《relativePath/》《/parent》《groupId》com.zgw《/groupId》《artifactId》gw-spring-boot-starter《/artifactId》《version》1.0-SNAPSHOT《/version》《dependencies》

《dependency》

《groupId》org.springframework.boot《/groupId》

《artifactId》spring-boot-autoconfigure《/artifactId》

《/dependency》《/dependencies》

我們先來(lái)看maven配置寫(xiě)入版本號(hào),如果自定義一個(gè)stater的話必須依賴spring-boot-autoconfigure這個(gè)包,我們先看下項(xiàng)目目錄。

public class GwServiceImpl implements GwService{

@Autowired

GwProperties properties;

@Override

public void Hello()

{

String name=properties.getName();

System.out.println(name+“說(shuō):你們好啊”);

}

}

我們做的就是通過(guò)配置文件來(lái)定制name這個(gè)是具體實(shí)現(xiàn)。

@Component@ConfigurationProperties(prefix = “spring.gwname”)

public class GwProperties {

String name=“zgw”;

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

}

這個(gè)類可以通過(guò)@ConfigurationProperties讀取配置文件。

@Configuration@ConditionalOnClass(GwService.class) //掃描類

@EnableConfigurationProperties(GwProperties.class) //讓配置類生效

public class GwAutoConfiguration {

/**

* 功能描述 托管給spring

* @author zgw

* @return

*/

@Bean

@ConditionalOnMissingBean

public GwService gwService()

{

return new GwServiceImpl();

}

}

這個(gè)為配置類,為什么這么寫(xiě)因?yàn)?,spring-boot的stater都是這么寫(xiě)的,我們可以參照他仿寫(xiě)stater,以達(dá)到自動(dòng)配置的目的,然后我們?cè)谕ㄟ^(guò)spring.factories也來(lái)進(jìn)行配置。

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.gw.GwAutoConfiguration

然后這樣一個(gè)簡(jiǎn)單的stater就完成了,然后可以進(jìn)行maven的打包,在其他項(xiàng)目引入就可以使用。

鏈接:cnblogs.com/cmt/p/14553189.html

責(zé)任編輯:haq

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • spring
    +關(guān)注

    關(guān)注

    0

    文章

    340

    瀏覽量

    14579
  • Boot
    +關(guān)注

    關(guān)注

    0

    文章

    150

    瀏覽量

    36141

原文標(biāo)題:10000 字講清楚 Spring Boot 注解原理

文章出處:【微信號(hào):harmonyos_developer,微信公眾號(hào):harmonyos_developer】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    校園點(diǎn)餐訂餐外賣(mài)跑腿Java源碼

    創(chuàng)建一個(gè)校園點(diǎn)餐訂餐外賣(mài)跑腿系統(tǒng)是一個(gè)復(fù)雜的項(xiàng)目,涉及到前端、后端、數(shù)據(jù)庫(kù)設(shè)計(jì)等多個(gè)方面。在這里,我可以提供一個(gè)簡(jiǎn)化的Java后端示例,使用Spring Boot框架來(lái)搭建一個(gè)基本的API服務(wù)。這個(gè)
    的頭像 發(fā)表于 12-24 14:55 ?282次閱讀
    校園點(diǎn)餐訂餐外賣(mài)跑腿Java源碼

    SSM開(kāi)發(fā)環(huán)境的搭建教程 SSM與Spring Boot的區(qū)別

    SSM開(kāi)發(fā)環(huán)境的搭建教程 SSM(Spring+SpringMVC+MyBatis)開(kāi)發(fā)環(huán)境的搭建涉及多個(gè)步驟,以下是詳細(xì)的教程: 創(chuàng)建Maven項(xiàng)目 : 使用Maven工具創(chuàng)建一個(gè)新的Maven
    的頭像 發(fā)表于 12-16 18:13 ?828次閱讀

    Spring 應(yīng)用合并之路(二):峰回路轉(zhuǎn),柳暗花明

    提醒下,決定拋開(kāi) Spring Boot 內(nèi)置的父子容器方案,完全自己實(shí)現(xiàn)父子容器。 如何加載 web 項(xiàng)目? 現(xiàn)在的難題只有一個(gè):如何加載 web 項(xiàng)目?加載完成后,如何持續(xù)持有 web 項(xiàng)目?經(jīng)過(guò)思考后,可以創(chuàng)建一個(gè) boot
    的頭像 發(fā)表于 12-12 11:22 ?911次閱讀

    Spring事務(wù)實(shí)現(xiàn)原理

    這些操作。 spring事務(wù)有編程式事務(wù)和聲明式事務(wù)兩種實(shí)現(xiàn)方式。編程式事務(wù)是通過(guò)編寫(xiě)代碼來(lái)管理事務(wù)的提交、回滾、以及事務(wù)的邊界。這意味著開(kāi)發(fā)者需要在代碼中顯式地調(diào)用事務(wù)的開(kāi)始、提交和回滾。聲明式事務(wù)是通過(guò)配置來(lái)管理事務(wù),您可以使用注解或XML配置來(lái)
    的頭像 發(fā)表于 11-08 10:10 ?930次閱讀
    <b class='flag-5'>Spring</b>事務(wù)實(shí)現(xiàn)原理

    dubbo3.0 服務(wù)導(dǎo)入導(dǎo)出原理

    不管是服務(wù)導(dǎo)出還是服務(wù)引入,都發(fā)生在應(yīng)用啟動(dòng)過(guò)程中,比如:在啟動(dòng)類上加上 @EnableDubbo 時(shí),該注解上有一個(gè) @DubboComponentScan 注解
    的頭像 發(fā)表于 11-04 15:01 ?248次閱讀
    dubbo3.0 服務(wù)導(dǎo)入導(dǎo)出原理

    ti814x-ddr3-init-u-boot

    電子發(fā)燒友網(wǎng)站提供《ti814x-ddr3-init-u-boot.pdf》資料免費(fèi)下載
    發(fā)表于 10-12 10:38 ?0次下載
    ti814x-ddr3-init-u-<b class='flag-5'>boot</b>

    OMAP-L138_Flash And Boot Utils使用及編譯指導(dǎo)

    電子發(fā)燒友網(wǎng)站提供《OMAP-L138_Flash And Boot Utils使用及編譯指導(dǎo).pdf》資料免費(fèi)下載
    發(fā)表于 09-05 11:26 ?0次下載
    OMAP-L138_Flash And <b class='flag-5'>Boot</b> Utils使用及編譯指導(dǎo)

    Spring Cloud Gateway網(wǎng)關(guān)框架

    SpringCloud Gateway功能特征如下: (1) 基于Spring Framework 5, Project Reactor 和 Spring Boot 2.0 進(jìn)行構(gòu)建; (2) 動(dòng)態(tài)路由:能夠匹配任何請(qǐng)求屬性;
    的頭像 發(fā)表于 08-22 09:58 ?589次閱讀
    <b class='flag-5'>Spring</b> Cloud Gateway網(wǎng)關(guān)框架

    單片機(jī)boot0和boot1怎么設(shè)置

    單片機(jī)Boot0和Boot1簡(jiǎn)介 Boot0和Boot1是單片機(jī)啟動(dòng)模式選擇引腳,用于選擇單片機(jī)的啟動(dòng)模式。 Boot0和
    的頭像 發(fā)表于 08-22 09:50 ?3613次閱讀

    stm32讀取boot引腳狀態(tài)

    在STM32微控制器中,Boot引腳(通常指的是BOOT0和BOOT1引腳)的狀態(tài)決定了設(shè)備啟動(dòng)時(shí)的引導(dǎo)模式。這些引腳的狀態(tài)在復(fù)位時(shí)被讀取,并據(jù)此選擇啟動(dòng)哪塊存儲(chǔ)器。比如,STM32F103系列
    的頭像 發(fā)表于 08-22 09:48 ?1833次閱讀

    STM32引腳中的BOOT1在哪里

    STM32是STMicroelectronics(意法半導(dǎo)體)推出的一系列32位微控制器,廣泛應(yīng)用于嵌入式系統(tǒng)設(shè)計(jì)。關(guān)于STM32的BOOT1引腳,它主要與系統(tǒng)的啟動(dòng)模式有關(guān)。 BOOT1引腳功能
    的頭像 發(fā)表于 08-22 09:43 ?2975次閱讀

    stm32boot0和boot1對(duì)應(yīng)哪個(gè)p引腳

    STM32系列微控制器是一種廣泛應(yīng)用于嵌入式系統(tǒng)領(lǐng)域的32位微控制器。在STM32系列微控制器中,BOOT0和BOOT1是兩個(gè)重要的引腳,它們用于設(shè)置設(shè)備的啟動(dòng)模式。 首先,讓我們了解STM32系列
    的頭像 發(fā)表于 08-22 09:40 ?4255次閱讀

    vue+spring boot人員定位系統(tǒng)源碼,實(shí)現(xiàn)實(shí)時(shí)定位、智慧調(diào)度、軌跡追蹤

    、機(jī)具、物料上定位標(biāo)簽回傳的位置信息數(shù)據(jù),采用多維定位模式,精確定位人、機(jī)具、物料的實(shí)時(shí)位置,實(shí)現(xiàn)實(shí)時(shí)定位、物料標(biāo)簽配置、智慧調(diào)度、軌跡追蹤、工時(shí)統(tǒng)計(jì)、區(qū)域物料統(tǒng)計(jì)、電子圍欄等應(yīng)用功能。 技術(shù)架構(gòu):java+ spring boot+ v
    的頭像 發(fā)表于 08-08 14:27 ?1006次閱讀
    vue+<b class='flag-5'>spring</b> <b class='flag-5'>boot</b>人員定位系統(tǒng)源碼,實(shí)現(xiàn)實(shí)時(shí)定位、智慧調(diào)度、軌跡追蹤

    玩轉(zhuǎn)Spring狀態(tài)機(jī)

    說(shuō)起Spring狀態(tài)機(jī),大家很容易聯(lián)想到這個(gè)狀態(tài)機(jī)和設(shè)計(jì)模式中狀態(tài)模式的區(qū)別是啥呢?沒(méi)錯(cuò),Spring狀態(tài)機(jī)就是狀態(tài)模式的一種實(shí)現(xiàn),在介紹Spring狀態(tài)機(jī)之前,讓我們來(lái)看看設(shè)計(jì)模式中的狀態(tài)模式
    的頭像 發(fā)表于 06-25 14:21 ?1100次閱讀
    玩轉(zhuǎn)<b class='flag-5'>Spring</b>狀態(tài)機(jī)

    UWB室內(nèi)外高精度一體化融合定位系統(tǒng)源碼 UWB技術(shù)定位系統(tǒng)應(yīng)用場(chǎng)景 Java+Spring boot+MYSQL?技術(shù)開(kāi)發(fā)

    UWB室內(nèi)外高精度一體化融合定位系統(tǒng)源碼 UWB技術(shù)定位系統(tǒng)應(yīng)用場(chǎng)景 Java+Spring boot+MYSQL?技術(shù)開(kāi)發(fā) 系統(tǒng)聚焦基于UWB(超寬帶)技術(shù)的底層定位網(wǎng)絡(luò)和定位算法,通過(guò)對(duì)定位分站
    的頭像 發(fā)表于 06-18 10:46 ?601次閱讀
    UWB室內(nèi)外高精度一體化融合定位系統(tǒng)源碼 UWB技術(shù)定位系統(tǒng)應(yīng)用場(chǎng)景 Java+<b class='flag-5'>Spring</b> <b class='flag-5'>boot</b>+MYSQL?技術(shù)開(kāi)發(fā)