真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

如何掌握Spring

這篇文章主要講解了“如何掌握Spring”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“如何掌握Spring”吧!

創(chuàng)新互聯(lián)建站專業(yè)為企業(yè)提供廣水網(wǎng)站建設(shè)、廣水做網(wǎng)站、廣水網(wǎng)站設(shè)計(jì)、廣水網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁(yè)設(shè)計(jì)與制作、廣水企業(yè)網(wǎng)站模板建站服務(wù),十余年廣水做網(wǎng)站經(jīng)驗(yàn),不只是建網(wǎng)站,更提供有價(jià)值的思路和整體網(wǎng)絡(luò)服務(wù)。

Spring 是一個(gè)控制反轉(zhuǎn)依賴管理的容器,作為 Java Web 的開發(fā)人員,基本沒有不熟悉 Spring 技術(shù)棧的,盡管在依賴注入領(lǐng)域,Java  Web 領(lǐng)域不乏其他優(yōu)秀的框架,如 google 開源的依賴管理框架 guice,如 Jersey web 框架等。但 Spring 已經(jīng)是 Java Web  領(lǐng)域使用最多,應(yīng)用最廣泛的 Java 框架。

此文將專注講解如何在 Spring 容器啟動(dòng)時(shí)實(shí)現(xiàn)我們自己想要實(shí)現(xiàn)的邏輯。我們時(shí)常會(huì)遇到在 Spring  啟動(dòng)的時(shí)候必須完成一些初始化的操作,如創(chuàng)建定時(shí)任務(wù),創(chuàng)建連接池等。

如果沒有 Spring 容器,不依賴于 Spring 的實(shí)現(xiàn),回歸 Java 類實(shí)現(xiàn)本身,我們可以在靜態(tài)代碼塊,在類構(gòu)造函數(shù)中實(shí)現(xiàn)相應(yīng)的邏輯,Java  類的初始化順序依次是靜態(tài)變量 > 靜態(tài)代碼塊 > 全局變量 > 初始化代碼塊 > 構(gòu)造器。

比如,Log4j 的初始化,就是在 LogManager 的靜態(tài)代碼塊中實(shí)現(xiàn)的:

static {     Hierarchy h = new Hierarchy(new RootLogger((Level) Level.DEBUG));     repositorySelector = new DefaultRepositorySelector(h);      String override =OptionConverter.getSystemProperty(DEFAULT_INIT_OVERRIDE_KEY,null);      if(override == null || "false".equalsIgnoreCase(override)) {           String configurationOptionStr = OptionConverter.getSystemProperty(DEFAULT_CONFIGURATION_KEY, null);           String configuratorClassName = OptionConverter.getSystemProperty(CONFIGURATOR_CLASS_KEY, null);            URL url = null;            if(configurationOptionStr == null) {             url = Loader.getResource(DEFAULT_XML_CONFIGURATION_FILE);             if(url == null) {               url = Loader.getResource(DEFAULT_CONFIGURATION_FILE);             }           } else {             try {               url = new URL(configurationOptionStr);             } catch (MalformedURLException ex) {               url = Loader.getResource(configurationOptionStr);             }           }            if(url != null) {             LogLog.debug("Using URL ["+url+"] for automatic log4j configuration.");             try {                 OptionConverter.selectAndConfigure(url, configuratorClassName,LogManager.getLoggerRepository());             } catch (NoClassDefFoundError e) {                 LogLog.warn("Error during default initialization", e);             }           } else {               LogLog.debug("Could not find resource: ["+configurationOptionStr+"].");           }     } else {             LogLog.debug("Default initialization of overridden by " +  DEFAULT_INIT_OVERRIDE_KEY + "property.");     } }

比如在構(gòu)造函數(shù)中實(shí)現(xiàn)相應(yīng)的邏輯:

@Component public class CustomBean {      @Autowired     private Environment env;      public CustomBean() {         env.getActiveProfiles();     } }

這里考驗(yàn)一下各位,上面的代碼是否可以正常運(yùn)行。—— 不行,構(gòu)造函數(shù)中的env將會(huì)發(fā)生NullPointException異常。這是因?yàn)樵?Spring  中將先初始化 Bean,也就是會(huì)先調(diào)用類的構(gòu)造函數(shù),然后才注入成員變量依賴的  Bean(@Autowired和@Resource注解修飾的成員變量),注意@Value等注解的配置的注入也是在構(gòu)造函數(shù)之后。

PostConstruct

在 Spring 中,我們可以使用@PostConstruct在 Bean 初始化之后實(shí)現(xiàn)相應(yīng)的初始化邏輯,@PostConstruct修飾的方法將在  Bean 初始化完成之后執(zhí)行,此時(shí) Bean 的依賴也已經(jīng)注入完成,因此可以在方法中調(diào)用注入的依賴 Bean。

