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

    技术2022-07-12  72

    上面两节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,

    直接执行测试用例:

     

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

    现在看第二个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

    Processed: 0.013, SQL: 9