原文网址:Spring--BeanPostProcessor--注意/问题/坑--SpringBoot_IT利刃出鞘的博客-CSDN博客

简介

本文用实例来介绍Spring的后置处理器(BeanPostProcessor)的一些坑,开发时要注意这些问题。

坑1:依赖的bean不走BeanPostProcessor

简介

在BeanPostProcessor的实现类中,依赖了其他的bean,那么被依赖的bean被创建时,将不会执行它所在的BeanPostProcessor实现类实现的方法。

因为由于BeanPostProcessor的实现类依赖于其他bean,所以这个bean需要在PostBean之前创建完成,这也就意味着在这个bean创建时,BeanPostProcessor的实现类还未初始化完成,所以不会调用它的方法。

以下用实例进行验证

BeanPostProcessor实现类

package com.example.processor;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;@Component
public class MyProcessor implements BeanPostProcessor {@Autowiredprivate MyBean myBean;@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if (bean instanceof MyBean) {System.out.println("postProcessBeforeInitialization==> " + "This is MyBean");}return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (bean instanceof MyBean) {System.out.println("postProcessAfterInitialization==> " + "This is MyBean");}return bean;}
}

被依赖的Bean

package com.example.processor;import org.springframework.stereotype.Component;@Component
public class MyBean {
}

测试

启动后,没有相关打印。

若将@Autowired  MyBean myBean删掉,则启动之后,会打印出:

  .   ____          _            __ _ _/\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \\\/  ___)| |_)| | | | | || (_| |  ) ) ) )'  |____| .__|_| |_|_| |_\__, | / / / /=========|_|==============|___/=/_/_/_/:: Spring Boot ::        (v2.3.0.RELEASE)2021-03-05 21:39:47.861  INFO 16100 --- [           main] com.example.DemoApplication              : Starting DemoApplication on DESKTOP-QI6B9ME with PID 16100 (E:\work\Idea_proj\demo_JAVA\demo_SpringBoot\target\classes started by Liu in E:\work\Idea_proj\demo_JAVA\demo_SpringBoot)
2021-03-05 21:39:47.864  INFO 16100 --- [           main] com.example.DemoApplication              : No active profile set, falling back to default profiles: default
2021-03-05 21:39:48.645  INFO 16100 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2021-03-05 21:39:48.652  INFO 16100 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2021-03-05 21:39:48.652  INFO 16100 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.35]
2021-03-05 21:39:48.730  INFO 16100 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2021-03-05 21:39:48.731  INFO 16100 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 825 ms
postProcessBeforeInitialization==> This is MyBean
postProcessAfterInitialization==> This is MyBean
2021-03-05 21:39:48.865  INFO 16100 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2021-03-05 21:39:48.998  INFO 16100 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2021-03-05 21:39:49.007  INFO 16100 --- [           main] com.example.DemoApplication              : Started DemoApplication in 1.557 seconds (JVM running for 2.638)

坑2:无法使用AOP

见:Spring--BeanPostProcessor无法使用AOP--原因/解决方案_IT利刃出鞘的博客-CSDN博客

坑3:注册方式及其限制

其他网址

谈谈Spring中的BeanPostProcessor接口 - 特务依昂 - 博客园

简介

如何将BeanPostProcessor注册到Spring容器中?方式主要有如下两种:

  1. 将其声明在Spring的配置类或xml文件中,作为普通的bean,让ApplicationContext对象去加载它,这样它就被自动注册到容器中了。而且Spring容器会对BeanPostProcessor的实现类做特殊处理,即会将它们挑选出来,在加载其他bean前,优先加载BeanPostProcessor的实现类。
  2. 使用ConfigurableBeanFactory接口的addBeanPostProcessor方法手动添加。ApplicationContext对象中组合了一个ConfigurableBeanFactory的实现类对象。但这样添加BeanPostProcessor有一些缺点,如下:
    1. 一创建Spring容器,配置文件中的单例bean就会被加载,此时addBeanPostProcessor方法还没执行,那手动添加的BeanPostProcessor就无法作用于这些bean,所以手动添加的BeanPostProcessor只能作用于延迟加载的bean,或者非单例bean。
    2. Ordered接口的作用将失效,而是以注册的顺序执行。前面提过,Ordered接口用来指定多个BeanPostProcessor实现的方法的执行顺序。这是Spring官方文档中提到的:While the recommended approach for BeanPostProcessor registration is through ApplicationContext auto-detection (as described above), it is also possible to register them programmatically against a ConfigurableBeanFactory using the addBeanPostProcessor method. This can be useful when needing to evaluate conditional logic before registration, or even for copying bean post processors across contexts in a hierarchy. Note however that BeanPostProcessor s added programmatically do not respect the Ordered interface. Here it is the order of registration that dictates the order of execution. Note also that BeanPostProcessor s registered programmatically are always processed before those registered through auto-detection, regardless of any explicit ordering.

