Spring-bean的生命周期-终篇

阶段8:Bean属性设置阶段

属性设置阶段分为3个小的阶段

  • 实例化后阶段
  • Bean属性赋值前处理
  • Bean属性赋值

实例化后阶段
这里也有spring给我们预留了扩展,就是实现InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation方法,开发者实现这个接口,重写此方法可以了
源码:

for (BeanPostProcessor bp : getBeanPostProcessors()) {
    if (bp instanceof InstantiationAwareBeanPostProcessor) {
        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
        if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
            return;
        }
    }
}

postProcessAfterInstantiation 方法返回false的时候,后续的Bean属性赋值前处理、Bean属性赋值都会被跳过了。

spring源码位置:

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

来个案例,先建一个process

/**
 * @description: 设置赋值前,如果返回false将不会被赋值
 *
 * 会调用 InstantiationAwareBeanPostProcessor 接口的 postProcessAfterInstantiation 这个方
 * 法,调用逻辑如下:,
 * 后续的Bean属性赋值前处理、Bean
 * 属性赋值都会被跳过了。
 * @author: stone
 * @date: Created by 2021/3/25 20:25
 * @version: 1.0.0
 * @pakeage: com.shiguiwu.springmybatis.spring.lifecycle.setprop
 */
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

    /**
     * 后续的Bean属性赋值前处理、Bean
     *  属性赋值都会被跳过了。
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
//        System.out.println("调用 MyInstantiationAwareBeanPostProcessor#postProcessAfterInstantiation");
        if ("pig1".equalsIgnoreCase(beanName)) {
            return false;
        }

        return true;
    }

再来一个spring bean

package com.shiguiwu.springmybatis.spring.lifecycle.definition;

import com.shiguiwu.springmybatis.spring.lifecycle.instance.MyAutowire;
import lombok.Data;

/**
 * @description: 小猪
 * @author: stone
 * @date: Created by 2021/3/17 14:08
 * @version: 1.0.0
 * @pakeage: com.shiguiwu.springmybatis.spring.lifecycle.definition
 */
@Data
public class Pig {

    private String name;
    private Integer age;

    private String description;

    public Pig() {
    }

    @MyAutowire
    public Pig(String name, Integer age) {
        System.out.println("增强候选注解@MyAutowire !!!!");
        this.name = name;
        this.age = age;
    }

    public Pig(String name, Integer age, String description) {
        this.name = name;
        this.age = age;
        this.description = description;
    }
}

测试案例如下:

public class InstancedTests {

    public static void main(String[] args) {
        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
        factory.addBeanPostProcessor(new MyInstantiationAwareBeanPostProcessor());

        BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Pig.class)
                .addPropertyValue("name", "猪八戒")
                .addPropertyValue("age", 30)
                .getBeanDefinition();

        BeanDefinition beanDefinition1 = BeanDefinitionBuilder.genericBeanDefinition(Pig.class)
                .addPropertyValue("name", "猪悟能")
                .addPropertyValue("age", 35)
                .getBeanDefinition();

        factory.registerBeanDefinition("pig", beanDefinition);
        factory.registerBeanDefinition("pig1", beanDefinition1);

        Arrays.stream(factory.getBeanDefinitionNames()).forEach(s -> System.out.println(factory.getBean(s)));

    }
}

打印结果

Connected to the target VM, address: '127.0.0.1:52046', transport: 'socket'
20:22:20.387 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'pig'
调用InstantiationAwareBeanPostProcessor #postProcessProperties
Pig(name=猪无能, age=12, description=null)
20:22:20.770 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'pig1'
Pig(name=null, age=null, description=null)
Disconnected from the target VM, address: '127.0.0.1:52046', transport: 'socket'

被指定的bean名称,跳过了属性赋值

Bean属性赋值前阶段
这个阶段,spring照样为开发者预留了干涉spring bean赋值前阶段的操作,这个阶段会调用 InstantiationAwareBeanPostProcessor 接口的postProcessProperties 方法,调
用逻辑:
代码如下:

for (BeanPostProcessor bp : getBeanPostProcessors()) {
    if (bp instanceof InstantiationAwareBeanPostProcessor) {
        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
        PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
        if (pvsToUse == null) {
            if (filteredPds == null) {
                filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
            }
            pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds,
                    bw.getWrappedInstance(), beanName);
            if (pvsToUse == null) {
                return;
            }
        }
        pvs = pvsToUse;
    }
}

