《spring设计思想》16-bean初始化阶段的自定义初始方法

上面两节14:讲了initializeBean中的第一步invokeAwareMethods

15:讲了initializeBean中的第二步,applyBeanPostProcessorsBeforeInitialization

这节我们讲一下第三步,invokeInitMethods

	/**
	 * Give a bean a chance to react now all its properties are set,
	 * and a chance to know about its owning bean factory (this object).
	 * This means checking whether the bean implements InitializingBean or defines
	 * a custom init method, and invoking the necessary callback(s) if it does.
	
	 * 给bean自己一个回调的机会,这个时候所有的属性都被设置了,因为执行过populateBean了
	 */
	protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
			throws Throwable {

		boolean isInitializingBean = (bean instanceof InitializingBean);
		// 真正调用的方法
		((InitializingBean) bean).afterPropertiesSet();
		
        //调用在BeanDefinition中定义的initMethod方法
		if (mbd != null && bean.getClass() != NullBean.class) {
			String initMethodName = mbd.getInitMethodName();
			if (StringUtils.hasLength(initMethodName) &&
					!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
					!mbd.isExternallyManagedInitMethod(initMethodName)) {
				invokeCustomInitMethod(beanName, bean, mbd);
			}
		}
	}

简单的看,代码就两个处理,一个是判断bean是否继承了InitializingBean,如果继承的话,调用bean的afterPropertiesSet方法,第二个是判断BeanDefintition中有没有自定义初始化方法,如果有的话,执行。

我们分别来看下demo

public class UserHolder implements InitializingBean {


    private int age;

    private String name;

    private String descript;

    public int getAge() {
        return age;
    }

    public UserHolder setAge(int age) {
        this.age = age;
        return this;
    }

    public String getName() {
        return name;
    }

    public UserHolder setName(String name) {
        this.name = name;
        return this;
    }

    public String getDescript() {
        return descript;
    }

    public UserHolder setDescript(String descript) {
        this.descript = descript;
        return this;
    }

    @Override
    public String toString() {
        return "UserHolder{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", descript='" + descript + '\'' +
                '}';
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("initializeBean方法中调用  invokeInitMethods,执行 InitializingBean的回调方法 afterPropertiesSet方法");
        this.descript = "经过invokeInitMethods 的方法回调,我们又变样了";
    }
}

UserHolder继承了 InitializingBean接口,实现方法afterPropertiesSet方法,输出一行文字,因为之前的例子已经在xml中配置了userHolder,

《spring设计思想》16-bean初始化阶段的自定义初始方法_第1张图片

直接执行测试用例:

 

发现属性已经被更改掉了。

现在看第二个BeanDefinition中定义的方法,要配置BeanDefinition中的initMethod需要两个途径,一个是xml配置,一个是注解配置

我们先看xml配置:

新增了配置init-method属性,在UserHolder中的自定义方法initMethod

执行测试用例

第二种注解自定义初始化方法,因为BeanFactory是无法实现注解的读取,需要使用AnnotationConfigApplicationContext;

@Configuration
public class AnnotationedBeanLifyCycleInBeanFactoryDemo {


    @Bean(initMethod = "initMethod")
    public UserHolder userHolder(){
        return new UserHolder();
    }

    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        applicationContext.register(AnnotationedBeanLifyCycleInBeanFactoryDemo.class);
        applicationContext.refresh();

        applicationContext.getBean(UserHolder.class);

        applicationContext.close();
    }
}

在@Bean中自定义初始化方法,

输出:

如果去掉initMethod注解。输出

以上就是本节的主要内容,下一节讲一下initializeBean的最后一个方法 applyBeanPostProcessAfterInitializarion

你可能感兴趣的:(spring)