SpringBoot的@Enable*註解的使用介紹
@EnableAsync或@EnableConfigurationProperties背後的執行原理,是使用了@Import註解。
@Import({User.class,Role.class,MyConfiguration.class}),@Import裡面可以存放陣列型別的。
@Import用來匯入一個或多個類(bean被spring容器託管)、或者配置類(配置類裡面的Bean都會被spring容器託管)。
@Enable*其實就是使用了@Import,@Import其實就是匯入了配置類。
1、以如何將配置檔案裡面的配置注入到bean中。之前貼過了,這裡再貼一下,權當自己熟悉了。
1 package com.bie.enable; 2 3 import org.springframework.boot.context.properties.ConfigurationProperties; 4 import org.springframework.stereotype.Component; 5 6 /** 7 * 8 * @Description TODO 9 * @author biehl 10 * @Date 2018年12月31日 下午1:13:07 11 * 12 */ 13 @Component 14@ConfigurationProperties(prefix = "tomcat") 15 public class TomcatProperties { 16 17 private String hosts; 18 private String ports; 19 public String getHosts() { 20 return hosts; 21 } 22 public void setHosts(String hosts) { 23 this.hosts = hosts; 24 }25 public String getPorts() { 26 return ports; 27 } 28 public void setPorts(String ports) { 29 this.ports = ports; 30 } 31 @Override 32 public String toString() { 33 return "TomcatProperties [hosts=" + hosts + ", ports=" + ports + "]"; 34 } 35 36 37 }
然後在配置檔案裡面進行配置:
tomcat.hosts=192.168.11.12 tomcat.ports=8090
然後寫一個主執行類來進行執行:
可以看到正常運行了。執行效果就不貼上了。
package com.bie.enable; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; /** * * @Description TODO * @author biehl * @Date 2018年12月31日 下午1:15:27 * */ @SpringBootApplication public class TomcatApplication { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(TomcatApplication.class, args); System.out.println("------------------------------------------------------------"); System.out.println(context.getEnvironment().getProperty("tomcat.hosts"));//從容器中獲取到物件tomcat.hosts System.out.println(context.getEnvironment().getProperty("tomcat.ports"));//從容器中獲取到物件tomcat.ports System.out.println("------------------------------------------------------------"); context.close(); } }
2、ctrl鍵和滑鼠左鍵點開@SpringBootApplication註解,其實可以發現,註解裡面主要使用瞭如此註解@EnableAutoConfiguration和@ComponentScan來實現的功能的。
注意1:@SpringBootConfiguration註解和Spring的@Configuration註解的作用是一樣的。
注意2:@EnableConfigurationProperties註解是替代@EnableAutoConfiguration,發揮作用的是@EnableConfigurationProperties註解。
然後呢,你會發現,使用這兩個註解和使用@SpringBootApplication註解的作用是一樣的。
package com.bie.enable; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.ComponentScan; /** * * @Description TODO * @author biehl * @Date 2018年12月31日 下午1:15:27 * */ //@SpringBootApplication @EnableAutoConfiguration @ComponentScan public class TomcatApplication { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(TomcatApplication.class, args); System.out.println("------------------------------------------------------------"); System.out.println(context.getEnvironment().getProperty("tomcat.hosts")); System.out.println(context.getEnvironment().getProperty("tomcat.ports")); System.out.println("------------------------------------------------------------"); context.close(); } }
執行效果如下所示:
上面說了發揮作用的@EnableConfigurationProperties,然而我測試的時候發現如下所示:
1 . ____ _ __ _ _ 2 /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ 3 ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ 4 \\/ ___)| |_)| | | | | || (_| | ) ) ) ) 5 ' |____| .__|_| |_|_| |_\__, | / / / / 6 =========|_|==============|___/=/_/_/_/ 7 :: Spring Boot :: (v1.5.10.RELEASE) 8 9 2018-12-31 13:27:18.515 INFO 2176 --- [ main] com.bie.enable.TomcatApplication : Starting TomcatApplication on DESKTOP-T450s with PID 2176 (E:\eclipeswork\guoban\spring-boot-hello\target\classes started by Aiyufei in E:\eclipeswork\guoban\spring-boot-hello) 10 2018-12-31 13:27:18.521 INFO 2176 --- [ main] com.bie.enable.TomcatApplication : No active profile set, falling back to default profiles: default 11 2018-12-31 13:27:18.600 INFO 2176 --- [ main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot[email protected]101df177: startup date [Mon Dec 31 13:27:18 CST 2018]; root of context hierarchy 12 2018-12-31 13:27:18.932 WARN 2176 --- [ main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean. 13 2018-12-31 13:27:19.423 ERROR 2176 --- [ main] o.s.boot.SpringApplication : Application startup failed 14 15 org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean. 16 at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:137) ~[spring-boot-1.5.10.RELEASE.jar:1.5.10.RELEASE] 17 at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:537) ~[spring-context-4.3.14.RELEASE.jar:4.3.14.RELEASE] 18 at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) ~[spring-boot-1.5.10.RELEASE.jar:1.5.10.RELEASE] 19 at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) [spring-boot-1.5.10.RELEASE.jar:1.5.10.RELEASE] 20 at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) [spring-boot-1.5.10.RELEASE.jar:1.5.10.RELEASE] 21 at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) [spring-boot-1.5.10.RELEASE.jar:1.5.10.RELEASE] 22 at org.springframework.boot.SpringApplication.run(SpringApplication.java:1118) [spring-boot-1.5.10.RELEASE.jar:1.5.10.RELEASE] 23 at org.springframework.boot.SpringApplication.run(SpringApplication.java:1107) [spring-boot-1.5.10.RELEASE.jar:1.5.10.RELEASE] 24 at com.bie.enable.TomcatApplication.main(TomcatApplication.java:21) [classes/:na] 25 Caused by: org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean. 26 at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.getEmbeddedServletContainerFactory(EmbeddedWebApplicationContext.java:189) ~[spring-boot-1.5.10.RELEASE.jar:1.5.10.RELEASE] 27 at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:162) ~[spring-boot-1.5.10.RELEASE.jar:1.5.10.RELEASE] 28 at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:134) ~[spring-boot-1.5.10.RELEASE.jar:1.5.10.RELEASE] 29 ... 8 common frames omitted
然而就百度唄,發現並沒有很清晰說這個問題怎麼解決的。
在https://stackoverflow.com/questions/37114076/exception-in-thread-main-org-springframework-context-applicationcontextexcepti發現了一段話,還挺有意思的。如是說,丟失註解,其實是依賴不對的問題,哈哈哈,然後看看自己的依賴。發現了問題所在。
我一開始是使用的<artifactId>spring-boot-starter-web</artifactId>,這種web的依賴,修改為了<artifactId>spring-boot-starter</artifactId>普通專案的依賴,這樣使用@EnableConfigurationProperties註解是替代@EnableAutoConfiguration執行就沒有問題了。
@EnableConfigurationProperties註解是用來啟用一個特性的,這個特性就是,可以把配置檔案注入到bean裡面去。一般是要和@ConfigurationProperties一起使用。
2、SpringBoot中如何啟用一個非同步,看看SpringBoot如何對非同步進行支援的。
1 package com.bie.enable; 2 3 import java.util.concurrent.TimeUnit; 4 5 import org.springframework.scheduling.annotation.Async; 6 import org.springframework.stereotype.Component; 7 8 /** 9 * 10 * @Description TODO 11 * @author biehl 12 * @Date 2018年12月31日 下午2:08:52 13 * 1、實現Runnable介面的類要實現run的方法 14 */ 15 @Component //新增到容器中 16 public class SyncRunnable implements Runnable { 17 18 //@Async註解實現,非同步執行 19 @Async 20 public void run() { 21 try { 22 for (int i = 0; i < 10; i++) { 23 System.out.println("-------------------" + i); 24 TimeUnit.SECONDS.sleep(1); 25 } 26 } catch (InterruptedException e) { 27 e.printStackTrace(); 28 } 29 30 } 31 32 }
然後寫主執行類,如下所示:
1 package com.bie.enable; 2 3 import org.springframework.boot.SpringApplication; 4 import org.springframework.boot.autoconfigure.SpringBootApplication; 5 import org.springframework.context.ConfigurableApplicationContext; 6 import org.springframework.scheduling.annotation.EnableAsync; 7 8 /** 9 * 10 * @Description TODO 11 * @author biehl 12 * @Date 2018年12月31日 下午2:11:52 13 * 14 */ 15 @SpringBootApplication 16 @EnableAsync //啟用非同步註解 17 public class SyncApplication { 18 19 public static void main(String[] args) { 20 ConfigurableApplicationContext context = SpringApplication.run(SyncApplication.class, args); 21 SyncRunnable bean = context.getBean(SyncRunnable.class); 22 System.out.println(bean); 23 bean.run(); 24 System.out.println("-----------end-----------"); 25 26 //關閉 27 context.close(); 28 } 29 }
如果使用上面的會報錯,如下所示:
1 . ____ _ __ _ _ 2 /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ 3 ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ 4 \\/ ___)| |_)| | | | | || (_| | ) ) ) ) 5 ' |____| .__|_| |_|_| |_\__, | / / / / 6 =========|_|==============|___/=/_/_/_/ 7 :: Spring Boot :: (v1.5.10.RELEASE) 8 9 2018-12-31 14:45:34.676 INFO 7500 --- [ main] com.bie.enable.SyncApplication : Starting SyncApplication on DESKTOP-T450s with PID 7500 (E:\eclipeswork\guoban\spring-boot-hello\target\classes started by Aiyufei in E:\eclipeswork\guoban\spring-boot-hello) 10 2018-12-31 14:45:34.682 INFO 7500 --- [ main] com.bie.enable.SyncApplication : No active profile set, falling back to default profiles: default 11 2018-12-31 14:45:34.991 INFO 7500 --- [ main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.spring[email protected]103f852: startup date [Mon Dec 31 14:45:34 CST 2018]; root of context hierarchy 12 2018-12-31 14:45:38.523 INFO 7500 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup 13 2018-12-31 14:45:38.623 INFO 7500 --- [ main] com.bie.enable.SyncApplication : Started SyncApplication in 5.1 seconds (JVM running for 5.898) 14 Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.bie.enable.SyncRunnable' available 15 at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:353) 16 at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:340) 17 at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1092) 18 at com.bie.enable.SyncApplication.main(SyncApplication.java:21) 19 2018-12-31 14:45:38.663 INFO 7500 --- [ Thread-2] s.c.a.AnnotationConfigApplicationContext : Closing org.spring[email protected]103f852: startup date [Mon Dec 31 14:45:34 CST 2018]; root of context hierarchy 20 2018-12-31 14:45:38.670 INFO 7500 --- [ Thread-2] o.s.j.e.a.AnnotationMBeanExporter : Unregistering JMX-exposed beans on shutdown
百度了一下,參考連結:https://www.cnblogs.com/javJoker/p/7281688.html
修改為瞭如下所示,參考連結的問題,確實也問住我了,需要深思一下吧。
@EnableAsync //啟用非同步註解,一般是和@Async一起使用。來實現非同步的功能。
1 package com.bie.enable; 2 3 import org.springframework.boot.SpringApplication; 4 import org.springframework.boot.autoconfigure.SpringBootApplication; 5 import org.springframework.context.ConfigurableApplicationContext; 6 import org.springframework.scheduling.annotation.EnableAsync; 7 8 /** 9 * 10 * @Description TODO 11 * @author biehl 12 * @Date 2018年12月31日 下午2:11:52 13 * 14 */ 15 @SpringBootApplication 16 @EnableAsync //啟用非同步註解 17 public class SyncApplication { 18 19 public static void main(String[] args) { 20 ConfigurableApplicationContext context = SpringApplication.run(SyncApplication.class, args); 21 Runnable bean = context.getBean(Runnable.class); 22 System.out.println(bean); 23 bean.run(); 24 System.out.println("-----------end-----------"); 25 26 //關閉 27 context.close(); 28 } 29 }
執行結果如下所示:
待續......