一句话:bean后置处理器就是对bean的生命周期的各阶段的增强

1、bean生命周期启动类:

代码语言:javascript复制@SpringBootApplication

public class A03 {

public static void main(String[] args) {

//创建容器

ConfigurableApplicationContext context =

SpringApplication.run(A03.class, args);

//关闭容器

context.close();

}

}添加扫描bean

代码语言:javascript复制@Component

@Slf4j

public class LifeCycleBean {

public LifeCycleBean() {

log.debug("bean生命周期>>>>>>>>>>>>>>>>>>>构造");

}

@Autowired

public void autowire(@Value("${JAVA_HOME}") String home) {

log.debug("bean生命周期>>>>>>>>>>>>>>>>>>依赖注入: {}", home);

}

@PostConstruct

public void init() {

log.debug("bean生命周期>>>>>>>>>>>>>>>>>>>初始化");

}

@PreDestroy

public void destroy() {

log.debug("bean生命周期>>>>>>>>>>>>>>>>>>>销毁");

}

}输出结果:

代码语言:javascript复制[INFO ] 18:03:31.555 [main] o.s.b.w.e.tomcat.TomcatWebServer - Tomcat initialized with port(s): 8080 (http)

[INFO ] 18:03:31.563 [main] o.a.coyote.http11.Http11NioProtocol - Initializing ProtocolHandler ["http-nio-8080"]

[INFO ] 18:03:31.564 [main] o.a.catalina.core.StandardService - Starting service [Tomcat]

[INFO ] 18:03:31.564 [main] o.a.catalina.core.StandardEngine - Starting Servlet engine: [Apache Tomcat/9.0.53]

[INFO ] 18:03:31.662 [main] o.a.c.c.C.[Tomcat].[localhost].[/] - Initializing Spring embedded WebApplicationContext

[INFO ] 18:03:31.663 [main] o.s.b.w.s.c.ServletWebServerApplicationContext - Root WebApplicationContext: initialization completed in 994 ms

[DEBUG] 18:03:31.710 [main] com.xc.a03.LifeCycleBean - bean生命周期>>>>>>>>>>>>>>>>>>>构造

[DEBUG] 18:03:31.713 [main] com.xc.a03.LifeCycleBean - bean生命周期>>>>>>>>>>>>>>>>>>依赖注入: E:\java\jdk\jdk8\tools

[DEBUG] 18:03:31.714 [main] com.xc.a03.LifeCycleBean - bean生命周期>>>>>>>>>>>>>>>>>>>初始化

[INFO ] 18:03:31.917 [main] o.s.b.a.w.s.WelcomePageHandlerMapping - Adding welcome page: class path resource [static/index.html]

[INFO ] 18:03:31.986 [main] c.a.d.s.b.a.DruidDataSourceAutoConfigure - Init DruidDataSource

[INFO ] 18:03:32.055 [main] c.a.druid.pool.DruidDataSource - {dataSource-1} inited

[INFO ] 18:03:32.416 [main] o.a.coyote.http11.Http11NioProtocol - Starting ProtocolHandler ["http-nio-8080"]

[INFO ] 18:03:32.429 [main] o.a.c.c.C.[Tomcat].[localhost].[/] - Initializing Spring DispatcherServlet 'dispatcherServlet'

[INFO ] 18:03:32.430 [main] o.s.web.servlet.DispatcherServlet - Initializing Servlet 'dispatcherServlet'

[TRACE] 18:03:32.430 [main] o.s.web.servlet.DispatcherServlet - Detected org.springframework.web.multipart.support.StandardServletMultipartResolver@4eed2acf

[TRACE] 18:03:32.430 [main] o.s.web.servlet.DispatcherServlet - Detected org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver@36fc05ff

[TRACE] 18:03:32.430 [main] o.s.web.servlet.DispatcherServlet - Detected org.springframework.web.servlet.theme.FixedThemeResolver@57c47a9e

[TRACE] 18:03:32.430 [main] o.s.web.servlet.DispatcherServlet - Detected DefaultRequestToViewNameTranslator

[TRACE] 18:03:32.430 [main] o.s.web.servlet.DispatcherServlet - Detected SessionFlashMapManager

[DEBUG] 18:03:32.430 [main] o.s.web.servlet.DispatcherServlet - enableLoggingRequestDetails='false': request parameters and headers will be masked to prevent unsafe logging of potentially sensitive data

