架构のSpring扩展点(三):Bean生命周期操作-InstantiationAwareBeanPostProcessor

作者简介:大齐,自学Java入门,现在某国企担任初级架构师

 有自己独立的学习方法,以及适合大部分人的学习路线,面试架构思路等

关注公众号【大齐架构】,查看最新最全的知识分享

Spring 的扩展点 是Spring易扩展的一个重要体现,熟悉这些扩展点的定义方式,以及其调用时机,不仅成为工作中利器,也能深度理解Spring框架的切入点。

InstantiationAwareBeanPostProcessor扩展点 

InstantiationAwareBeanPostProcessor用途

InstantiationAwareBeanPostProcessor接口扩展了BeanPostProcessor子接口,提供了Bean被实例化之前、Bean实例化之后、Bean属性装配前更细粒度控制Bean创建流程的处理。

查看Sprng源码接口上的注解:

/**
 * BeanPostProcessor接口的子接口,它添加了一个在实例化之前的回调,以及一个在实例化后但在显式属性设置或自动装配之前的回调。
 * 通常用于特定目标bean的默认实例化
 * Subinterface of {@link BeanPostProcessor} that adds a before-instantiation callback,
 * and a callback after instantiation but before explicit properties are set or
 * autowiring occurs.

 * 例如使用特殊的 TargetSource 创建代理(例如池化目标、延迟初始化目标等),
 * 或实现其他类型的注入策略,例如字段注入
 * 

Typically used to suppress default instantiation for specific target beans, * for example to create proxies with special TargetSources (pooling targets, * lazily initializing targets, etc), or to implement additional injection strategies * such as field injection. */ public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {


InstantiationAwareBeanPostProcessor可实现的方法如下:

架构のSpring扩展点(三):Bean生命周期操作-InstantiationAwareBeanPostProcessor_第1张图片

postProcessPropertyValues()Spring5.1版本后被弃用

来源

org.springframework.beans它是由Spring本身提供的容器级别的接口。

InstantiationAwareBeanPostProcessor方法

主要的扩展点有以下5个方法,在bean生命周期的两大阶段:实例化阶段初始化阶段,按调用顺序为:

  • postProcessBeforeInstantiation:实例化bean之前,相当于new这个bean之前

  • postProcessAfterInstantiation:实例化bean之后,相当于new这个bean之后,属性注入前触发执行

  • postProcessPropertiess:bean已经实例化完成,在属性注入时阶段触发,@Autowired,@Resource等注解原理基于此方法实现

  • postProcessBeforeInitialization:初始化bean之前,相当于把bean注入spring上下文之前

  • postProcessAfterInitialization:初始化bean之后,相当于把bean注入spring上下文之后

BeanPostProcess接口只在bean的初始化阶段进行扩展(注入spring上下文前后)

InstantiationAwareBeanPostProcessor接口在此基础上增加了3个方法,把可扩展的范围增加了实例化阶段和属性注入阶段。

自定义实现方式

InstantiationAwareBeanPostProcessor扩展点的实现方式很简单,实现接口,重写相应的方法实现扩展逻辑。

@Component
@Slf4j
public class ExampleComponent implements InitializingBean {
    public ExampleComponent() {
        log.info("----ExampleComponent无参构造方法被执行");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        log.info("----ExampleComponent被初始化");
    }
}
@Service
@Slf4j
public class ExampleService {

    private String userName="大齐架构";
    private ExampleComponent exampleComponent;
    
    public ExampleService() {
        log.info("----ExampleService无参构造方法被执行");
    }
    @Autowired
    public void setExampleService(ExampleComponent exampleComponent) {
        this.exampleComponent = exampleComponent;
        log.info("----ExampleService内的exampleComponent属性被注入");
    }

    public void setUserName(String userName) {
        this.userName = userName;
        log.info("----ExampleService内的userName属性被注入");
    }
    public String getUserName() {
        return userName;
    }
}

ExampleService 代码

@Component
@Slf4j
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
    @SneakyThrows
    @Override
    public Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException {
        if (beanName.equals("exampleService")) {
            log.info("----postProcessBeforeInstantiation被执行:" + beanName);
            return null;
        }
        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if (beanName.equals("exampleService")) {
            log.info("----postProcessAfterInstantiation被执行:" + beanName);
        }
        return true;
    }

    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        if (beanName.equals("exampleService")) {
            log.info("----postProcessProperties被执行:" + beanName);
            MutablePropertyValues mutablePropertyValues=new MutablePropertyValues();
            mutablePropertyValues.addPropertyValue("userName","李四");
            pvs=mutablePropertyValues;
        }
        return pvs;
    }
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("exampleService")) {
            log.info("----postProcessBeforeInitialization---" + beanName);
            //如果特定的bean实例化完成后,还未执行InitializingBean.afterPropertiesSet()方法之前,有一些其他操作,可以在这里实现
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("exampleService")) {
            log.info("----postProcessAfterInitialization---" + beanName);
            //如果特定的bean实例化完成,InitializingBean.afterPropertiesSet()方法执行后,有一些其他操作,可以在这里实现
        }
        return bean;
    }

}

