自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

這六個Spring高級開發(fā)技巧掌握了嗎?

開發(fā) 前端
如果在SpringWeb項目中,類型轉(zhuǎn)換功能通常是由框架內(nèi)部自動處理的,尤其是在Spring MVC的Controller層,當(dāng)請求參數(shù)需要綁定到方法的參數(shù)時。

環(huán)境:Spring5.3.33

1. Lifecycle接口

Lifecycle接口是一個定義啟動/停止生命周期控制方法的通用接口。它允許Bean對象和容器(通常是Spring的ApplicationContext本身)實現(xiàn)啟動和停止操作,接口定義:

public interface Lifecycle {
  // Spring容器啟動之前執(zhí)行
  void start();
  // Spring容器在要關(guān)閉時執(zhí)行
  void stop();
  // 判斷是否正在運行
  boolean isRunning();
}

注意,常規(guī)的org.springframework.context.Lifecycle接口是顯式啟動和停止通知的簡單約定,并不意味著在上下文刷新時自動啟動。為了細(xì)粒度地控制自動啟動和特定bean的優(yōu)雅停止(包括啟動和停止階段),你應(yīng)該實現(xiàn)org.springframework.context.SmartLifecycle接口。

如下示例:

public class PackLifecycle implements SmartLifecycle {
  private volatile boolean running ;
  @Override
  public void start() {
    this.running = true;
    System.out.println("lifecycle start ... ") ;
  }
  @Override
  public void stop() {
    this.running = false ;
    System.out.println("lifecycle stop ... ") ;
  }
  @Override
  public boolean isRunning() {
    return running ;
  }
}

start/stop執(zhí)行時機

start方法執(zhí)行

public abstract class AbstractApplicationContext {
  public void refresh() {
    // ...
    // 實例化單例bean
    finishBeanFactoryInitialization(beanFactory);
    // 完成上下文刷新操作最后一步執(zhí)行
    finishRefresh();
  }
  protected void finishRefresh() {
    // 通過LifecycleProcessor#onRefresh方法執(zhí)行Lifecycle#start方法
    getLifecycleProcessor().onRefresh();
  }
}

stop方法執(zhí)行

public abstract class AbstractApplicationContext {
  // 當(dāng)容器關(guān)閉時執(zhí)行
  public void close() {
    doClose();
  }
  protected void doClose() {
    // 通過LifecycleProcessor#onClose方法執(zhí)行Lifecycle#stop方法
    this.lifecycleProcessor.onClose();
  }
}

你可以通過自定義Lifecycle,在容器啟動完成時和容器關(guān)閉時做你需要的人和事。

2. FactoryBean接口

如果你想自定義完全控制bean的實例化,那么你可以通過實現(xiàn)FactoryBean接口。

FactoryBean<T>接口提供了三種方法:

  • T getObject():  返回此工廠創(chuàng)建的對象的實例。實例可能是共享的,這取決于此工廠返回的是單件還是原型。
  • boolean isSingleton():  如果此FactoryBean返回singletons,則返回true;否則返回false。此方法的默認(rèn)實現(xiàn)返回true。
  • Class<?> getObjectType(): 返回getObject()方法返回的對象類型,如果類型事先未知,則返回null。

如下示例:

public class User {}
@Component("user")
public class UserFactoryBean implements FactoryBean<User> {
  @Override
  public User getObject() throws Exception {
    // 自定義對象實例化
    User user = new User() ;
    return user ;
  }
  @Override
  public Class<?> getObjectType() {
    return User.class;
  }
}

雖然我們定義的是FactoryBean實例,但是我們使用的時候還是可以按照User類型注入使用即可,如下示例:

@Resource
private User user;

那如何獲取UserFactoryBean這個對象呢?我們可以通過如下方式:

try (GenericApplicationContext context = new GenericApplicationContext()) {
  // ...
  System.out.println(context.getBean("&user")) ;
}

在beanName之前添加'&'符合即可獲取真實的UserFactoryBean對象。

3. 非web環(huán)境優(yōu)雅關(guān)閉容器

如果在非web應(yīng)用程序環(huán)境中(例如,在富客戶端桌面環(huán)境中)使用Spring的IoC容器,請向JVM注冊關(guān)閉掛鉤。這樣做可以確保正常關(guān)閉,并在單例bean上調(diào)用相關(guān)的destroy方法,從而釋放所有資源。通過容器對象ConfigurableApplicationContext#registerShutdownHook()方法注冊關(guān)閉鉤子。

public class User implements DisposableBean {
  @Override
  public void destroy() throws Exception {
    System.out.println("User Object destroy...") ;
  }
}


public static void main(String[] args) {
  GenericApplicationContext context = new GenericApplicationContext() ;
  context.registerBean(User.class) ;
  // 該方法會啟動一個線程,該線程會關(guān)閉onClose方法;這樣bean相關(guān)的生命周期方法都能被調(diào)用
  context.registerShutdownHook() ;
  context.refresh() ; 
}
// 控制臺輸出;如果沒有調(diào)用registerShutdownHook則不會有任何輸出
User Object destroy...

注意:在SpringBoot環(huán)境下,上面的registerShutdownHook是自動調(diào)用。

4. 資源注入

我們可以直接通過@Value注解注入資源,如下示例:

@Value("${pack.images:file:///d:/images/1.png}")
private Resource res ;
// 將上面注入的資源,將圖片直接輸出到瀏覽器、
@GetMapping("/res0")
public void res0(HttpServletResponse response) throws Exception {
  response.setContentType("image/png") ;
  StreamUtils.copy(res.getInputStream(), response.getOutputStream()) ;
}