[INFO ] 18:03:32.430 [main] o.s.web.servlet.DispatcherServlet - Completed initialization in 0 ms

[INFO ] 18:03:32.432 [main] o.s.b.w.e.tomcat.TomcatWebServer - Tomcat started on port(s): 8080 (http) with context path ''

[INFO ] 18:03:32.441 [main] com.xc.a03.A03 - Started A03 in 2.152 seconds (JVM running for 3.009)

[INFO ] 18:03:32.713 [main] c.a.druid.pool.DruidDataSource - {dataSource-1} closing ...

[INFO ] 18:03:32.714 [main] c.a.druid.pool.DruidDataSource - {dataSource-1} closed

[DEBUG] 18:03:32.715 [main] com.xc.a03.LifeCycleBean - bean生命周期>>>>>>>>>>>>>>>>>>>销毁

Process finished with exit code 02、常用的bean后置处理器接口2.1、初始化-Bean后置处理器BeanPostProcessor是bean后置处理器最底层接口两个方法返回的bean会替换原来的bean初始化阶段在实例化和属性填充之后初始化之前执行:解析注解@PostConstruct、@ConfigurationProperties初始化之后执行:代理增强代码语言:javascript复制public interface BeanPostProcessor {

//bean初始化前执行

@Nullable

default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

return bean;

}

//bean初始化后执行

@Nullable

default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

return bean;

}

}自定义初始化后置处理器代码语言:javascript复制@Component

@Slf4j

public class MyBeanPostProcessor implements BeanPostProcessor {

@Override

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

if (beanName.equals("lifeCycleBean"))

log.debug("初始化后置处理器>>>>>>> 初始化之前执行, 这里返回的对象会替换掉原本的 bean, 如 @PostConstruct、@ConfigurationProperties");

return bean;

}

@Override

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

if (beanName.equals("lifeCycleBean"))

log.debug("初始化后置处理器>>>>>>> 初始化之后执行, 这里返回的对象会替换掉原本的 bean, 如代理增强");

return bean;

}

}2.2、实例化-Bean后置处理器BeanPostProcessor的扩展接口(子接口)实例化之前执行:返回的bean对象可能是要使用的代理,而不是目标bean,从而有效地抑制了目标bean的默认实例化。如果此方法返回非null对象,则bean创建过程将被短路(也就是正常bean实例化的后续流程不再执行)实例化之后执行:返回结果为true时,说明应该为bean设置属性。如果返回结果为false,跳过bean属性赋值环节依赖注入阶段执行:解析注解@Autowired、@Value、@ResourcepostProcessPropertyValues:这个方法在spring低版本中使用,在高版本已经过时了,使用postProcessProperties代替代码语言:javascript复制public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {

//bean实例化前执行

@Nullable

default Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException {

return null;

}

//bean实例化后执行

default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {

return true;

}

//依赖注入阶段执行

@Nullable

default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {

return null;

}

/** @deprecated */

@Deprecated

@Nullable

default PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {

return pvs;

}

}自定义实例化后置处理器代码语言:javascript复制@Component

@Slf4j

public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

@Override

public Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException {

if (beanName.equals("lifeCycleBean"))

log.debug("实例化后置处理器>>>>>>> 实例化之前执行, 这里返回的对象会替换掉原本的 bean");

return null;

}

@Override

public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {

if (beanName.equals("lifeCycleBean")) {

log.debug("实例化后置处理器>>>>>>>实例化之后执行, 这里如果返回 false 会跳过依赖注入阶段");

// return false;

}

return true;

}

@Override

public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {

if (beanName.equals("lifeCycleBean"))

log.debug("实例化后置处理器>>>>>>> 依赖注入阶段执行, 如 @Autowired、@Value、@Resource");

return pvs;

}

}2.3、销毁-Bean后置处理器BeanPostProcessor的扩展接口(子接口)销毁之前执行:解析注解@PreDestroy代码语言:javascript复制public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor {

//这里实现销毁对象的逻辑

void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;

//判断是否需要处理这个对象的销毁

default boolean requiresDestruction(Object bean) {

return true;

}

}自定义销毁后置处理器代码语言:javascript复制@Component

@Slf4j