@Component public class CustomBean {      @Autowired     private Environment env;      @PostConstruce     public void init() {         env.getActiveProfiles();     } }

與@PostConstruct相對(duì)應(yīng)的,如果想在 Bean 注銷時(shí)完成一些清掃工作,如關(guān)閉線程池等,可以使用@PreDestroy注解:

@Component public class CustomBean {      @Autowired     private ExecutorService executor = Executors.newFixedThreadPool(1)      @PreDestroy     public void destroy() {         env.getActiveProfiles();     } }

InitializingBean

實(shí)現(xiàn) Spring 的InitializingBean接口同樣可以實(shí)現(xiàn)以上在 Bean  初始化完成之后執(zhí)行相應(yīng)邏輯的功能,實(shí)現(xiàn)InitializingBean接口,在afterPropertiesSet方法中實(shí)現(xiàn)邏輯:

@Component public class CustomBean implements InitializingBean {      private static final Logger LOG       = Logger.getLogger(InitializingBeanExampleBean.class);      @Autowired     private Environment environment;      @Override     public void afterPropertiesSet() throws Exception {         LOG.info(environment.getDefaultProfiles());     } }

ApplicationListener

我們可以在 Spring 容器初始化的時(shí)候?qū)崿F(xiàn)我們想要的初始化邏輯。這時(shí)我們就可以使用到 Spring 的初始化事件。Spring  有一套完整的事件機(jī)制,在 Spring 啟動(dòng)的時(shí)候,Spring 容器本身預(yù)設(shè)了很多事件,在 Spring  初始化的整個(gè)過程中在相應(yīng)的節(jié)點(diǎn)觸發(fā)相應(yīng)的事件,我們可以通過監(jiān)聽這些事件來實(shí)現(xiàn)我們的初始化邏輯。Spring 的事件實(shí)現(xiàn)如下:

  • ApplicationEvent,事件對(duì)象,由 ApplicationContext 發(fā)布,不同的實(shí)現(xiàn)類代表不同的事件類型。

  • ApplicationListener,監(jiān)聽對(duì)象,任何實(shí)現(xiàn)了此接口的 Bean 都會(huì)收到相應(yīng)的事件通知。實(shí)現(xiàn)了 ApplicationListener  接口之后,需要實(shí)現(xiàn)方法 onApplicationEvent(),在容器將所有的 Bean 都初始化完成之后,就會(huì)執(zhí)行該方法。

與 Spring Context 生命周期相關(guān)的幾個(gè)事件有以下幾個(gè):

  • ApplicationStartingEvent: 這個(gè)事件在 Spring Boot  應(yīng)用運(yùn)行開始時(shí),且進(jìn)行任何處理之前發(fā)送(除了監(jiān)聽器和初始化器注冊(cè)之外)。

  • ContextRefreshedEvent: ApplicationContext 被初始化或刷新時(shí),該事件被發(fā)布。這也可以在  ConfigurableApplicationContext 接口中使用 refresh() 方法來發(fā)生。

  • ContextStartedEvent: 當(dāng)使用 ConfigurableApplicationContext 接口中的 start() 方法啟動(dòng)  ApplicationContext 時(shí),該事件被觸發(fā)。你可以查詢你的數(shù)據(jù)庫(kù),或者你可以在接受到這個(gè)事件后重啟任何停止的應(yīng)用程序。

  • ApplicationReadyEvent: 這個(gè)事件在任何 application/ command-line runners 調(diào)用之后發(fā)送。

  • ContextClosedEvent: 當(dāng)使用 ConfigurableApplicationContext 接口中的 close() 方法關(guān)閉  ApplicationContext 時(shí),該事件被觸發(fā)。一個(gè)已關(guān)閉的上下文到達(dá)生命周期末端;它不能被刷新或重啟。

  • ContextStoppedEvent: Spring 最后完成的事件。

因此,如果我們想在 Spring 啟動(dòng)的時(shí)候?qū)崿F(xiàn)一些相應(yīng)的邏輯,可以找到 Spring  啟動(dòng)過程中符合我們需要的事件,通過監(jiān)聽相應(yīng)的事件來完成我們的邏輯:

@Component @Slf4j public class StartupApplicationListenerExample implements ApplicationListener<ContextRefreshedEvent> {      @Override     public void onApplicationEvent(ContextRefreshedEvent event) {         log.info("Subject ContextRefreshedEvent");     } }

除了通過實(shí)現(xiàn)ApplicationListener接口來監(jiān)聽相應(yīng)的事件,Spring  的事件機(jī)制也實(shí)現(xiàn)了通過@EventListener注解來監(jiān)聽相對(duì)應(yīng)事件:

@Component @Slf4j public class StartupApplicationListenerExample {      @EventListener     public void onApplicationEvent(ContextRefreshedEvent event) {         log.info("Subject ContextRefreshedEvent");     } }

