在spring中beanPostProcessor绝对是开天辟地的产物,给了程序员很多自主权,beanPostProcessor即常说的bean后置处理器。

一、概览

先来说下InstantiationAwareBeanPostProcessor,这个后置处理器是BeanPostProcessor的子接口,继承自BeanPostProcessor,先看下BeanPostProcessor中的方法,

再看下InstantiationAwareBeanPostProcessor中的方法,

可见InstantiationAwareBeanPostProcessor扩展了BeanPostProcessor接口,并且新增了4个方法,今天先看postProcessAfterInstantiation方法,

default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true;
}

改方法有默认的返回值为true。

二、详述

InstantiationAwareBeanPostProcessor中的postProcessAfterInstantiation方法的作用是什么那,用在什么地方。在看spring源码的时候看到属性注入这段代码,其中属性注入是在populateBean方法中完成,在此方法中便出现了postProcessAfterInstatiation方法的调用,这里只贴出populateBean方法中和这块有关系的代码,

boolean continueWithPropertyPopulation = true;
//调用beanFactory中已注册的beanPostProcessors即bean后置处理器,判断是否为InstantiationAwareBeanPostProcessor的类型,如果是执行postProcessAfterInstantiation
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
//如果返回值为false才会进到下面的赋值操作,从而下方的1处才会为true,则属性注入才会中断
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
//1
if (!continueWithPropertyPopulation) {
return;
}

上面这段逻辑就是来循环已经注册的beanPostProcessor,找到是InstantiationAwareBeanPostProcessor的类型,并执行其postProcessAfterInstantiation方法,通过查看已注册的beanPostProcessor发现其返回值均为true,通过上面的分析,只有postProcessAfterInstantiation方法返回false,populateBean方法才会返回,属性注入才会中断,即不会注入值。

怎么才能保证postProcessAfterInstantiation方法返回false那,这里只有自己向spring注册一个InstantiationAwareBeanPostProcessor的后置处理器,下面是我的一个后置处理器,

package cn.com.my.test;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.stereotype.Component;
@Component
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor { @Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
// TODO Auto-generated method stub
System.out.println("beanName:"+beanName);
if("userService".equals(beanName)) {
return false;
}
return InstantiationAwareBeanPostProcessor.super.postProcessAfterInstantiation(bean, beanName);
}
}

自定义的beanPostProcessor仅实现了postProcessAfterInstantiation方法,上面的代码逻辑中,可以看到只有beanName为userService的时候,改方法才会返回false,其他情况下调用的接口方法,返回默认值true。

下面看我的测试类,

package cn.com.my.test;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Test {

    public static void main(String[] args) {
// TODO Auto-generated method stub AnnotationConfigApplicationContext ac=new AnnotationConfigApplicationContext(Config.class); UserService us=ac.getBean(UserService.class);
System.out.println("us.roleService:"+us.getRoleService());
} }

下面是我的UserService类,

package cn.com.my.test;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.stereotype.Component; @Component
public class UserService { @Autowired
private RoleService roleService; public RoleService getRoleService() {
return roleService;
} public void setRoleService(RoleService roleService) {
this.roleService = roleService;
}
}

从UserService类中,可以看出有一个加了注解的roleService属性,正常情况下会自动注入改属性,但在我自定义的beanPostProcessor之后,看下面的结果

神奇的事情,发生了us.roleService的属性返回的null。

这是为什么那,我们再看populateBean中的这段代码,

boolean continueWithPropertyPopulation = true;
//调用beanPostProcessors即bean后置处理器,
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
} if (!continueWithPropertyPopulation) {
return;
}

由于,我们向beanFactory中注册了一个beanPostProcessor,所以这里循环的时候肯定会执行我的postProcessAfterInstantiation后置处理器,而我在后置处理器中进行了判断,即在给beanName为userService进行属性注入的时候postProcessAfterInstantiation方法会返回false,那么上面的continueWithPropertyPopulation便为false,导致会进入到下面的if,方法直接返回,属性注入便会中止,所以UserService类中的roleService的值为null。

三、适用场合

什么时候需要实现InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation方法那,如果不想使用spring的自动注入(前提是已经使用了@Autowired注解),则对于特殊的bean则可以注册一个beanPostProcessor使其不进行注入,使用自己的方式进行注入。

原创不易,有不当之处,欢迎指正,谢谢!

