.markdown-body { line-height: 1.75; font-weight: 400; font-size: 16px; overflow-x: hidden; color: rgba(37, 41, 51, 1) }
.markdown-body h1, .markdown-body h2, .markdown-body h3, .markdown-body h4, .markdown-body h5, .markdown-body h6 { line-height: 1.5; margin-top: 35px; margin-bottom: 10px; padding-bottom: 5px }
.markdown-body h1 { font-size: 24px; line-height: 38px; margin-bottom: 5px }
.markdown-body h2 { font-size: 22px; line-height: 34px; padding-bottom: 12px; border-bottom: 1px solid rgba(236, 236, 236, 1) }
.markdown-body h3 { font-size: 20px; line-height: 28px }
.markdown-body h4 { font-size: 18px; line-height: 26px }
.markdown-body h5 { font-size: 17px; line-height: 24px }
.markdown-body h6 { font-size: 16px; line-height: 24px }
.markdown-body p { line-height: inherit; margin-top: 22px; margin-bottom: 22px }
.markdown-body img { max-width: 100% }
.markdown-body hr { border-top: 1px solid rgba(221, 221, 221, 1); border-right: none; border-bottom: none; border-left: none; margin-top: 32px; margin-bottom: 32px }
.markdown-body code { border-radius: 2px; overflow-x: auto; background-color: rgba(255, 245, 245, 1); color: rgba(255, 80, 44, 1); font-size: 0.87em; padding: 0.065em 0.4em }
.markdown-body code, .markdown-body pre { font-family: Menlo, Monaco, Consolas, Courier New, monospace }
.markdown-body pre { overflow: auto; position: relative; line-height: 1.75 }
.markdown-body pre>code { font-size: 12px; padding: 15px 12px; margin: 0; word-break: normal; display: block; overflow-x: auto; color: rgba(51, 51, 51, 1); background: rgba(248, 248, 248, 1) }
.markdown-body a { text-decoration: none; color: rgba(2, 105, 200, 1); border-bottom: 1px solid rgba(209, 233, 255, 1) }
.markdown-body a:active, .markdown-body a:hover { color: rgba(39, 91, 140, 1) }
.markdown-body table { display: inline-block !important; font-size: 12px; width: auto; max-width: 100%; overflow: auto; border: 1px solid rgba(246, 246, 246, 1) }
.markdown-body thead { background: rgba(246, 246, 246, 1); color: rgba(0, 0, 0, 1); text-align: left }
.markdown-body tr:nth-child(2n) { background-color: rgba(252, 252, 252, 1) }
.markdown-body td, .markdown-body th { padding: 12px 7px; line-height: 24px }
.markdown-body td { min-width: 120px }
.markdown-body blockquote { color: rgba(102, 102, 102, 1); padding: 1px 23px; margin: 22px 0; border-left: 4px solid rgba(203, 203, 203, 1); background-color: rgba(248, 248, 248, 1) }
.markdown-body blockquote:after { display: block; content: "" }
.markdown-body blockquote>p { margin: 10px 0 }
.markdown-body ol, .markdown-body ul { padding-left: 28px }
.markdown-body ol li, .markdown-body ul li { margin-bottom: 0; list-style: inherit }
.markdown-body ol li .task-list-item, .markdown-body ul li .task-list-item { list-style: none }
.markdown-body ol li .task-list-item ol, .markdown-body ol li .task-list-item ul, .markdown-body ul li .task-list-item ol, .markdown-body ul li .task-list-item ul { margin-top: 0 }
.markdown-body ol ol, .markdown-body ol ul, .markdown-body ul ol, .markdown-body ul ul { margin-top: 3px }
.markdown-body ol li { padding-left: 6px }
.markdown-body .contains-task-list { padding-left: 0 }
.markdown-body .task-list-item { list-style: none }
@media (max-width: 720px) { .markdown-body h1 { font-size: 24px } .markdown-body h2 { font-size: 20px } .markdown-body h3 { font-size: 18px } }.markdown-body pre, .markdown-body pre>code.hljs { color: rgba(51, 51, 51, 1); background: rgba(248, 248, 248, 1) }
.hljs-comment, .hljs-quote { color: rgba(153, 153, 136, 1); font-style: italic }
.hljs-keyword, .hljs-selector-tag, .hljs-subst { color: rgba(51, 51, 51, 1); font-weight: 700 }
.hljs-literal, .hljs-number, .hljs-tag .hljs-attr, .hljs-template-variable, .hljs-variable { color: rgba(0, 128, 128, 1) }
.hljs-doctag, .hljs-string { color: rgba(221, 17, 68, 1) }
.hljs-section, .hljs-selector-id, .hljs-title { color: rgba(153, 0, 0, 1); font-weight: 700 }
.hljs-subst { font-weight: 400 }
.hljs-class .hljs-title, .hljs-type { color: rgba(68, 85, 136, 1); font-weight: 700 }
.hljs-attribute, .hljs-name, .hljs-tag { color: rgba(0, 0, 128, 1); font-weight: 400 }
.hljs-link, .hljs-regexp { color: rgba(0, 153, 38, 1) }
.hljs-bullet, .hljs-symbol { color: rgba(153, 0, 115, 1) }
.hljs-built_in, .hljs-builtin-name { color: rgba(0, 134, 179, 1) }
.hljs-meta { color: rgba(153, 153, 153, 1); font-weight: 700 }
.hljs-deletion { background: rgba(255, 221, 221, 1) }
.hljs-addition { background: rgba(221, 255, 221, 1) }
.hljs-emphasis { font-style: italic }
.hljs-strong { font-weight: 700 }