public class MyDestructionAwareBeanPostProcessor implements DestructionAwareBeanPostProcessor {

@Override

public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {

if (beanName.equals("lifeCycleBean"))

log.debug("销毁后置处理器>>>>>>> 销毁之前执行, 如 @PreDestroy");

}

} 生命周期bean添加后置处理器后输出结果:

代码语言:javascript复制[INFO ] 18:07:14.639 [main] o.s.b.w.e.tomcat.TomcatWebServer - Tomcat initialized with port(s): 8080 (http)

[INFO ] 18:07:14.646 [main] o.a.coyote.http11.Http11NioProtocol - Initializing ProtocolHandler ["http-nio-8080"]

[INFO ] 18:07:14.646 [main] o.a.catalina.core.StandardService - Starting service [Tomcat]

[INFO ] 18:07:14.646 [main] o.a.catalina.core.StandardEngine - Starting Servlet engine: [Apache Tomcat/9.0.53]

[INFO ] 18:07:14.715 [main] o.a.c.c.C.[Tomcat].[localhost].[/] - Initializing Spring embedded WebApplicationContext

[INFO ] 18:07:14.715 [main] o.s.b.w.s.c.ServletWebServerApplicationContext - Root WebApplicationContext: initialization completed in 867 ms

[DEBUG] 18:07:14.748 [main] c.x.a.MyInstantiationAwareBeanPostProcessor - 实例化后置处理器>>>>>>> 实例化之前执行, 这里返回的对象会替换掉原本的 bean

[DEBUG] 18:07:14.749 [main] com.xc.a03.LifeCycleBean - bean生命周期>>>>>>>>>>>>>>>>>>>构造

[DEBUG] 18:07:14.750 [main] c.x.a.MyInstantiationAwareBeanPostProcessor - 实例化后置处理器>>>>>>>实例化之后执行, 这里如果返回 false 会跳过依赖注入阶段

[DEBUG] 18:07:14.750 [main] c.x.a.MyInstantiationAwareBeanPostProcessor - 实例化后置处理器>>>>>>> 依赖注入阶段执行, 如 @Autowired、@Value、@Resource

[DEBUG] 18:07:14.751 [main] com.xc.a03.LifeCycleBean - bean生命周期>>>>>>>>>>>>>>>>>>依赖注入: E:\java\jdk\jdk8\tools

[DEBUG] 18:07:14.752 [main] com.xc.a03.MyBeanPostProcessor - 初始化后置处理器>>>>>>> 初始化之前执行, 这里返回的对象会替换掉原本的 bean, 如 @PostConstruct、@ConfigurationProperties

[DEBUG] 18:07:14.752 [main] com.xc.a03.LifeCycleBean - bean生命周期>>>>>>>>>>>>>>>>>>>初始化

[DEBUG] 18:07:14.752 [main] com.xc.a03.MyBeanPostProcessor - 初始化后置处理器>>>>>>> 初始化之后执行, 这里返回的对象会替换掉原本的 bean, 如代理增强

[INFO ] 18:07:14.920 [main] o.s.b.a.w.s.WelcomePageHandlerMapping - Adding welcome page: class path resource [static/index.html]

[INFO ] 18:07:14.986 [main] c.a.d.s.b.a.DruidDataSourceAutoConfigure - Init DruidDataSource

[INFO ] 18:07:15.056 [main] c.a.druid.pool.DruidDataSource - {dataSource-1} inited

[INFO ] 18:07:15.273 [main] o.a.coyote.http11.Http11NioProtocol - Starting ProtocolHandler ["http-nio-8080"]

[INFO ] 18:07:15.285 [main] o.a.c.c.C.[Tomcat].[localhost].[/] - Initializing Spring DispatcherServlet 'dispatcherServlet'

[INFO ] 18:07:15.285 [main] o.s.web.servlet.DispatcherServlet - Initializing Servlet 'dispatcherServlet'

[TRACE] 18:07:15.286 [main] o.s.web.servlet.DispatcherServlet - Detected org.springframework.web.multipart.support.StandardServletMultipartResolver@57c47a9e

[TRACE] 18:07:15.286 [main] o.s.web.servlet.DispatcherServlet - Detected org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver@642505c7

[TRACE] 18:07:15.286 [main] o.s.web.servlet.DispatcherServlet - Detected org.springframework.web.servlet.theme.FixedThemeResolver@4339e0de