也可以注入資源數(shù)組;

@Component
public class PackResource {
  private final Resource[] templates ;
  public PackResource(@Value("${pack.templates.path}") Resource[] templates) {
    this.templates = templates;
  }
}

資源路徑配置;

pack:
  templates:
    path: classpath*:com/pack/templates/*.ftl

ResourceLoaderAware接口

ResourceLoaderAware接口是一個特殊的回調(diào)接口,用于標(biāo)識期望為其提供ResourceLoader引用的組件,如下示例:

@Component
public class PackResourceLoader implements ResourceLoaderAware {


  @Override
  public void setResourceLoader(ResourceLoader resourceLoader) {
    Resource resource = resourceLoader.getResource("classpath:com/pack/templates/1.txt") ;
    System.out.println(StreamUtils.copyToString(resource.getInputStream(), StandardCharsets.UTF_8)) ;
  }
}

注意:由于ApplicationContext是ResourceLoader,因此bean還可以實現(xiàn)ApplicationContextAware接口,并直接使用提供的應(yīng)用程序上下文來加載資源。但是,一般來說,如果你只需要專用的ResourceLoader接口,那么最好使用該接口。代碼將只耦合到資源加載接口(可以被視為實用程序接口),而不耦合到整個Spring ApplicationContext接口。

5. 參數(shù)驗證

參數(shù)驗證一般都只是用在Controller請求方法上,如下示例:

@PostMapping("")
public Object save(@Validated @RequestBody User user, BindingResult errors) {
  // TODO
}

在SpringBoot環(huán)境下(SpringBoot當(dāng)你引入了validation模塊后,會自動配置Validator),你可以在任意管理的Bean中使用參數(shù)驗證功能,如下示例:

private final Validator validator ;
public UserService(Validator validator) {
  this.validator = validator ;
}
public void save(User user) {
  Errors errors = ...
  this.validator.validate(user, errors) ;
  if (errors.hasErrors()) {
    // TODO
  }
}

如果你不在SpringBoot環(huán)境下,那么你可以手動注冊Validator

@Bean
public LocalValidatorFactoryBean validator() {
  return new LocalValidatorFactoryBean() ;
}

有關(guān)參數(shù)驗證的其它更加全面的知識,請查看下面這篇文章:

必讀!SpringBoot接口參數(shù)校驗N種實用技巧大揭秘

SpringBoot參數(shù)驗證@Validated和@Valid分清楚了嗎?這些驗證細(xì)節(jié)你知道嗎?

6. 類型轉(zhuǎn)換

如果在SpringWeb項目中,類型轉(zhuǎn)換功能通常是由框架內(nèi)部自動處理的,尤其是在Spring MVC的Controller層,當(dāng)請求參數(shù)需要綁定到方法的參數(shù)時。然而,在應(yīng)用程序的其他部分,比如Service層或其他組件中,有時我們確實需要手動執(zhí)行類型轉(zhuǎn)換。在這些情況下,我們可以利用Spring提供的ConversionService接口來完成數(shù)據(jù)類型之間的轉(zhuǎn)換。

在Spring Boot環(huán)境下,系統(tǒng)自動為我們配置了ConversionService可以被注入到任何Bean對象中,以便我們在需要的時候使用它。如下示例:

private final ConversionService conversionService ;
public PackComponent(ConversionService conversionService) {
  this.conversionService = conversionService ;
}
public Object convert(Object source, Class<?> targetType) {  
  // 檢查源對象和目標(biāo)類型是否為null  
  if (source == null || targetType == null) {  
    throw new IllegalArgumentException("Source or target type cannot be null");  
  }  
  // 嘗試進(jìn)行類型轉(zhuǎn)換  
  return conversionService.convert(source, targetType) ;  
}

非常方便的進(jìn)行類型轉(zhuǎn)換。

責(zé)任編輯:武曉燕 來源: Spring全家桶實戰(zhàn)案例源碼
相關(guān)推薦

2025-02-28 13:00:00

JavaScrip開發(fā)語言

2025-04-08 09:10:00

PillowPython圖像處理

2024-03-12 12:27:00

Vue 3前端開發(fā)

2023-09-24 13:55:42

Spring應(yīng)用程序

2021-08-23 11:35:00

工具yyds開源

2025-01-07 08:21:03

2022-04-29 17:03:37

WordPress開發(fā)者網(wǎng)站安全

2018-05-20 16:17:50

物聯(lián)網(wǎng)互聯(lián)產(chǎn)品成熟度模型

2024-09-20 15:37:02

2024-03-06 10:50:30

云計算云實例云提供商

2016-12-15 09:53:07

自學(xué)編程技巧

2021-09-03 09:57:13

開源技術(shù) 項目

2024-01-30 08:43:26

IF 語句JavaScripJS

2021-11-16 11:30:10

Linux命令運維

2016-01-04 15:20:46

2016趨勢互聯(lián)網(wǎng)

2021-10-09 10:00:52

遠(yuǎn)程招聘技巧招聘

2022-09-06 08:07:24

SQL語句查詢

2023-02-08 17:00:07

IF 語句技巧代碼

2023-10-10 18:24:46

PostgreSQL性能RDBMS

2015-07-30 14:43:04

導(dǎo)航欄iOS開發(fā)
點贊
收藏

51CTO技術(shù)棧公眾號