简介

该接口目前有两个方法:

  • postProcessBeforeInitialization 该在初始化方法之前调用。
  • postProcessAfterInitialization 该方法再初始化方法之后调用。
public interface BeanPostProcessor {
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
} @Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}

用途示例

Spring aop注入切面-BeanNameAutoProxyCreator

在目标bean初始化完成之后,包装之后返回一个代理对象,注入相关的切面逻辑。

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
} // Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//对原来的bean进行代理
Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
//返回代理对象
return proxy;
} this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}

监控 Bean 初始化耗时, 常用来排查Spring启动慢分析流程中,排查是否Bean初始化所致

@Service
@Slf4j
public class BeanInitMetrics implements BeanPostProcessor { private final Map<String, Long> stats = new HashMap<>(); private final List<Metric> metrics = new ArrayList<>(); @Data
public static class Metric{ public Metric() {
} public Metric(String name, Integer value) {
this.name = name;
this.value = value;
this.createDate = new Date();
} private String name; //bean名称打印 private Integer value; //bean耗时,单位为毫秒 private Date createDate; //bean耗时的创建时间
} //重写初始化接口
@Override
public Object postProcessBeforeInitialization(@NotNull Object bean, @NotNull String beanName) throws BeansException {
stats.put(beanName, System.currentTimeMillis());
return bean;
} //后处理后初始化
@Override
public Object postProcessAfterInitialization(@NotNull Object bean, @NotNull String beanName) throws BeansException {
Long start = stats.get(beanName);
if (start != null) {
metrics.add(new Metric(beanName, Math.toIntExact(System.currentTimeMillis() - start)));
}
return bean;
} //通过后处理后初始化 - 初始化的时间算出bean耗时
public List<Metric> getMetrics() {
metrics.sort((o1, o2) -> {
try {
return o2.getValue() - o1.getValue();
}catch (Exception e){
return 0;
}
});
log.info("metrics {}", JSON.toJSONString(metrics));
return UnmodifiableList.unmodifiableList(metrics); //只读的集合
} }

更多信息请移步Spring专栏:www.yuque.com/mrhuang-ire…

参考:
[1].zhuanlan.zhihu.com/p/617821971
[2].blog.csdn.net/weixin_4393…

