91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

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

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

Spring組件的實現步驟

發布時間:2020-07-18 09:54:33 來源:億速云 閱讀:151 作者:小豬 欄目:編程語言

這篇文章主要講解了Spring組件的實現步驟,內容清晰明了,對此有興趣的小伙伴可以學習一下,相信大家閱讀完之后會有幫助。

本文詳細的介紹了Spring組件的實現步驟,分享給大家,具體如下:

Spring組件的實現步驟

背景

Spring 框架提供了許多接口,可以使用這些接口來定制化 bean ,而非簡單的 getter/setter 或者構造器注入。細翻 Spring Cloud Netflix、Spring Cloud Alibaba 等這些構建在 Spring Framework 的成熟框架源碼,你會發現大量的擴展 bean 例如

Eureka 健康檢查

package org.springframework.cloud.netflix.eureka;

public class EurekaHealthCheckHandler implements InitializingBean {}

Seata Feign 配置

package com.alibaba.cloud.seata.feign;

public class SeataContextBeanPostProcessor implements BeanPostProcessor {}

代碼示例

Spring組件的實現步驟

DemoBean

@Slf4j
public class DemoBean implements InitializingBean {

 public DemoBean() {
  log.info("--> instantiate ");
 }

 @PostConstruct
 public void postConstruct() {
  log.info("--> @PostConstruct ");
 }

 @Override
 public void afterPropertiesSet() throws Exception {
  log.info("--> InitializingBean.afterPropertiesSet ");
 }

 public void initMethod() {
  log.info("--> custom initMehotd");
 }
}

DemoBeanPostProcessor

@Configuration
public class DemoBeanPostProcessor implements BeanPostProcessor {
 @Override
 public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
  if ("demoBean".equals(beanName)){
   log.info("--> BeanPostProcessor.postProcessBeforeInitialization ");
  }
  return bean;
 }

 @Override
 public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  if ("demoBean".equals(beanName)){
   log.info("--> BeanPostProcessor.postProcessAfterInitialization ");
  }
  return bean;
 }
}

DemoConfig

@Configuration
public class DemoConfig {

 @Bean(initMethod = "initMethod")
 public DemoBean demoBean() {
  return new DemoBean();
 }
}

運行輸出日志

整個 bean 的創建過程日志輸出如下和文首圖片橫線以上 bean 創建周期一致

DemoBean : --> instantiate
DemoBeanPostProcessor: --> BeanPostProcessor.postProcessBeforeInitialization
DemoBean : --> @PostConstruct
DemoBean : --> InitializingBean.afterPropertiesSet
DemoBean : --> custom initMehotd
DemoBeanPostProcessor: --> BeanPostProcessor.postProcessAfterInitialization

執行過程核心源碼

AbstractAutowireCapableBeanFactory.initializeBean

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {

 // 執行BeanPostProcessor.postProcessBeforeInitialization
 Object wrappedBean = wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
  ...
  // 執行用戶自定義初始化and JSR 250 定義的方法
 invokeInitMethods(beanName, wrappedBean, mbd);
  ...
 // 執行執行BeanPostProcessor.postProcessAfterInitialization
 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

 return wrappedBean;
}

下文就詳細說明一下每個 bean 的擴展周期的最佳使用場景BeanPostProcessor

Spring組件的實現步驟

BeanPostProcessor 是一個可以自定義實現回調方法接口,來實現自己的實例化邏輯、依賴解決邏輯等,如果想要在 Spring 完成對象實例化、配置、初始化之后實現自己的業務邏輯,可以通過擴展實現一個或多個 BeanPostProcessor 處理。

多用于適配器模式,可以在實現同一接口 bean 創建前后進行包裝轉換

// seata 上下文轉換,將其他類型 wrap 成 SeataFeignContext
public class SeataContextBeanPostProcessor implements BeanPostProcessor {