坑4:使用@Bean配置的限制

简介

如果使用Java类的方式配置Spring,并使用@Bean声明一个工厂方法返回bean实例,那么返回值的类型必须是BeanPostProcessor类型,或者等级低于BeanPostProcessor的类型。

演示 

package com.example.processor;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;@Component
public class MyProcessor implements BeanPostProcessor, Ordered {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("postProcessBeforeInitialization==> " + beanName);return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("postProcessAfterInitialization==> " + beanName);return bean;}@Overridepublic int getOrder() {return Ordered.LOWEST_PRECEDENCE;}
}

在配置类中,声明MyProcessor可以有以下几种方式

@Configuration
public class BeanConfig {// 方式1:MyProcessor@Beanpublic MyProcessor myProcessor() {return new MyProcessor();}// 方式2:返回值为BeanPostProcessor@Beanpublic BeanPostProcessor myProcessor() {return new MyProcessor();}// 方式3:返回值为Ordered@Beanpublic Ordered postBean() {return new MyProcessor();}
}

以上三种方式都可以让Spring容器创建MyProcessor实例对象,因为MyProcessor实现了BeanPostProcessor和Ordered接口,所以它的对象也是这两种类型的对象。但是需要注意,上面三种方式中,只有第一种和第二种方式,会让Spring容器将MyProcessor当作BeanPostProcessor处理;而第三种方式,则会被当作一个普通Bean处理,实现BeanPostProcessor的两个方法都不会被调用。因为在MyProcessor的继承体系中,Ordered和BeanPostProcessor是同级别的,Spring无法识别出这个Ordered对象,也是一个BeanPostProcessor对象;但是使用MyProcessor却可以,因为MyProcessor类型就是BeanPostProcessor的子类型。所以,在使用@Bean声明工厂方法返回BeanPostProcessor实现类对象时,返回值必须是BeanPostProcessor类型,或者更低级的类型。Spring官方文档中,这一部分的内容如下:

Note that when declaring a BeanPostProcessor using an @Bean factory method on a configuration class, the return type of the factory method should be the implementation class itself or at least the org.springframework.beans.factory.config.BeanPostProcessor interface, clearly indicating the post-processor nature of that bean. Otherwise, the ApplicationContext won’t be able to autodetect it by type before fully creating it. Since a BeanPostProcessor needs to be instantiated early in order to apply to the initialization of other beans in the context, this early type detection is critical.

其他网址

谈谈Spring中的BeanPostProcessor接口 - 特务依昂 - 博客园

无法使用AOP

谈谈Spring中的BeanPostProcessor接口 - 特务依昂 - 博客
BeanPostProcessor中autowired导致AOP失效 | 大专栏

BeanPostProcessor启动时对依赖Bean的“误伤”陷阱(is not eligible for getting processed by all...)_YourBatman-CSDN博客
记一次Spring配置事故 - 飞昂之雪 - 博客园
业务类无法被AOP代理问题

坑4:使用@Bean配置的限制

谈谈Spring中的BeanPostProcessor接口 - 特务依昂 - 博客园