Spring扩展接口-BeanPostProcessor的更多相关文章

  1. spring源码分析系列 (2) spring拓展接口BeanPostProcessor

    Spring更多分析--spring源码分析系列 主要分析内容: 一.BeanPostProcessor简述与demo示例 二.BeanPostProcessor源码分析:注册时机和触发点 (源码基于 ...

  2. spring源码分析系列 (3) spring拓展接口InstantiationAwareBeanPostProcessor

    更多文章点击--spring源码分析系列 主要分析内容: 一.InstantiationAwareBeanPostProcessor简述与demo示例 二.InstantiationAwareBean ...

  3. Spring8:一些常用的Spring Bean扩展接口

    前言 Spring是一款非常强大的框架,可以说是几乎所有的企业级Java项目使用了Spring,而Bean又是Spring框架的核心. Spring框架运用了非常多的设计模式,从整体上看,它的设计严格 ...

  4. 0001 - Spring 框架和 Tomcat 容器扩展接口揭秘

    前言 在 Spring 框架中,每个应用程序上下文(ApplicationContext)管理着一个 BeanFactory,BeanFactory 主要负责 Bean 定义的保存.Bean 的创建. ...

  5. 深入理解Spring系列之八:常用的扩展接口

    转载 https://mp.weixin.qq.com/s/XfhZltSlTall8wKwV_7fKg Spring不仅提供了一个进行快速开发的基础框架,而且还提供了很多可扩展的接口,用于满足一些额 ...

  6. spring初始化源码浅析之关键类和扩展接口

    目录 1.关键接口和类 1.1.关键类之 DefaultListableBeanFactory 1.2.关键类之XmlBeanDefinitionReader 1.3.关键类之ClassPathXml ...

  7. Spring拓展接口之BeanPostProcessor,我们来看看它的底层实现

    前言 开心一刻 小明:“妈,我被公司开除了”,妈:“啊,为什么呀?”, 小明:“我骂董事长是笨蛋,公司召开高层会议还要起诉我”,妈:“告你诽谤是吧?”,小明:“不是,他们说要告我泄露公司机密” Bea ...

  8. 谈谈Spring中的BeanPostProcessor接口

    一.前言   这几天正在复习Spring的相关内容,在了解bean的生命周期的时候,发现其中涉及到一个特殊的接口--BeanPostProcessor接口.由于网上没有找到比较好的博客,所有最后花了好 ...

  9. Spring扩展之五:Aware接口等

    ApplicationContextAwareProcessor 1.介绍 ApplicationContextAwareProcessor是一个Spring内部工具,它实现了接口BeanPostPr ...

  10. spring扩展点整理

    本文转载自spring扩展点整理 背景 Spring的强大和灵活性不用再强调了.而灵活性就是通过一系列的扩展点来实现的,这些扩展点给应用程序提供了参与Spring容器创建的过程,好多定制化的东西都需要 ...

随机推荐

  1. gorm事务的rollback和commit操作

    一个事务内同一操作二次回滚(Rollback)会报错,二次提交(commit)也会报错, 如果回滚完又进行提交操作,一样会报错 循环注意把事务开启tx.Begin放在事务操作前边,操作完回滚或者提交

  2. Qt ButtonRole参数的作用

    文章目录 QMessgageBox中addButton(QAbstructButton* , ButtonRole),ButtonRole的作用 QMessgageBox中addButton(QAbs ...

  3. Flask快速入门1

    因为新换了一个工作,项目使用了Flask框架技术,需要快速学习下,学过Django这个重量级的框架基础后,再去学习Flask框架相对还是容易的. 当然入门基础容易,要深入理解还是要慢慢花时间深耕练习使 ...

  4. C#/.NET/.NET Core技术前沿周刊 | 第 31 期(2025年3.17-3.23)

    前言 C#/.NET/.NET Core技术前沿周刊,你的每周技术指南针!记录.追踪C#/.NET/.NET Core领域.生态的每周最新.最实用.最有价值的技术文章.社区动态.优质项目和学习资源等. ...

  5. Ubuntu安装mosquitto并进行配置

    要在Ubuntu上安装Mosquitto并进行配置,你可以按照以下步骤进行操作: 打开终端. 更新软件包列表,使用以下命令: sudo apt update 安装Mosquitto包,使用以下命令: ...

  6. Cannot find one or more components.

    场景重现 有那么一天重启了下电脑, 打开 Microsoft SQL Server Management Studio 2016, 没有出现腻歪的用户界面, 反而出现如下异常: 错误原因 谁造呢? 有 ...

  7. CPU 和GPUskinning对比

    CPU: 比如广泛的设备兼容性,比如上面说的精确逻辑处理,比如可以根据距离对Skinning进行LOD(如近距离角色每秒30帧Skinning,远距离角色每秒15帧Skinning),比如多Pass渲 ...

  8. Nim 语言新的性能测试

    今天将 性能测试网站: benchmarks game 上一个关于 n-body 的题目改成 nim 1.6.4 语言来编写. 注意,我是基于 java 的版本来写的,没有像  c++ 那样的版本使用 ...

  9. Linux限制可通过SSH登录到服务器的IP——hosts.allow

    Linux服务器针对固定的IP进行禁止.允许登录 linux 服务器通过设置/etc/hosts.allow和/etc/hosts.deny这个两个文件进行限制. 优先级:hosts.allow大于h ...

  10. Java 线程的常用操作方法

    目录 线程命名和取得 线程的休眠 线程优先级(priority) 线程命名和取得 如果想要进行线程名称的操作,可以使用Thread类的如下方法: 构造方法:public Thread(Runnable ...