spring中BeanPostProcessor之一:InstantiationAwareBeanPostProcessor(01)的更多相关文章

  1. spring中BeanPostProcessor之三:InitDestroyAnnotationBeanPostProcessor(01)

    在<spring中BeanPostProcessor之二:CommonAnnotationBeanPostProcessor(01)>一文中,分析到在调用CommonAnnotationB ...

  2. spring中BeanPostProcessor之四:AutowiredAnnotationBeanPostProcessor(01)

    在<spring中BeanPostProcessor之二:CommonAnnotationBeanPostProcessor(01)>中分析了CommonAnnotationBeanPos ...

  3. Spring中BeanPostProcessor

    Spring中BeanPostProcessor 前言: 本文旨在介绍Spring动态配置数据源的方式,即对一个DataSource的配置诸如jdbcUrl,user,password,driverC ...

  4. spring中BeanPostProcessor之二:CommonAnnotationBeanPostProcessor(01)

    在上篇博客中分享了InstantiationAwareBeanPostProcessor接口中的四个方法,分别对其进行了详细的介绍,在文末留下了一个问题,那就是postProcessPropertie ...

  5. spring中BeanPostProcessor之一:InstantiationAwareBeanPostProcessor(02)

    在上篇博客中写道了bean后置处理器InstantiationAwareBeanPostProcessor,只介绍了其中一个方法的作用及用法,现在来看postProcessBeforeInstanti ...

  6. spring中BeanPostProcessor之一:InstantiationAwareBeanPostProcessor(03)

    前面介绍了InstantiationAwareBeanPostProcessor后置处理器的postProcessBeforeInstantiation和postProcessAfterInstant ...

  7. spring(三):spring中BeanPostProcessor的使用

    spring中实现BeanPostProcessor的后置处理器 ApplicationContextAwareProcessor 进入该实现类内部 可以看到:该类帮我们组建IOC容器,判断我们的be ...

  8. Spring中的BeanPostProcessor

    一.何谓BeanProcessor BeanPostProcessor是SpringFramework里非常重要的核心接口之一,我先贴出一段源代码: /* * Copyright 2002-2015 ...

  9. 通过BeanPostProcessor理解Spring中Bean的生命周期

    通过BeanPostProcessor理解Spring中Bean的生命周期及AOP原理 Spring源码解析(十一)Spring扩展接口InstantiationAwareBeanPostProces ...

随机推荐

  1. SpringBoot 全局异常处理 @RestControllerAdvice +@ExceptionHandler 请求参数校验

    ControllerAdvice 指示带注释的类辅助“控制器”. 作为的特殊化@Component,允许通过类路径扫描自动检测实现类. 通常用于定义@ExceptionHandler, @InitBi ...

  2. 玩转 React(五)- 组件的内部状态和生命周期

    文章标题总算是可以正常一点了-- 通过之前的文章我们已经知道:在 React 体系中所谓的 "在 JavaScript 中编写 HTML 代码" 指的是 React 扩展了 Jav ...

  3. python小白入门

    阅读目录 一python介绍 二安装python解释器 三第一个python程序 四变量 五用户与程序交互 六基本数据类型 七格式化输出 八基本运算符 九流程控制之if...else 十流程控制之wh ...

  4. 详细解析kafka之kafka分区和副本

    本篇主要介绍kafka的分区和副本,因为这两者是有些关联的,所以就放在一起来讲了,后面顺便会给出一些对应的配置以及具体的实现代码,以供参考~ 1.kafka分区机制 分区机制是kafka实现高吞吐的秘 ...

  5. scrapy-redis分布式爬取知乎问答,使用docker布置多台机器。

    先上结果: 问题: 答案: 可以看到现在答案文档有十万多,十万个为什么~hh 正文开始: 分布式爬虫应该是在多台服务器(A B C服务器)布置爬虫环境,让它们重复交叉爬取,这样的话需要用到状态管理器. ...

  6. flask 链接mysql数据库 小坑

    #config.py MYSQL_NAME = 'root' MYSQL_PASSWORD = 'zyms90bdcs' MYSQL_HOST = 'xxxx' MYSQL_POST = ' MYSQ ...

  7. mysql实现读写分离

    MySQL读写分离概述 1.读写分离介绍 对于目前单机运行MySQL服务.会导致MySQL连接数过多.最终导致mysql的宕机.因此可以使用多台MySQL服务器一起承担压力.考虑到项目中读写比例的不一 ...

  8. vue-router需要注意的点

    1.在编程式导航中,如果提供了path,params会被忽略:需要提供name,或手写完整的带有参数的path;以下写法可取: const  userId = '123'; 1.this.$route ...

  9. span(行级元素)在不定高的div(块级元素)中垂直居中的方法

    设置父级元素: align-items: center; display: flex;

  10. turtle学习笔记续集

    turtle(海龟)是Python重要的标准库之一,它能够进行基本的图形绘制.turtle图形绘制的概念诞生于1969年,成功应用于LOGO编程语言. turtle库绘制图形有一个基本框架:一个小海龟 ...