文章目录
源码: https://github.com/nieandsun/spring-study
1 前言
通过前面两篇文章
《【bean的生命周期】— 对象创建+初始化流程分析 — 【重点@Autowired的作用时机】》
《【bean的生命周期】— 构造方法、@Autowired、BeanPostProcessor、InitializingBean等的执行顺序解析》
我已经从spring源码的角度介绍了BeanPostProcessor在单实例bean创建+初始化过程中的作用时机,本篇文章将对BeanPostProcessor的使用方法和原理做进一步剖析。
2 BeanPostProcessor简单介绍
2.1 BeanPostProcessor接口 + 运行时机介绍
BeanPostProcessor其实是一个顶级接口,其源码如下:
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;
}
}
前面两篇文章已经介绍过BeanPostProcessor的作用时机如下:
也就是说在每一个单实例业务bean
的创建+初识化过程中,都会走当前IOC容器里所有实现了BeanPostProcessor接口的类的postProcessBeforeInitialization方法和postProcessAfterInitialization方法 —> 当然实现了BeanPostProcessor接口的bean是在更早的时机被注册到了IOC容器中。
2.2 BeanPostProcessor实现类简单介绍
spring源码里其实有很多实现了BeanPostProcessor接口的类,当然这些类并不会在spring启动时都一股脑的被注入到IOC容器里,除了一些必要的类之外,其他的类可以由使用者按需选择。
2.3 默认使用的BeanPostProcessor简单介绍
通过断点调试可以发现,针对单实例业务bean默认情况下spring注入到IOC容器中的BeanPostProcessor有如下几个:
每一个BeanPostProcessor对当前业务bean具体做了什么操作本文不做具体分析了 — 下篇文章应该会介绍一下ApplicationContextAwareProcessor
,因为在工作中我们可能会经常遇到这个processor。
3 自定义BeanPostProcessor
通过上面的介绍可以知道BeanPostProcessor其实就是一个接口,当然我们也可以实现该接口,并将其注入到IOC容器,从而达到某些特定的目的。
3.1 自定义BeanPostProcessor并将其注入到IOC容器
- 自定义BeanPostProcessor
package com.nrsc.springstudy.c072_bean_life_cycle.processor;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
@Component //通过扫描的方式将其注入到IOC容器
public class NrscBeanPostProcessor implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.err.println("自定义后置处理器(前)---当前bean为:" + bean + ",beanName为:" + beanName);
//返回处理后的bean --> 接下来该bean才能被注入到IOC容器
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.err.println("自定义后置处理器(后)---当前bean为:" + bean + ",beanName为:" + beanName);
return bean;
}
}
- 业务bean — Cat
package com.nrsc.springstudy.c072_bean_life_cycle.beans;
import org.springframework.beans.factory.InitializingBean;
import javax.annotation.PostConstruct;
public class Cat implements InitializingBean {
private String name;
//构造方法-----创建对象时调用
public Cat() {
System.out.println("Cat......constructor............");
}
//设置name属性时会调用
public void setName(String name) {
System.out.println("===cat=========setName========");
this.name = name;
}
public String getName() {
return name;
}
//在配置类中利用注解将initMethod指向下面的init方法----对应于initMethod的用法
public void init() {
System.out.println("Cat......init............");
}
//继承了InitializingBean接口,需要实现afterPropertiesSet方法---对应于InitializingBean的用法
public void afterPropertiesSet() throws Exception {
System.out.println("Cat......afterPropertiesSet............");
}
@PostConstruct
public void init2() {
System.out.println("Cat......@PostConstruct............");
}
}
3.2 测试
(1)可以发现自定义的BeanPostProcessor也起作用了
(2)运行结果如下:
由此也再一次验证了上篇文章中介绍的业务bean的创建+初始化过程中构造方法、@Autowired、BeanPostProcessor、@PostConstruct、InitializingBean、initMethod的执行顺序。
4 后话 — 介绍一个BeanPostProcessor的使用场景
其实在我之前的一篇博客里介绍过BeanPostProcessor的使用 —> 感觉那是一个比较好的BeanPostProcessor使用场景。那篇博客的地址为:《【Spring Security OAuth开发APP认证框架】— APP认证框架下社交登陆过程中注册逻辑处理》 。