Spring Event 是一套完善的進(jìn)程內(nèi)事件發(fā)布訂閱機(jī)制,我們除了用來監(jiān)聽 Spring 內(nèi)置的事件,也可以使用 Spring Event  實(shí)現(xiàn)自定義的事件發(fā)布訂閱功能。

Constructor 注入

在學(xué)習(xí) Spring 的注入機(jī)制的時(shí)候,我們都知道 Spring 可以通過構(gòu)造函數(shù)、Setter  和反射成員變量注入等方式。上面我們?cè)诔蓡T變量上通過@Autoware注解注入依賴 Bean,但是在 Bean 的構(gòu)造函數(shù)函數(shù)中卻無法使用到注入的 Bean(因?yàn)? Bean 還未注入),其實(shí)我們也是使用 Spring 的構(gòu)造函數(shù)注入方式, 這也是 Spring 推薦的注入機(jī)制(在我們使用 IDEA  的時(shí)候,如果沒有關(guān)閉相應(yīng)的代碼 Warning 機(jī)制,會(huì)發(fā)現(xiàn)在成員變量上的@Autoware是黃色的,也就是 idea 不建議的代碼)。Spring  更推薦構(gòu)造函數(shù)注入的方式:

@Component @Slf4j public class ConstructorBean {      private final Environment environment;      @Autowired     public LogicInConstructorExampleBean(Environment environment) {         this.environment = environment;         log.info(Arrays.asList(environment.getDefaultProfiles()));     } }

CommandLineRunner

如果我們的項(xiàng)目使用的是 Spring Boot,那么可以使用 Spring Boot 提供的 CommandLineRunner  接口來實(shí)現(xiàn)初始化邏輯,Spring Boot 將在啟動(dòng)初始化完成之后調(diào)用實(shí)現(xiàn)了CommandLineRunner的接口的run方法:

@Component @Slf4j public class CommandLineAppStartupRunner implements CommandLineRunner {      @Override     public void run(String...args) throws Exception {         log.info("Increment counter");     } }

并且,多個(gè)CommandLineRunner實(shí)現(xiàn),可以通過@Order來控制它們的執(zhí)行順序。

SmartLifecycle

還有一種更高級(jí)的方法來實(shí)現(xiàn)我們的邏輯。這可以 Spring 高級(jí)開發(fā)必備技能哦。SmartLifecycle  不僅僅能在初始化后執(zhí)行一個(gè)邏輯,還能再關(guān)閉前執(zhí)行一個(gè)邏輯,并且也可以控制多個(gè) SmartLifecycle  的執(zhí)行順序,就像這個(gè)類名表示的一樣,這是一個(gè)智能的生命周期管理接口。

  • start():bean 初始化完畢后,該方法會(huì)被執(zhí)行。

  • stop():容器關(guān)閉后,spring 容器發(fā)現(xiàn)當(dāng)前對(duì)象實(shí)現(xiàn)了 SmartLifecycle,就調(diào)用 stop(Runnable), 如果只是實(shí)現(xiàn)了  Lifecycle,就調(diào)用 stop()。

  • isRunning:當(dāng)前狀態(tài),用來判你的斷組件是否在運(yùn)行。

  • getPhase:控制多個(gè) SmartLifecycle 的回調(diào)順序的,返回值越小越靠前執(zhí)行 start() 方法,越靠后執(zhí)行 stop()  方法。

  • isAutoStartup():start 方法被執(zhí)行前先看此方法返回值,返回 false 就不執(zhí)行 start 方法了。

  • stop(Runnable):容器關(guān)閉后,spring 容器發(fā)現(xiàn)當(dāng)前對(duì)象實(shí)現(xiàn)了 SmartLifecycle,就調(diào)用 stop(Runnable),  如果只是實(shí)現(xiàn)了 Lifecycle,就調(diào)用 stop()。

@Component public class SmartLifecycleExample implements SmartLifecycle {      private boolean isRunning = false;      @Override     public void start() {         System.out.println("start");         isRunning = true;     }      @Override     public int getPhase() {         // 默認(rèn)為 0         return 0;     }      @Override     public boolean isAutoStartup() {         // 默認(rèn)為 false         return true;     }      @Override     public boolean isRunning() {         // 默認(rèn)返回 false         return isRunning;     }      @Override     public void stop(Runnable callback) {         System.out.println("stop(Runnable)");         callback.run();         isRunning = false;     }      @Override     public void stop() {         System.out.println("stop");          isRunning = false;     }  }

感謝各位的閱讀,以上就是“如何掌握Spring”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對(duì)如何掌握Spring這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!


當(dāng)前題目:如何掌握Spring
本文路徑:http://weahome.cn/article/gghssd.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部