中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何掌握Spring

發布時間:2021-10-20 15:26:05 來源:億速云 閱讀:105 作者:iii 欄目:web開發

這篇文章主要講解了“如何掌握Spring”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“如何掌握Spring”吧!

Spring 是一個控制反轉依賴管理的容器,作為 Java Web 的開發人員,基本沒有不熟悉 Spring 技術棧的,盡管在依賴注入領域,Java  Web 領域不乏其他優秀的框架,如 google 開源的依賴管理框架 guice,如 Jersey web 框架等。但 Spring 已經是 Java Web  領域使用最多,應用最廣泛的 Java 框架。

此文將專注講解如何在 Spring 容器啟動時實現我們自己想要實現的邏輯。我們時常會遇到在 Spring  啟動的時候必須完成一些初始化的操作,如創建定時任務,創建連接池等。

如果沒有 Spring 容器,不依賴于 Spring 的實現,回歸 Java 類實現本身,我們可以在靜態代碼塊,在類構造函數中實現相應的邏輯,Java  類的初始化順序依次是靜態變量 > 靜態代碼塊 > 全局變量 > 初始化代碼塊 > 構造器。

比如,Log4j 的初始化,就是在 LogManager 的靜態代碼塊中實現的:

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.");     } }

比如在構造函數中實現相應的邏輯:

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

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

PostConstruct

在 Spring 中,我們可以使用@PostConstruct在 Bean 初始化之后實現相應的初始化邏輯,@PostConstruct修飾的方法將在  Bean 初始化完成之后執行,此時 Bean 的依賴也已經注入完成,因此可以在方法中調用注入的依賴 Bean。

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

與@PostConstruct相對應的,如果想在 Bean 注銷時完成一些清掃工作,如關閉線程池等,可以使用@PreDestroy注解:

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

InitializingBean

實現 Spring 的InitializingBean接口同樣可以實現以上在 Bean  初始化完成之后執行相應邏輯的功能,實現InitializingBean接口,在afterPropertiesSet方法中實現邏輯:

@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 容器初始化的時候實現我們想要的初始化邏輯。這時我們就可以使用到 Spring 的初始化事件。Spring  有一套完整的事件機制,在 Spring 啟動的時候,Spring 容器本身預設了很多事件,在 Spring  初始化的整個過程中在相應的節點觸發相應的事件,我們可以通過監聽這些事件來實現我們的初始化邏輯。Spring 的事件實現如下:

  • ApplicationEvent,事件對象,由 ApplicationContext 發布,不同的實現類代表不同的事件類型。

  • ApplicationListener,監聽對象,任何實現了此接口的 Bean 都會收到相應的事件通知。實現了 ApplicationListener  接口之后,需要實現方法 onApplicationEvent(),在容器將所有的 Bean 都初始化完成之后,就會執行該方法。

與 Spring Context 生命周期相關的幾個事件有以下幾個:

  • ApplicationStartingEvent: 這個事件在 Spring Boot  應用運行開始時,且進行任何處理之前發送(除了監聽器和初始化器注冊之外)。

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

  • ContextStartedEvent: 當使用 ConfigurableApplicationContext 接口中的 start() 方法啟動  ApplicationContext 時,該事件被觸發。你可以查詢你的數據庫,或者你可以在接受到這個事件后重啟任何停止的應用程序。

  • ApplicationReadyEvent: 這個事件在任何 application/ command-line runners 調用之后發送。

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

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

因此,如果我們想在 Spring 啟動的時候實現一些相應的邏輯,可以找到 Spring  啟動過程中符合我們需要的事件,通過監聽相應的事件來完成我們的邏輯:

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

除了通過實現ApplicationListener接口來監聽相應的事件,Spring  的事件機制也實現了通過@EventListener注解來監聽相對應事件:

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

Spring Event 是一套完善的進程內事件發布訂閱機制,我們除了用來監聽 Spring 內置的事件,也可以使用 Spring Event  實現自定義的事件發布訂閱功能。

Constructor 注入

在學習 Spring 的注入機制的時候,我們都知道 Spring 可以通過構造函數、Setter  和反射成員變量注入等方式。上面我們在成員變量上通過@Autoware注解注入依賴 Bean,但是在 Bean 的構造函數函數中卻無法使用到注入的 Bean(因為  Bean 還未注入),其實我們也是使用 Spring 的構造函數注入方式, 這也是 Spring 推薦的注入機制(在我們使用 IDEA  的時候,如果沒有關閉相應的代碼 Warning 機制,會發現在成員變量上的@Autoware是黃色的,也就是 idea 不建議的代碼)。Spring  更推薦構造函數注入的方式:

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

CommandLineRunner

如果我們的項目使用的是 Spring Boot,那么可以使用 Spring Boot 提供的 CommandLineRunner  接口來實現初始化邏輯,Spring Boot 將在啟動初始化完成之后調用實現了CommandLineRunner的接口的run方法:

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

并且,多個CommandLineRunner實現,可以通過@Order來控制它們的執行順序。

SmartLifecycle

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

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

  • stop():容器關閉后,spring 容器發現當前對象實現了 SmartLifecycle,就調用 stop(Runnable), 如果只是實現了  Lifecycle,就調用 stop()。

  • isRunning:當前狀態,用來判你的斷組件是否在運行。

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

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

  • stop(Runnable):容器關閉后,spring 容器發現當前對象實現了 SmartLifecycle,就調用 stop(Runnable),  如果只是實現了 Lifecycle,就調用 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() {         // 默認為 0         return 0;     }      @Override     public boolean isAutoStartup() {         // 默認為 false         return true;     }      @Override     public boolean isRunning() {         // 默認返回 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”的內容了,經過本文的學習后,相信大家對如何掌握Spring這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

翁牛特旗| 西青区| 凉城县| 建始县| 灌南县| 萍乡市| 铜陵市| 上高县| 青浦区| 湾仔区| 勐海县| 遂川县| 共和县| 京山县| 东丰县| 板桥市| 来凤县| 革吉县| 乐平市| 丁青县| 弋阳县| 竹山县| 湟源县| 平罗县| 抚松县| 五台县| 元朗区| 灯塔市| 禹城市| 南开区| 凌源市| 墨江| 师宗县| 荔波县| 汶川县| 天台县| 涟水县| 南投市| 绿春县| 平潭县| 时尚|