MyInstantiationAwareBeanPostProcessor 代码
 

@Test
    public void test() {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.rfq");
        ExampleService bean = context.getBean(ExampleService.class);
        Assert.isTrue("李四".equals(bean.getUserName()), "属性替换失败");
        log.info("----" + bean.getUserName());
    }

单元测试代码

 c.r.s.component.ExampleComponent         : ----ExampleComponent无参构造方法被执行
 c.r.s.component.ExampleComponent         : ----ExampleComponent被初始化
 .p.MyInstantiationAwareBeanPostProcessor : ----postProcessBeforeInstantiation被执行:exampleService
 c.rfq.springtest.service.ExampleService  : ----ExampleService无参构造方法被执行
 .p.MyInstantiationAwareBeanPostProcessor : ----postProcessAfterInstantiation被执行:exampleService
 .p.MyInstantiationAwareBeanPostProcessor : ----postProcessProperties被执行:exampleService
 c.rfq.springtest.service.ExampleService  : ----ExampleService内的exampleComponent属性被注入
 c.rfq.springtest.service.ExampleService  : ----ExampleService内的userName属性被注入
 .p.MyInstantiationAwareBeanPostProcessor : ----postProcessBeforeInitialization---exampleService
 .p.MyInstantiationAwareBeanPostProcessor : ----postProcessAfterInitialization---exampleService
 c.r.s.rfqtest.RfqTestApplicationTests    : ----李四

控制台输出结果

工作原理

注册时机

因为InstantiationAwareBeanPostProcessor接口继承于BeanPostProcessor接口,所以InstantiationAwareBeanPostProcessor接口的实现类的注册时机和BeanPostProcessor是一致的。

  1. 应用启动后进入,AbstractApplicationContext#refresh()方法中

    架构のSpring扩展点(三):Bean生命周期操作-InstantiationAwareBeanPostProcessor_第2张图片

  2. refresh方法中调用registerBeanPostProcessors最终用交由类PostProcessorRegistrationDelegate#registerBeanPostProcessors的方法进行注

    架构のSpring扩展点(三):Bean生命周期操作-InstantiationAwareBeanPostProcessor_第3张图片

  3. 获取所有实现BeanPostProcessor接口的实现类的名称

  4. 架构のSpring扩展点(三):Bean生命周期操作-InstantiationAwareBeanPostProcessor_第4张图片

  5. 把所有的BeanPostProcessor接口的实现类,按照是否实现PriorityOrdered接口、是否实现Ordered接口、其他三种筛选条件进行分类

  6. 最终将所有的BeanPostProcessor接口的实现类注册到工厂BeanFactory

     近期文章精选(关注公众号大齐架构,获取更多精彩知识)

    架构のSpring扩展点(一):上下文创建前的动态处理-ApplicationContextInitializer

    架构のSpring扩展点(二):Bean定义操作-BeanDefinitionRegistryPostProcessor

    架构のSpring扩展点(四):Bean初始化时对象自动注入-Aware全解析

    架构のSpring扩展点(五):如何保证在同一线程内获取的bean是同一对象-自定义Scope

    架构のSpring扩展点(六):ApplicationContextAwareProcessor接口全解析,看完就懂

    认知结构的提升,需要合适的思考方法-架构提升

    架构のSpring扩展点(一):上下文创建前的动态处理-ApplicationContextInitializer

    认知结构的提升,需要合适的思考方法-架构提升

你可能感兴趣的:(Spring扩展点,java,开发语言)