[TRACE] 18:07:15.286 [main] o.s.web.servlet.DispatcherServlet - Detected DefaultRequestToViewNameTranslator

[TRACE] 18:07:15.286 [main] o.s.web.servlet.DispatcherServlet - Detected SessionFlashMapManager

[DEBUG] 18:07:15.286 [main] o.s.web.servlet.DispatcherServlet - enableLoggingRequestDetails='false': request parameters and headers will be masked to prevent unsafe logging of potentially sensitive data

[INFO ] 18:07:15.286 [main] o.s.web.servlet.DispatcherServlet - Completed initialization in 0 ms

[INFO ] 18:07:15.287 [main] o.s.b.w.e.tomcat.TomcatWebServer - Tomcat started on port(s): 8080 (http) with context path ''

[INFO ] 18:07:15.295 [main] com.xc.a03.A03 - Started A03 in 1.781 seconds (JVM running for 2.529)

[INFO ] 18:07:15.581 [main] c.a.druid.pool.DruidDataSource - {dataSource-1} closing ...

[INFO ] 18:07:15.582 [main] c.a.druid.pool.DruidDataSource - {dataSource-1} closed

[DEBUG] 18:07:15.584 [main] c.x.a.MyDestructionAwareBeanPostProcessor - 销毁后置处理器>>>>>>> 销毁之前执行, 如 @PreDestroy

[DEBUG] 18:07:15.584 [main] com.xc.a03.LifeCycleBean - bean生命周期>>>>>>>>>>>>>>>>>>>销毁

Process finished with exit code 03、模板方法设计模式,扩展bean后置处理器getBean方法执行流程步骤已确定后置处理器接口集合遍历,添加后置处理器只需要bean工厂添加到后置处理器集合汇总即可代码语言:javascript复制public class TestMethodTemplate {

public static void main(String[] args) {

MyBeanFactory beanFactory = new MyBeanFactory();

beanFactory.addBeanPostProcessor(bean -> System.out.println("解析 @Autowired"));

beanFactory.addBeanPostProcessor(bean -> System.out.println("解析 @Resource"));

beanFactory.getBean();

}

}

// 模板方法

class MyBeanFactory {

private final List processors = new ArrayList<>();

public void addBeanPostProcessor(BeanPostProcessor processor) {

processors.add(processor);

}

public Object getBean() {

Object bean = new Object();

System.out.println("构造 " + bean);

System.out.println("依赖注入 " + bean); // @Autowired, @Resource

for (BeanPostProcessor processor : processors) {

processor.inject(bean);

}

System.out.println("初始化 " + bean);

return bean;

}

}

interface BeanPostProcessor {

public void inject(Object bean); // 对依赖注入阶段的扩展

}输出结果:

代码语言:javascript复制构造 java.lang.Object@533ddba

依赖注入 java.lang.Object@533ddba

解析 @Autowired

解析 @Resource

初始化 java.lang.Object@533ddba

Process finished with exit code 04、bean后置处理器排序实现了 PriorityOrdered 接口的优先级最高实现了 Ordered 接口与加了 @Order 注解的平级, 按数字升序其它的排在最后代码语言:javascript复制public class TestProcessOrder {

public static void main(String[] args) {

DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);

//排序

List list = Arrays.asList(new P1(), new P2(), new P3(), new P4(), new P5());

list.sort(beanFactory.getDependencyComparator());

//遍历执行后置处理器的初始化之前方法

list.forEach(processor->{

processor.postProcessBeforeInitialization(new Object(), "");

});

}

}

@Order(1)

class P1 implements BeanPostProcessor {

@Override

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

System.out.println("postProcessBeforeInitialization @Order(1)");

return bean;

}

}

@Order(2)

class P2 implements BeanPostProcessor {

@Override

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

System.out.println("postProcessBeforeInitialization @Order(2)");

return bean;

}

}

class P3 implements BeanPostProcessor, PriorityOrdered {

@Override

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

System.out.println("postProcessBeforeInitialization PriorityOrdered getOrder() == 100");

return bean;

}

@Override

public int getOrder() {

return 100;

}

}

class P4 implements BeanPostProcessor, Ordered {

@Override

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

System.out.println("postProcessBeforeInitialization Ordered getOrder() == 0");

return bean;

}

@Override

public int getOrder() {

return 0;

}

}

