-
Spring 后置处理器PostProcessor 作用及种类
2020-06-17 10:27:11一、作用 ... 2.其里边的方法会在特定的时机被容器...大类分为容器级别的后置处理器以及Bean级别的后置处理器 1.BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor(容器级别的处理器) 2.BeanPostProcess一、作用
1、本身也是一种需要注册到容器里的bean
2.其里边的方法会在特定的时机被容器调用
3.实现不改变容器或者Bean核心逻辑的情况下对Bean进行扩展
4.对Bean进行包装,影响其行为、修改Bean的内容等
二、PostProcessor的种类
大类分为容器级别的后置处理器以及Bean级别的后置处理器
1.BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor(容器级别的处理器)
2.BeanPostProcessor(Bean级别的后置处理器,AOP思想的一种体现)
-
spring后置处理器beanpostprocessor
2019-05-11 11:08:46现了spring后置处理器beanpostprocessor。为什么说beanpostprocessor重要的呢?我们先来看看 他的作用。 BeanPostProcessor接口作用: 如果我们想在Spring容器中完成bean实例化、配置以及其他初始化方法前后要...spring bean的生命周期完整过程一共有11步,但其中最重要的是第五步和第八步,因为它们先实 现了spring后置处理器beanpostprocessor。为什么说beanpostprocessor重要的呢?我们先来看看 他的作用。 BeanPostProcessor接口作用: 如果我们想在Spring容器中完成bean实例化、配置以及其他初始化方法前后要添加一些自己逻辑处理。我们需要定 义一个或多个BeanPostProcessor接口实现类,然后注册到Spring IoC容器中,说白了就是 BeanPostProcessor类可 以在【生成类的过程当中对我们的类产生代理】,并且对它里面的方法增强。
我们来做一个案例 实际来操作一下
1.创建一个带有增删改查的接口package com.zhou.ioc.demo3; public interface UserDao { public void findAll(); public void save(); public void update(); public void delete(); }
2.编写接口的实现类
package com.zhou.ioc.demo3; public class UserDaoImpl implements UserDao { @Override public void findAll() { System.out.println("查询"); } @Override public void save() { System.out.println("保存"); } @Override public void update() { System.out.println("修改"); } @Override public void delete() { System.out.println("删除"); } }
3.编写配置文件 applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean class="com.zhou.ioc.demo3.MyBeanPostProcessor"/> <bean id="userDao" class="com.zhou.ioc.demo3.UserDaoImpl"/> </beans>
4.编写一个增加方法 的类 让其去 实现 beanpostprocessor 接口
package com.zhou.ioc.demo3; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class MyBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { //初始化Bean实例之前去执行方法 return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { //剔除 beanName 不为 userDao if("userDao".equals(beanName)){ //参数一:类加载器 参数二:用来指明生成哪个对象的代理对象,通过接口指定 参数三:用来指明产生的这个代理对象要做什么事情 Object proxy = Proxy.newProxyInstance(bean.getClass().getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //如果方法是 save 就进行增强 if("save".equals(method.getName())){ System.out.println("权限校验======"); return method.invoke(bean,args); } return method.invoke(bean,args); } }); return proxy; }else { return bean; } } }
5.接着编写测试类
package com.zhou.ioc.demo3; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class SpringDemo1 { @Test public void demo1(){ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); UserDao userDao = (UserDao) applicationContext.getBean("userDao"); userDao.delete(); userDao.findAll(); userDao.save(); userDao.update(); } }
6.测试结果
删除 查询 权限校验====== 保存 修改
-
beanpostprocessor_Spring后置处理器BeanPostProcessor
2020-11-29 00:14:53Spring中有一个接口BeanPostProcessor,该接口我们叫后置处理器,作用是在Bean对象实例化和依赖注入完毕后,在显示调用初始化方法的前后添加我们自己的逻辑。接口源码如下:一、自定义后置处理器/** * ...Spring中有一个接口BeanPostProcessor,该接口我们叫后置处理器,作用是在Bean对象实例化和依赖注入完毕后,在显示调用初始化方法的前后添加我们自己的逻辑。接口源码如下:
一、自定义后置处理器
/** * BeanPostProcessor接口也叫后置处理器,作用是在Bean对象实例化和依赖注入完毕后, * 在显示调用初始化方法的前后添加我们自己的逻辑。 */@Componentpublic class MyBeanPostProcessor implements BeanPostProcessor { /** * 实例化、依赖注入完毕,在调用显示的初始化之前完成一些定制的初始化任务 * 注意:方法返回值不能为null * 如果返回null那么在后续初始化方法将报空指针异常或者通过getBean()方法获取不到bena实例对象 * 因为后置处理器从Spring IoC容器中取出bean实例对象没有再次放回IoC容器中 * @param bean * @param beanName * @return * @throws BeansException */ @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("初始化 before--实例化的bean对象:"+beanName); // 可以根据beanName不同执行不同的处理操作 return bean; } /** * 实例化、依赖注入、初始化完毕时执行 * 注意:方法返回值不能为null * 如果返回null那么在后续初始化方法将报空指针异常或者通过getBean()方法获取不到bena实例对象 * 因为后置处理器从Spring IoC容器中取出bean实例对象没有再次放回IoC容器中 * @param bean * @param beanName * @return * @throws BeansException */ @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("初始化 after...实例化的bean对象:"+beanName); // 可以根据beanName不同执行不同的处理操作 return bean; }}
注:接口中两个方法不能返回null,如果返回null那么在后续初始化方法将报空指针异常或者通过getBean()方法获取不到bena实例对象,因为后置处理器从Spring IoC容器中取出bean实例对象没有再次放回IoC容器中
然后定义实体类User:
public class User { private int id; private String name; public User(){ System.out.println("User 被实例化"); } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { System.out.println("设置name="+name); this.name = name; } public void customInit(){ System.out.println("User 中自定义的初始化方法"); }}
再将User类配置成bean对象:
@Bean(initMethod = "customInit") public User user(){ User user = new User(); user.setName("张三"); return user; }
这里也可以使用xml配置。
然后启动我们的项目,在控制台输出如下:
User 被实例化
设置name=张三
初始化 before--实例化的bean对象:user
User 中自定义的初始化方法
初始化 after...实例化的bean对象:user
通过输出语句我们能看到postProcessBeforeInitialization方法的输出语句是在Bean实例化及属性注入后执行的,且在自定义的初始化方法之前执行(通过Bean注解的initMethod指定)。而postProcessAfterInitialization方法是在自定义初始化方法执行之后执行的。
注意:
1.BeanFactory和ApplicationContext两个容器对待bean的后置处理器稍微有些不同。ApplicationContext容器会自动检测Spring配置文件中那些bean所对应的Java类实现了BeanPostProcessor接口,并自动把它们注册为后置处理器。在创建bean过程中调用它们,所以部署一个后置处理器跟普通的bean没有什么太大区别。
2.BeanFactory容器注册bean后置处理器时必须通过代码显示的注册,在IoC容器继承体系中的ConfigurableBeanFactory接口中定义了注册方法。
ConfigurableBeanFactory factory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));factory.addBeanPostProcessor(new MyBeanPostProcessor());
二、多个后置处理器
我们可以在Spring中添加多个BeanPostProcessor(后置处理器)接口实现类,默认情况下Spring容器会根据后置处理器定义的顺序依次执行。
当然,如果你想指定后置处理器的调用顺序,那么你可以通过实现Ordered接口的getOrder方法来自定义顺序。该方法默认值为 0,优先级最高,值越大优先级越低。
@Componentpublic class MyBeanPostProcessor2 implements BeanPostProcessor, Ordered { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("第2个before--实例化的bean对象:"+beanName); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("第2个after...实例化的bean对象:"+beanName); return bean; } @Override public int getOrder() { return 2; }}
-
spring实现先返回后执行_Spring后置处理器大盘点
2020-12-10 04:21:51在前面几篇文章中梳理了Spring中bean的创建过程,...在这篇文章中,将按照出场顺序对后置处理器作用场景及发挥功能进行梳理。调用1 InstantiationAwareBeanPostProcessorpostProcessBeforeInstantiation()AbstractA...在前面几篇文章中梳理了Spring中bean的创建过程,在这个过程中各式各样的后置处理器发挥了不同的作用,可以说后置处理器贯穿了bean的实例化以及初始化过程。在这篇文章中,将按照出场顺序对后置处理器作用场景及发挥功能进行梳理。
调用1
InstantiationAwareBeanPostProcessor
postProcessBeforeInstantiation()
AbstractAutowireCapableBeanFactory 的createBean方法中调用,这时bean还没有被实例化:
调用resolveBeforeInstantiation方法:
applyBeanPostProcessorsBeforeInstantiation方法:
在这里,首先拿到spring中提供的所有后置处理器,判断是不是InstantiationAwareBeanPostProcessor。该后置处理器实现了BeanPostProcessor,在这调用了postProcessBeforeInstantiation方法。
这里在目标对象被spring实例化之前调用,postProcessBeforeInstantiation方法的返回值类型是Object,可以返回任何类型的值。由于此时目标对象还未实例化,所以这个返回值可以用来代替原本该生成的目标对象的实例,一般为代理对象。
如果该方法的返回的Object对象代替了原本该生成的目标对象,那么就会把返回的对象放到单例池当中缓存,后续只有BeanPostProcessor的postProcessAfterInitialization方法会调用,其它方法不再调用。
如果这里返回了null,就按照正常的流程创建对象,交给spring去负责对象的实例化。因此这个方法可以判断这个对象在spring实例化之前是否要做特殊的处理,比如不交给Spring管理,自己使用代理产生。
调用2
SmartInstantiationAwareBeanPostProcessor
determineCandidateConstructors()
在AbstractAutowireCapableBeanFactory 的 createBeanInstance方法中调用:
determineConstructorsFromBeanPostProcessors方法,该方法用于推断实例化的构造方法,这里可能检测出bean拥有多个候选构造方法:
SmartInstantiationAwareBeanPostProcessor接口的实现类AutowiredAnnotationBeanPostProcessor负责完成这个过程,如果有多个构造方法的情况下,ctors会返回空,后续使用默认无参构造方法进行实例化。但是如果有一个构造方法上有@Autowired注解,spring会优先选择这个方法。
调用3
MergedBeanDefinitionPostProcessor
postProcessMergedBeanDefinition()
AbstractAutowireCapableBeanFactory的doCreateBean 方法中调用:
applyMergedBeanDefinitionPostProcessors方法:
在方法中对所有实现了MergedBeanDefinitionPostProcessor接口的后置处理器进行遍历,这里具体调用AutowiredAnnotationBeanPostProcessor,用于扫描需要注入的属性。
AutowiredAnnotationBeanPostProcessor中,定义了两种需要扫描的注解类型,@Autowired和@Value
在findAutowiredAnnotation方法中:
对正在创建的bean进行扫描,如果有属性和方法上面加了这两个注解,就会把对应的方法或者属性保存,最终在buildAutowiringMetadata方法中封装成InjectionMetadata对象。
需要注意这里的后置处理器仅仅用于扫描及缓存bean的注入信息,这里只完成了查找功能,没有完成属性的注入,属性的注入是在之后的另外的后置处理器中完成的。
调用4
SmartInstantiationAwareBeanPostProcessor
getEarlyBeanReference()
在AbstractAutowireCapableBeanFactory的doCreateBean 方法中调用,主要用于处理Bean的循环依赖:
在产生循环依赖后调用getEarlyBeanReference方法:
在这里遍历后置处理器,得到经过后置处理器代理后的对象,放入spring的二级缓存当中,提前暴露供循环引用的情况调用。注意这里返回的仅仅是一个对象,还算不上是一个完整的bean对象。这个具体调用过程在上一篇讲循环依赖的中的文章中讲的比较详细,如果有不明白的可以回顾一下。
调用5
InstantiationAwareBeanPostProcessor
postProcessAfterInstantiation()
在AbstractAutowireCapableBeanFactory的populateBean方法中调用:
在populateBean方法中:
该方法在目标对象实例化之后调用,这个时候对象已经被实例化,但是该实例的属性还未被设置,都是null。
这里遍历后置处理器,如果实现了InstantiationAwareBeanPostProcessor,那么就调用postProcessAfterInstantiation方法。如果方法返回值为true,按照正常流程进行属性值的填充;如果该方法返回false,会忽略属性值的设置过程。简而言之,该后置处理器用于判断当前实例化完成的bean需不需要进行属性填充。
调用6
InstantiationAwareBeanPostProcessor
postProcessPropertyValues()
同样在populateBean方法中,在postProcessAfterInstantiation后返回true时执行,如果方法返回false,该方法不会被调用。
遍历后置处理器,如果属于InstantiationAwareBeanPostProcessor类型,则调用它的postProcessPropertyValues方法。
这里发挥作用的是AutowiredAnnotationBeanPostProcessor,负责对添加了 @Autowired和@Value等注解的属性进行依赖的填充。在其中遍历所有需要注入的属性的列表,使用反射将注入的bean实例赋值给属性。(具体过程参照Spring实例化Bean源码解析)
调用7
BeanPostProcessor
postProcessBeforeInitialization()
AbstractAutowireCapableBeanFactory的doCreateBean方法中调用initializeBeanfan方法:
applyBeanPostProcessorsBeforeInitialization方法中:
在该方法中,遍历执行所有BeanPostProcessor的postProcessBeforeInitialization方法。
在执行该方法前,bean已经被实例化完成,并且完成了属性的填充,因此这个过程属于后续的bean的初始化过程。
需要注意的是,如果在bean中有方法被标注了@PostContrust注解,那么在CommonAnnotationBeanPostProcessor中,会调用该@PostContrust方法。
调用8
BeanPostProcessor
postProcessAfterInitialization()
和第7次调用入口相同,也是在AbstractAutowireCapableBeanFactory 的initializeBean方法中:
applyBeanPostProcessorsAfterInitialization方法中:
遍历执行所有BeanPostProcessor的postProcessAfterInitialization方法。综上所述,bean的各种方法执行属性为,先执行构造方法,再执行后置管理器中的before方法及@PostContrust方法,最后执行后置处理器的after方法。
调用9
InitDestroyAnnotationBeanPostProcessor
postProcessBeforeDestruction()
如果当前bean中有方法被@PreDestroy注解标注,那么当Spring的ApplicationContext执行close方法时调用该后置处理器。在DefaultSingletonBeanRegistry中执行destroyBean方法:
调用destroy方法:
InitDestroyAnnotationBeanPostProcessor的postProcessBeforeDestruction方法:
在该方法中,调用@PreDestroy注解标注的方法,执行销毁方法。
总结
本文对贯穿bean的实例化及初始化过程中出现的后置处理器进行了一下梳理,但是还有很多其他的后置处理器没有讲到。可以说后置处理器是spring提供给使用者的一些扩展点,如果能够熟练的使用这些后置处理器,能够帮助我们接触到一些spring中比较深层的东西,并对spring中的生命周期进行有利的插手。公众号后台回复
"面试"---领取大厂面试资料
"导图"---领取24张Java后端学习笔记导图
"架构"---领取29本java架构师电子书籍
"实战"---领取springboot实战项目
"视频"---领取最新java架构师视频
"加群"---加入学习交流群
扫码关注公众号
有趣、深入、直接
与你聊聊java
觉得有用,点个在看吧~ -
spring bean的后置处理器作用(转载)
2021-03-27 22:01:43spring bean的后置处理器作用 -
spring后置处理器BeanPostProcessor
2018-07-02 16:36:00BeanPostProcessor的作用是在调用初始化方法的前后添加一些逻辑,这里初始化方法是指在配置文件中配置init-method,或者实现了InitializingBean接口的afterPropertiesSet方法,注意不包括@PostConstruct这种初始化... -
Spring 后置处理器 PropertyPlaceholderConfigurer 类(引用外部文件)
2019-10-08 15:11:03PropertyPlaceholderConfigurer 是 BeanFactory 后置处理器的实现,也是 BeanFactoryPostProcessor 接口的一个实现。允许将上下文(配置文件)中的属性值放在另一个单独的标准 JavaProperties 文件中去。在 XML 文件... -
SpringBean后置处理器学习记录
2019-08-18 23:09:43bean的后置处理器 : 对IOC容器中所有的bean都起作用. */ public class MyBeanPostProcessor implements BeanPostProcessor { /** 在bean的生命周期的初始化方法之前执行 Object bean: 正在被创建的bean对象. String... -
beanpostprocessor作用_spring-后置处理器BeanPostProcessor
2020-12-17 22:49:02BeanPostProcessor及其子类都实现了后置处理的功能。作用:在Bean对象在实例化和依赖注入完毕后,在显示调用初始化方法的前后添加我们自己的逻辑。注意是Bean实例化完毕后及依赖注入完成后触发的。接口的源码如下... -
Spring的后置处理器BeanPostProcessor
2019-10-08 15:10:52一、BeanPostProcessor接口的作用 如果我们需要在Spring容器完成Bean的实例化、配置和其他的初始化前后添加一些自己的逻辑处理,我们就可以定义一个或者多个BeanPostProcessor接口的实现,然后注册到容器中去。 ... -
spring的组件工厂后置处理器——BeanFactoryPostProcessor
2019-04-21 17:57:00spring有两种后置处理器: 1. 组件后置处理器——org.springframework.beans.factory.config.BeanPostProcessor; 2. 工厂后置处理器——org.springframework.beans.factory.config.BeanFactoryPostProcessor。 ... -
Spring之BeanPostProcessor(后置处理器)介绍
2019-03-03 13:10:33该接口我们也叫后置处理器,作用是在Bean对象在实例化和依赖注入完毕后,在显示调用初始化方法的前后添加我们自己的逻辑。注意是Bean实例化触发的。接口的源码如下 public interface BeanPostProcessor { ..... -
spring09--bean后置处理器
2019-04-18 20:24:19bean后置处理器的作用:Bean后置处理器允许在调用初始化方法前后对Bean进行额外的处理。 1、创建bean后置处理器: 先创建一个类实现BeanPostProcessor接口,并具体提供: postProcessBeforeInitialization(Object... -
spring(二):后置处理器和AOP
2020-03-22 17:52:55文章目录2.后置处理器2.1. BeanProcessor实现分析2.2 ApplicationContextAwareProcessor实现分析3.AOP3.1 使用案例3.2 源码分析核心类加载源码跟踪图 2.后置处理器 2.1. BeanProcessor实现...后置处理器的作用:判... -
35.spring系列- ConfigurationClassPostProcessor Spring的重要后置处理器
2020-11-04 16:37:56疑惑 @Configuraction注解的作用是什么,Spring是如何解析加了@Configuraction...ConfigurationClassPostProcessor 是一个BeanFactory的后置处理器,因此它的主要功能是参与BeanFactory的建造。在这个类中,会解析加 -
2.5、调用后置处理器
2020-08-18 23:54:41在idea中搜索了一下Spring的后置处理器(PostProcessor),找出了下图的几个 本文主要来分析红框中标出的两个,也就是在 refresh() 方法的第5步调用的后置处理器 1、后置处理器调用的时机 2、后置处理器调用的顺序 ... -
Spring-Bean后置处理器之AnnotationAwareAspectJAutoProxyCreator
2020-11-07 05:27:11AnnotationAwareAspectJAutoProxyCreator后置器的作用是什么? Spring AOP自动增强bean是如何实现的。 如何在spring上下文添加AnnotationAwareAspectJAutoProxyCreator? 如何利用ProxyFactory硬编码实现一个bean的... -
简单了解spring中的BeanPostProcessor(后置处理器)
2020-02-21 22:47:36最近项目中使用了spring中的异步处理@EnableAsync和定时任务@EnableSchedule,二者作用在同一个service中,导致异步方法失效,最终发现还是不了解后置处理器作用导致的,还是图样图森破。 BeanPostProcessor 该接口... -
Spring系列之BeanPostProcessor(后置处理器)介绍
2020-08-02 15:30:56该接口我们也叫后置处理器,作用是在Bean对象在实例化和依赖注入完毕后,在显示调用初始化方法的前后添加我们自己的逻辑。注意是Bean实例化完毕后及依赖注入完成后触发的。接口的源码如下 public interface ... -
记录:Spring中Bean的生命周期所涉及到的主要后置处理器
2019-08-11 20:39:40InstantiationAwareBeanPostProcessor后置处理器,调用的是:postProcessBeforeInstantiation方法,第一次后置处理器的作用是:给后置处理器一个返回代理对象的机会。这个方法用来在对象实例化前直接返回一个对象... -
Spring-BeanFactory后置处理器之ConfigurationClassPostProcessor
2020-11-07 05:27:11ConfigurationClassPostProcessor的作用是什么? @Configuration、@Component、@ComponentScan、@ComponentScans、@Bean、@Import等注解是如何完成bean注册的? @Conditional注解如何控制配置类是否需要解析? @... -
Spring中的后置处理器BeanPostProcessor讲解
2019-08-06 16:57:08BeanPostProcessor接口作用: 如果我们想在Spring容器中完成bean实例化、配置以及其他初始化方法前后要添加一些自己逻辑处理。我们需要定义一个或多个BeanPostProcessor接口实现类,然后注册到Spring IoC容器中。 ... -
Spring框架总结五---bean生命周期后置处理器
2020-05-18 17:36:54总结(删除线部分为后置处理器部分)二.后置处理器1.什么时候起作用?2.如何处理?3.使用条件?三.实现代码1.Emp类2.Person类3.后置处理器类4.配置文件5.运行效果6.总结 一.生命周期 1.创建bean实例 public Emp() { ... -
Bean后置处理器 BeanPostProcessor
2017-11-17 11:18:00Bean后置处理器允许在调用初始化方法前后对Bean进行额外的处理,Bean后置处理器对IOC容器的所有bean实例逐一处理,而非单一实例。 我们可以定义一个或多个BeanPostProcessor接口实现类,然后注册到Spring IOC容器中...