这篇文章主要介绍了如何写好一个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 {}

代码示例

DemoBean

@Slf4j
public class DemoBean implements InitializingBean {public DemoBean() {log.info("--> instantiate ");}@PostConstructpublic void postConstruct() {log.info("--> @PostConstruct ");}@Overridepublic void afterPropertiesSet() throws Exception {log.info("--> InitializingBean.afterPropertiesSet ");}public void initMethod() {log.info("--> custom initMehotd");}
} 

DemoBeanPostProcessor

@Configuration
public class DemoBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if ("demoBean".equals(beanName)){log.info("--> BeanPostProcessor.postProcessBeforeInitialization ");}return bean;}@Overridepublic 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.postProcessBeforeInitializationObject wrappedBean = wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);...// 执行用户自定义初始化and JSR 250 定义的方法invokeInitMethods(beanName, wrappedBean, mbd);...// 执行执行BeanPostProcessor.postProcessAfterInitializationwrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);return wrappedBean;
} 

下文就详细说明一下每个 bean 的扩展周期的最佳使用场景BeanPostProcessor

BeanPostProcessor 是一个可以自定义实现回调方法接口,来实现自己的实例化逻辑、依赖解决逻辑等,如果想要在 Spring 完成对象实例化、配置、初始化之后实现自己的业务逻辑,可以通过扩展实现一个或多个 BeanPostProcessor 处理。

多用于适配器模式,可以在实现同一接口 bean 创建前后进行包装转换

// seata 上下文转换,将其他类型 wrap 成 SeataFeignContext
public class SeataContextBeanPostProcessor implements BeanPostProcessor {@Overridepublic 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/subpublic class RStreamListenerDetector implements BeanPostProcessor {@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {Class<?> 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

InitializingBean 接口方法会在 容器初始化(getter/setter/构造器)完成 bean 的属性注入后执行。

应用场景: 动态修改容器注入的 Bean 参数

正常用户配置参数注入到 bean

security:oauth2:ignore-urls:- '/ws/**'@ConfigurationProperties(prefix = "security.oauth2")
public class PermitAllUrlProperties {@Getter@Setterprivate List<String> ignoreUrls = new ArrayList<>();
} 

initMethod

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

@Bean(initMethod = "initMethod")
public DemoBean demoBean() {return new DemoBean();
}public void initMethod() {log.info("--> custom initMehotd");
} 

总结

如何写好一个Spring组件的实现步骤的实现步骤的文章就介绍到这了!

@bean 什么时候执行_写好一个Spring组件的实现步骤是什么?相关推荐

  1. 依赖 netty spring_面试官:如何写好一个 Spring 组件?懵圈!

    背景 Spring 框架提供了许多接口,可以使用这些接口来定制化 bean ,而非简单的 getter/setter 或者构造器注入.细翻 Spring Cloud Netflix.Spring Cl ...

  2. python函数的组成要素_写好一个Python函数的六要素

    Python 虽然好用,但用好真的很难.尤其是函数部分,只要写不好,后面的一连串人都会遭殃.看又看不懂,测试起来也麻烦,维护又维护不动,真是让人头疼. 那怎么写好一个 Python 函数呢?<W ...

  3. pythonjava app切出后无网络连接_写了一个java的Server 用python的client访问却访问不通问题。...

    首先给出这个java的Server代码 try{//1.创建一个服务器端Socket,即ServerSocket,指定绑定的端口,并监听此端口 ServerSocket serverSocket=ne ...

  4. 真香!如何用300行代码写完一个Spring基本框架?

    Spring是一个非侵入性(non-invasive)框架,其目标是使应用程序代码对框架的依赖最小化,应用代码可以在没有Spring或者其他容器的情况下运行. 看spring的源码,学习spring, ...

  5. 如何写出一个confirm组件

    前言 一直都想写一个组件库,作为一个前端的我一直都有这么一个梦想,在写项目的过程中一直都在引用别人的组件库长久而言自己也开始想写一个组件库.什么是组件呢?这里不再过的赘述,下面我们先谈一谈confir ...

  6. python 基金量化分析_写了一个基金投资管理分析的 python 工具箱

    0 赞同来自: 发车了? 2020-03-15 09:26 0 条评论 0 赞同来自: 支持下 2020-03-15 09:27 0 条评论 0 赞同来自: 场内etf有么老铁,多谢了 2020-03 ...

  7. C++开发环境搭建_需要学习的内容介绍_写第一个C++程序---C++语言工作笔记008

    C语言现在在语言排行榜,以及python语言在语言排行榜越来越靠前,然后 java的使用,变的少了,所以有必要,把C语言系统的来上一遍. C是做嵌入式的基础,python是做人工智能,算法的基础都要掌 ...

  8. @bean 什么时候执行_离婚冷静期什么时候开始执行?

    十三届全国人大三次会议5月28日下午3时举行闭幕会,会议表决通过了<中华人民共和国民法典>.在民法典法条中,设置离婚冷静期成为社会广泛关注的问题.<民法典>在婚姻家庭编中设立了 ...

  9. python等待执行完毕 再继续执行_如何等待一个函数内部异步执行完毕再执行另外一个函数?...

    问题描述 有两个函数f1和f2,其中f1中有异步操作,执行完f1接着执行f2,因为f1内部有异步操作,所以会先执行完f2,再执行f1里的异步,如何等待f1异步执行完再执行f2. 备注:执行方式为f1( ...

最新文章

  1. 论机智,还是国产安卓旗舰花样多,从2999到10999元,各有各的“开窍点”
  2. 企业网站做SEO优化必走的三条路线,希望新人前方不要右转
  3. python有道词典-Python爬取有道词典
  4. android 获取其他布局,android listview onItemClick中获取其他item的布局
  5. 4.Spring Cloud Alibaba教程:Nacos配置管理
  6. c语言联合验证大小端存储,2021C语言面试题及答案.docx
  7. 莫烦Tensorflow教程(15~22)
  8. 会话标识未更新 java_Appscan漏洞之会话标识未更新
  9. java excel_java生成excel并下载功能
  10. 滚屏加载--无刷新动态加载数据技术的应用
  11. gradle对java插件的扩展_Gradle之java插件入门
  12. MySQL之父Michael Wideneus:有自己的电脑,我可以做任何事情
  13. python报数组越界_【问题汇总】列表数组越界的问题
  14. 北大青鸟软件工程师 ACCP6.0课程体系
  15. h5文件格式数据集制作
  16. 设置Excel表格“只读模式”的两种方法
  17. Windows自带录屏
  18. 【Python教程】python之路
  19. 区域经济发展的扬州创新:融合工业化与信息化
  20. 个人用户拨号上网除了具备计算机,计算机和网络基的础知识总复习资料第一部分网络.doc...

热门文章

  1. JavaScript的格式
  2. 我如何进行简历的筛选与人员的选择
  3. C#: Writing a CookieContainer to Disk and Loading Back In For Use
  4. ubuntu10.10升级到11.4出错之问题解决
  5. 使用Acronis Disk Director Suite调整分区大小
  6. shell if判断语句
  7. 1、maven笔记(一):构建项目
  8. systemtap原理及使用
  9. 【python】Python的基本数据类型之运算符
  10. 接口测试-使用mock生产随机数据