从上面可以看出,如果 InstantiationAwareBeanPostProcessor 中的
postProcessProperties 和 postProcessPropertyValues 都返回空的时候,表示这个bean不
需要设置属性,直接返回了,直接进入下一个阶段。

来看一下 postProcessProperties 这个方法的定义:

@Nullable
default PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
    return pvs;
}

PropertyValues中保存了bean实例对象中所有属性值的设置,所以我们可以在这个这个方法中对PropertyValues值进行修改

示例代码如下:

@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
    System.out.println("调用InstantiationAwareBeanPostProcessor #postProcessProperties");
    if (beanName.equals("pig")) {
        if (pvs==null) {
            pvs = new MutablePropertyValues();
        }
        if (pvs instanceof MutablePropertyValues) {
            MutablePropertyValues pv = (MutablePropertyValues) pvs;
            //偷梁换柱,给属性辅助
            pv.add("name", "猪无能");
            pv.add("age", 12);
        }
    }
    return null;
}

Bean属性赋值阶段
这个过程比较简单了,循环处理 PropertyValues 中的属性值信息,通过反射调用set方法将属性的值设置到bean实例中。
PropertyValues中的值是通过bean xml中property元素配置的,或者调用MutablePropertyValues中add方法设置的值。


阶段9:Bean初始化阶段

这个阶段分为5个小的阶段

  • Bean Aware接口回调
  • Bean初始化前操作
  • Bean初始化操作
  • Bean初始化后操作
  • Bean初始化完成操作

Bean Aware接口回调,这里也是spring给我们的扩展
这块的源码:

private void invokeAwareMethods(final String beanName, final Object bean) {
    if (bean instanceof Aware) {
        if (bean instanceof BeanNameAware) {
            ((BeanNameAware) bean).setBeanName(beanName);
        }
        if (bean instanceof BeanClassLoaderAware) {
            ClassLoader bcl = getBeanClassLoader();
            if (bcl != null) {
                ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
            }
        }
        if (bean instanceof BeanFactoryAware) {
            ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
        }
    }
}

如果我们的bean实例实现了上面的接口,会按照下面的顺序依次进行调用:

BeanNameAware:将bean的名称注入进去
BeanClassLoaderAware:将BeanClassLoader注入进去
BeanFactoryAware:将BeanFactory注入进去

来一个实现这三个接口的类:

/**
 * @description: 三个接口
 * @author: stone
 * @date: Created by 2021/3/28 11:54
 * @version: 1.0.0
 * @pakeage: com.shiguiwu.springmybatis.spring.lifecycle.init
 */
public class MyAware implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware {
    @Override
    public void setBeanName(String name) {
        System.out.println("beanName:" + name);

    }


    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        System.out.println("classLoader:" + classLoader);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("beanFactory:" + beanFactory);
    }
}

测试代码:

package com.shiguiwu.springmybatis.spring.lifecycle.init;

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;

/**
 * @description: 9.1初始化-aware接口回调
 * @author: stone
 * @date: Created by 2021/3/28 11:51
 * @version: 1.0.0
 * @pakeage: com.shiguiwu.springmybatis.spring.lifecycle.init
 */
public class AwareTests {

    public static void main(String[] args) {
        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
        BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(MyAware.class).getBeanDefinition();
        factory.registerBeanDefinition("myAware", beanDefinition);
        System.out.println(factory.getBean(MyAware.class));

    }
}

输出信息

Connected to the target VM, address: '127.0.0.1:55707', transport: 'socket'
22:21:14.221 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'myAware'
beanName:myAware
classLoader:sun.misc.Launcher$AppClassLoader@18b4aac2
beanFactory:org.springframework.beans.factory.support.DefaultListableBeanFactory@6c3f5566: defining beans [myAware]; root of factory hierarchy
com.shiguiwu.springmybatis.spring.lifecycle.init.MyAware@71248c21
Disconnected from the target VM, address: '127.0.0.1:55707', transport: 'socket'

Bean初始化前操作,spring给开发者的扩展
这个阶段的源码:

@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
    Object result = existingBean;
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
        Object current = processor.postProcessBeforeInitialization(result, beanName);
        if (current == null) {
            return result;
        }
        result = current;
    }
    return result;
}

会调用 BeanPostProcessor的postProcessBeforeInitialization 方法,若返回null,当前方法将结束。
通常称postProcessBeforeInitialization这个方法为:bean初始化前操作。
这个接口有2个实现类,比较重要,画重点:

org.springframework.context.support.ApplicationContextAwareProcessor
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor

ApplicationContextAwareProcessor注入6个Aware接口对象
如果bean实现了下面的接口,在ApplicationContextAwareProcessor#postProcessBeforeInitialization 中会依次调用下面接口中的方法,将 Aware 前缀对应的对象注入到bean实例中。

EnvironmentAware:注入Environment对象
EmbeddedValueResolverAware:注入EmbeddedValueResolver对象
ResourceLoaderAware:注入ResourceLoader对象
ApplicationEventPublisherAware:注入ApplicationEventPublisher对象
MessageSourceAware:注入MessageSource对象
ApplicationContextAware:注入ApplicationContext对象

从名称上可以看出这个类以 ApplicationContext 开头的,说明这个类只能在 ApplicationContext 环境中使用。

CommonAnnotationBeanPostProcessor调用@PostConstruct标注的方法
CommonAnnotationBeanPostProcessor#postProcessBeforeInitialization 中会调用bean中所有标注@PostConstruct注解的方法
整体来个案例

package com.shiguiwu.springmybatis.spring.lifecycle.init;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.StringValueResolver;

import javax.annotation.PostConstruct;

/**
 * @description: 初始化前操作
 * @author: stone
 * @date: Created by 2021/3/28 12:06
 * @version: 1.0.0
 * @pakeage: com.shiguiwu.springmybatis.spring.lifecycle.init
 */
public class BeforeBean implements EnvironmentAware, EmbeddedValueResolverAware,
        ResourceLoaderAware, ApplicationEventPublisherAware, MessageSourceAware,
        ApplicationContextAware {

    @PostConstruct
    public void postConstruct1() {
        System.out.println("postConstruct1");
    }


    @PostConstruct
    public void postConstruct2() {
        System.out.println("postConstruct2");
    }


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("applicationContext:" + applicationContext);
    }

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        System.out.println("applicationEventPublisher:" + applicationEventPublisher);
    }

    @Override
    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        System.out.println("resolver:" + resolver);
    }

    @Override
    public void setEnvironment(Environment environment) {
        System.out.println("environment:" + environment);
    }

    @Override
    public void setMessageSource(MessageSource messageSource) {
        System.out.println("messageSource:" + messageSource);
    }

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        System.out.println("resourceLoader:" + resourceLoader);
    }
}

测试代码如下:

package com.shiguiwu.springmybatis.spring.lifecycle.init;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @description: 9.2初始化前
 * @author: stone
 * @date: Created by 2021/3/28 12:04
 * @version: 1.0.0
 * @pakeage: com.shiguiwu.springmybatis.spring.lifecycle.init
 */
public class BeforeInitTests {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext factory = new AnnotationConfigApplicationContext();
//        BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(BeforeBean.class).getBeanDefinition();
//        factory.("beforeBean", beanDefinition);
        factory.register(BeforeBean.class);
        factory.refresh();
        System.out.println(factory.getBean(BeforeBean.class));
    }
}

打印结果

environment:StandardEnvironment {activeProfiles=[], defaultProfiles= ...
resolver:org.springframework.beans.factory.config.EmbeddedValueResolver@3a52dba3
resourceLoader:org.springframework.context.annotation.AnnotationConfigApplicationContext@11438d26, started on Tue Nov 02 22:59:30 CST 2021
applicationEventPublisher:org.springframework.context.annotation.AnnotationConfigApplicationContext@11438d26, started on Tue Nov 02 22:59:30 CST 2021
messageSource:org.springframework.context.annotation.AnnotationConfigApplicationContext@11438d26, started on Tue Nov 02 22:59:30 CST 2021
applicationContext:org.springframework.context.annotation.AnnotationConfigApplicationContext@11438d26, started on Tue Nov 02 22:59:30 CST 2021
postConstruct1
postConstruct2
com.shiguiwu.springmybatis.spring.lifecycle.init.BeforeBean@610f7aa

大家可以去看一下AnnotationConfigApplicationContext的源码,其内部会添加很多
BeanPostProcessor 到 DefaultListableBeanFactory 中。


Bean初始化阶段
2个步骤

  1. 调用InitializingBean接口的afterPropertiesSet方法
  2. 调用定义bean的时候指定的初始化方法
    调用InitializingBean接口的afterPropertiesSet方法
public interface InitializingBean {
    public void afterPropertiesSet() throws Exception;
}

当我们的bean实现了这个接口的时候,会在这个阶段被调用
调用bean定义的时候指定的初始化方法
方式1:xml方式指定初始化方法

<bean init-method="bean中方法名称"/>

方式2:@Bean的方式指定初始化方法

@Bean(initMethod = "初始化的方法")

方式3:api的方式指定初始化方法

this.beanDefinition.setInitMethodName(methodName);

初始化方法最终会赋值给下面这个字段

org.springframework.beans.factory.support.AbstractBeanDefinition#initMethodName

案例如下:

package com.shiguiwu.springmybatis.spring.lifecycle.init;

import org.springframework.beans.factory.InitializingBean;

/**
 * @description: 初始化bean
 * @author: stone
 * @date: Created by 2021/3/28 13:04
 * @version: 1.0.0
 * @pakeage: com.shiguiwu.springmybatis.spring.lifecycle.init
 */
public class InitializeBean implements InitializingBean {

    public void init() {
        System.out.println("初始化方法!!!!");

    }
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("afterPropertiesSet");

    }
}