class P5 implements BeanPostProcessor {

@Override

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

System.out.println("postProcessBeforeInitialization 无排序接口");

return bean;

}

}输出结果:

代码语言:javascript复制Connected to the target VM, address: '127.0.0.1:63224', transport: 'socket'

postProcessBeforeInitialization PriorityOrdered getOrder() == 100

postProcessBeforeInitialization Ordered getOrder() == 0

postProcessBeforeInitialization @Order(1)

postProcessBeforeInitialization @Order(2)

postProcessBeforeInitialization 无排序接口

Disconnected from the target VM, address: '127.0.0.1:63224', transport: 'socket'

Process finished with exit code 05、bean后置处理器实现类的作用准备bean:

代码语言:javascript复制@Slf4j

public class Bean1 {

private Bean2 bean2;

@Autowired

public void setBean2(Bean2 bean2) {

log.debug("@Autowired 生效: {}", bean2);

this.bean2 = bean2;

}

@Autowired

private Bean3 bean3;

@Resource

public void setBean3(Bean3 bean3) {

log.debug("@Resource 生效: {}", bean3);

this.bean3 = bean3;

}

private String home;

@Autowired

public void setHome(@Value("${JAVA_HOME}") String home) {

log.debug("@Value 生效: {}", home);

this.home = home;

}

@PostConstruct

public void init() {

log.debug("@PostConstruct 生效");

}

@PreDestroy

public void destroy() {

log.debug("@PreDestroy 生效");

}

@Override

public String toString() {

return "Bean1{" +

"bean2=" + bean2 +

", bean3=" + bean3 +

", home='" + home + '\'' +

'}';

}

}代码语言:javascript复制public class Bean2 {

}代码语言:javascript复制public class Bean3 {

}代码语言:javascript复制@ConfigurationProperties(prefix = "java")

public class Bean4 {

private String home;

private String version;

public String getHome() {

return home;

}

public void setHome(String home) {

this.home = home;

}

public String getVersion() {

return version;

}

public void setVersion(String version) {

this.version = version;

}

@Override

public String toString() {

return "Bean4{" +

"home='" + home + '\'' +

", version='" + version + '\'' +

'}';

}

}启动类:

代码语言:javascript复制public class A04 {

public static void main(String[] args) {

// GenericApplicationContext 是一个【干净】的容器

GenericApplicationContext context = new GenericApplicationContext();

// 用原始方法注册三个 bean

context.registerBean("bean1", Bean1.class);

context.registerBean("bean2", Bean2.class);

context.registerBean("bean3", Bean3.class);

context.registerBean("bean4", Bean4.class);

// 解析表达式

context.getDefaultListableBeanFactory().setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());

// @Autowired @Value

context.registerBean(AutowiredAnnotationBeanPostProcessor.class);

// @Resource @PostConstruct @PreDestroy

context.registerBean(CommonAnnotationBeanPostProcessor.class);

//解析配置文件properties对象

ConfigurationPropertiesBindingPostProcessor.register(context.getDefaultListableBeanFactory());

// 执行beanFactory后处理器, 添加bean后处理器, 初始化所有单例

context.refresh();

System.out.println(context.getBean(Bean1.class));

// 销毁容器

context.close();

}

}输出结果:

代码语言:javascript复制[DEBUG] 22:37:41.613 [main] com.xc.a04.Bean1 - @Resource 生效: com.xc.a04.Bean3@f2f2cc1

[DEBUG] 22:37:41.661 [main] com.xc.a04.Bean1 - @Value 生效: E:\java\jdk\jdk8\tools

[DEBUG] 22:37:41.664 [main] com.xc.a04.Bean1 - @Autowired 生效: com.xc.a04.Bean2@2fd6b6c7

[DEBUG] 22:37:41.664 [main] com.xc.a04.Bean1 - @PostConstruct 生效

Bean1{bean2=com.xc.a04.Bean2@2fd6b6c7, bean3=com.xc.a04.Bean3@f2f2cc1, home='E:\java\jdk\jdk8\tools'}

[DEBUG] 22:37:41.905 [main] com.xc.a04.Bean1 - @PreDestroy 生效

Process finished with exit code 0 总结:后置处理器解析@Autowired@Resource@PostConstruct等一些列注解处理bean生命周期阶段(依赖注入, 初始化)的扩展功能