Spring--BeanPostProcessor--注意/问题/坑--SpringBoot相关推荐

  1. springboot 事务手动回滚_来,讲讲Spring事务有哪些坑?

    来自公众号:孤独烟 引言 今天,我们接上文<面试官:谈谈你对mysql事务的认识>的内容,来讲spring中和事务有关的考题! 因为事务这块,面试的出现几率很高.而大家工作中CRUD的比较 ...

  2. 宝贝,来,讲讲spring事务有哪些坑?

    引言 今天,我们接上文<面试官:谈谈你对mysql事务的认识>的内容,来讲spring中和事务有关的考题! 因为事务这块,面试的出现几率很高.而大家工作中CRUD的比较多,没有好好总结过这 ...

  3. jdbctemplate 开启事务_来,讲讲Spring事务有哪些坑?

    来自公众号:孤独烟 引言 今天,我们接上文<面试官:谈谈你对mysql事务的认识>的内容,来讲spring中和事务有关的考题! 因为事务这块,面试的出现几率很高.而大家工作中CRUD的比较 ...

  4. 面试官: 讲讲 Spring 事务有哪些坑?

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 引言 今天,我们来讲 Spring 中和事务有关的考题. ...

  5. Spring事务的那些坑,这里都给你总结好了!

    点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达 今日推荐:硬刚一周,3W字总结,一年的经验告诉你如何准备校招! 个人原创100W+访问量博客:点击前往,查看更多 作者:蚊 ...

  6. 从web.xml谈谈SpringMVC集成spring的初始化流程及SpringBoot集成SpringMVC

    一.关于servlet 详解servlet,https://www.runoob.com/servlet/servlet-tutorial.html 总览一下: servlet与servlet容器 J ...

  7. 快速创建springboot项目:使用http://start.spring.io/网页创建,使用IDEA的Spring Initializr创建,使用SpringBoot CLI创建

    1 快速创建SpringBoot项目 快速创建SpringBoot项目至少可以通过两种方式: 1.使用http://start.spring.io/网页版的创建 2.使用IDEA创建 1.1.通过访问 ...

  8. springboot+jsp中文乱码_【spring 国际化】springMVC、springboot国际化处理详解

    在web开发中我们常常会遇到国际化语言处理问题,那么如何来做到国际化呢? 你能get的知识点? 使用springgmvc与thymeleaf进行国际化处理. 使用springgmvc与jsp进行国际化 ...

  9. 启动Spring项目报错,Springboot启动报错 Disconnected from the target VM 解决过程

    启动Spring项目报错,Springboot启动报错 Disconnected from the target VM 解决过程 大概率是缺少了一下依赖 <dependency><g ...

  10. 最新Kafka教程(包含kafka部署与基本操作、java连接kafka、spring连接kafka以及使用springboot)

    最新Kafka教程(包含kafka部署与基本操作.java连接kafka.spring连接kafka以及使用springboot) 欢迎转载,转载请注明网址:https://blog.csdn.net ...

最新文章

  1. [转]kaldi中的特征提取
  2. Fragment 的生命周期
  3. 领域驱动设计(2)怎么使用沟通
  4. 2018年计算机CPU纳米制程,AMD发大招,推出7纳米制程CPU与GPU
  5. java作业不能运行_从Windows运行时,YARN作业失败
  6. kettle基础使用教程
  7. 网友热爱的截图软件--Sinpaste
  8. 定罪了!“女版乔布斯”有可能入狱20年
  9. ORACLE 11G使用exp或者pl/sql导出空表
  10. 读书笔记_稻盛和夫《心》
  11. vue中用cdn引入优化vender.js大小,和cdn 引入mint-ui的问题
  12. AtCoder Beginner Contest 164 E Two Currencies Bellman-Ford优化思想+01背包+动归dp状态转移
  13. 环境光传感器--OPT3001,硬件开发与程序设计
  14. 零基础通过直播小程序组件实现电商带货
  15. Egret的eui的使用
  16. 样本空间与事件集合,事件间的关系——概率论与数理统计(宋浩)
  17. 软件设计师——100
  18. Bluetooth技术学习笔记 ——HFP控制功能之连接管理
  19. H3C 设备自检常用命令
  20. 英语否定词语表达例析

热门文章

  1. scatter的用法 随机颜色_PS上最强的颜色神器插件“达芬奇配色”正式发布!文末双十一活动!全年最低价!...
  2. 简单的图片轮播器(一):一个关于仿flash的图片轮换器
  3. 适用于Linux的3个顶级开源交叉分发软件包管理系统
  4. vue前端面试题之vue组件传递参数
  5. 在web页面预览PDF文件
  6. 学习笔记之——汉明码(Hamming Code)
  7. 【TM1650】STM8S TM1650芯片控制程序
  8. (98)Address already in use: AH00072: make_sock: could not bind to address [::]:80
  9. 漂亮的后台界面PSD下载
  10. 长尾分布,重尾分布(Heavy-tailed Distribution)