测试代码

package com.shiguiwu.springmybatis.spring.lifecycle.init;

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;

/**
 * @description: 9.3初始化阶段
 * @author: stone
 * @date: Created by 2021/3/28 13:02
 * @version: 1.0.0
 * @pakeage: com.shiguiwu.springmybatis.spring.lifecycle.init
 */
public class InitializeTests {

    public static void main(String[] args) {
        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
        BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(InitializeBean.class).getBeanDefinition();
        beanDefinition.setInitMethodName("init");
        factory.registerBeanDefinition("initializeBean", beanDefinition);
        System.out.println(factory.getBean(InitializeBean.class));
    }
}

输出结果

23:09:16.350 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory 
afterPropertiesSet
初始化方法!!!!
com.shiguiwu.springmybatis.spring.lifecycle.init.InitializeBean@221af3c0
'socket'

调用顺序:InitializingBean中的afterPropertiesSet、然后在调用自定义的初始化方法


Bean初始化后阶段

public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
    Object result = existingBean;
    Object current;
    for(Iterator iterator = this.getBeanPostProcessors().iterator(); iterator.hasNext(); result = current) {
        BeanPostProcessor processor = (BeanPostProcessor)iterator.next();
        current = processor.postProcessAfterInitialization(result, beanName);
        if (current == null) {
            return result;
        }
    }
    return result;
}

调用 BeanPostProcessor接口的postProcessAfterInitialization方法 ,返回null的时候,会中断上面的操作,注意这里也是扩展哦
通常称postProcessAfterInitialization这个方法为:bean初始化后置操作。
来个案例

public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("bean :" + beanName);
        System.out.println("初始化后》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》");
        return bean;
    }
}

测试代码

package com.shiguiwu.springmybatis.spring.lifecycle.init;

import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;

/**
 * @description: 9.4初始化后阶段
 * @author: stone
 * @date: Created by 2021/3/28 13:07
 * @version: 1.0.0
 * @pakeage: com.shiguiwu.springmybatis.spring.lifecycle.init
 */
public class AfterInitializeTests {
    public static void main(String[] args) {
        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
        //叫一个初始化后处理器
        factory.addBeanPostProcessor(new MyBeanPostProcessor());

        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(String.class)
                .addConstructorArgValue( "shiguiwu")
                .getBeanDefinition();

        AbstractBeanDefinition beanDefinition1 = BeanDefinitionBuilder.genericBeanDefinition(Integer.class)
                .addConstructorArgValue(15)
                .getBeanDefinition();

        factory.registerBeanDefinition("shiguiwuabc", beanDefinition);
        factory.registerBeanDefinition("shiguiwuA", beanDefinition1);

        System.out.println(factory.getBean(String.class));
        System.out.println(factory.getBean(Integer.class));
    }
}

输出结果

Connected to the target VM, address: '127.0.0.1:56910', transport: 'socket'
23:20:37.770 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'shiguiwuabc'
bean :shiguiwuabc
初始化后》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
shiguiwu
23:20:38.099 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'shiguiwuA'
bean :shiguiwuA
初始化后》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
15
Disconnected from the target VM, address: '127.0.0.1:56910', transport: 'socket'

Process finished with exit code 0

此致,终篇完毕,内容有点,希望能好好消化,接下来就是尾篇。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值