 @Override
 public Object postProcessBeforeInitialization(Object bean, String beanName){
  if (bean instanceof FeignContext && !(bean instanceof SeataFeignContext)) {
   return new SeataFeignContext(getSeataFeignObjectWrapper(),
     (FeignContext) bean);
  }
  return bean;
 }
}

自定義 注解查找擴展

net.dreamlu.mica.redisson.stream.RStreamListenerDetector 查找自定義 @RStreamListener 實現 基于 Redisson 的 pub/sub

public class RStreamListenerDetector implements BeanPostProcessor {

 @Override
 public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  Class<&#63;> userClass = ClassUtils.getUserClass(bean);
  ReflectionUtils.doWithMethods(userClass, method -> {
   RStreamListener listener = AnnotationUtils.findAnnotation(method, RStreamListener.class);
   .... do something
  }, ReflectionUtils.USER_DECLARED_METHODS);
  return bean;
 }
}

PostConstruct

JavaEE5 引入了@PostConstruct 作用于 Servlet 生命周期的注解,實現 Bean 初始化之前的自定義操作。

  • 只能有一個非靜態方法使用此注解
  • 被注解的方法不能有返回值和方法參數
  • 被注解的方法不得拋出異常

這里需要注意的 這個注解不是 Spring 定義的,而是屬于 JavaEE JSR-250 規范定義的注解,當你在使用 Java11 的時候要手動引入相關 jar(因為 Java11 移除了)

<dependency>
 <groupId>javax.annotation</groupId>
 <artifactId>javax.annotation-api</artifactId>
</dependency>

使用場景: 在之前的版本,我們可以在啟動后通過 @PostConstruct 注解的方法執行初始化數據。但由于 Java 高版本已經移除相關 API ,我們不推薦使用此 注解,可以通過 Spring 相關 Event 回調事件處理

@PostConstruct 注解的方法在項目啟動的時候執行這個方法,也可以理解為在 spring 容器啟動的時候執行,可作為一些數據的常規化加載,比如數據字典之類的。

InitializingBean

Spring組件的實現步驟

InitializingBean 接口方法會在 容器初始化(getter/setter/構造器)完成 bean 的屬性注入后執行。

應用場景: 動態修改容器注入的 Bean 參數

正常用戶配置參數注入到 bean

security:
 oauth3:
  ignore-urls:
  - '/ws/**'

@ConfigurationProperties(prefix = "security.oauth3")
public class PermitAllUrlProperties {
 @Getter
 @Setter
 private List<String> ignoreUrls = new ArrayList<>();
}

我們發現此時用戶配置并不完整,還有一些通用不需要用戶維護,可通過實現 InitializingBean 接口回調擴展

@ConfigurationProperties(prefix = "security.oauth3.ignore")
public class PermitAllUrlProperties implements InitializingBean {

 @Getter
 @Setter
 private List<String> urls = new ArrayList<>();

 @Override
 public void afterPropertiesSet() {
  urls.add("/common/*");
 }
}

initMethod

上文 @PostConstruct 已經不推薦大家使用,可以使用 Bean(initMethod = 'initMehotd') 替代,相關的限制如上。

@Bean(initMethod = "initMethod")
public DemoBean demoBean() {
 return new DemoBean();
}

public void initMethod() {
 log.info("--> custom initMehotd");
}

看完上述內容,是不是對Spring組件的實現步驟有進一步的了解,如果還想學習更多內容,歡迎關注億速云行業資訊頻道。

向AI問一下細節

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

AI

兴隆县| 新余市| 大丰市| 宜城市| 策勒县| 贡嘎县| 烟台市| 正镶白旗| 罗甸县| 新昌县| 邯郸市| 安宁市| 万全县| 开阳县| 略阳县| 广灵县| 临海市| 金坛市| 吉水县| 宿松县| 阜阳市| 潞城市| 岐山县| 铜川市| 泗水县| 灵璧县| 延长县| 武冈市| 嫩江县| 色达县| 上犹县| 灵台县| 孝昌县| 沙河市| 汉寿县| 绥化市| 米易县| 清原| 宁化县| 徐水县| 上杭县|